Please help! How to make multiple objects with animations and transitions?

Hi!
I’m making a shooting game where the hero is on the ground shooting at air enemies.

The enemies consist of a helicopter flying across the screen and out jumps several parachuters that then glides down to the ground. The hero has to kill the parachuter before it hits the ground, otherwise the parachuter lands, throws a grenade on the fence and then runs away.

The parachuter has 4 animation stages:

  1. Opening the parachute
  2. Removing the parachute while landing
  3. Throwing a grenade
  4. Running

This is how it looks like right now:
http://www.youtube.com/watch?v=q7gdtUQBGuA

For now I’ve solved the different stages like this:

First I make an object (1) with physics that just falls to the ground. I’ve set up a platform that catches the object (1), removes and nil it and then make another object (2) also with physics that falls a little bit more and then got caught up by a second platform that removes and nil it and then makes object (3) that just transition on the spot, then onComplete it calls another function that makes object (4) and transition it out of screen then removes and nil it.

When the hero shoots on the parachuter, object (1) should be removed and nil. The hero can only hit when the parachuter is falling, eg. object (1).

The problem I’m having is that I can’t nil the parachuter when I shoot it, then I get the error message:

main.lua:497: attempt to index field 'other' (a nil value)

It seems like when I make several parachuters (objects) on the same time they get the same “id” or something. The big problem is that I don’t know how to handle this whole problem. How should I do?

I’m willing to offer payment if someone can show me a solution to the whole scenario above; from making several parachuters in some sort of for-loop, to be catched up on a platform, to the transition-process.

Best regards,
joelwe [import]uid: 54640 topic_id: 27600 reply_id: 327600[/import]

I think if you publish some of your code, just where you create those parachuters or lines above 497 (but i assume that they are the same lines), would be easier to help.

PS: Do you create each parachuter with the same variable? [import]uid: 116842 topic_id: 27600 reply_id: 112095[/import]

Couldn’t you just use sprites with self assigned object.state to create a state machine? Instead of using the physics library, which by the way is an unnecessary resource hog if you’re not creating a physics game, you could just check the coordinates of the sprites to see if they have reached the ground.

A simple state machine would be:
spawn sprites
-> play spawn sequence
-> on sequence end play descending sequence, set state to descending
-> if descending
=>sprite:translate(0,speedY*deltaTime*0.001)
=>if hit by bullet, play death sequence, kill on sequence end (sprite.sprite = killFunction; sprite:addEventListener(“sprite”, sprite))
=> if reached ground coordinate, play grenade throwing sequence, change state to grenade lobbing
-> if lobbing grenade
=>if grenade lobbing sequence ended, change state to running off screen
-> if running off screen:
=>play running sequence
=> sprite:translate(speedX*deltaTime*0.001,0)

[import]uid: 108204 topic_id: 27600 reply_id: 112121[/import]

Instead of importing the physics library just to throw grenades, use these equations instead:
http://wiki.answers.com/Q/What_are_the_kinematic_equations. Simple and effective. Reduces the size of your app too. [import]uid: 108204 topic_id: 27600 reply_id: 112122[/import]

Hi!
I’m sorry for late reply, but I’ve had loads of work. I’ve tried to change my code now, but I still get the same error message.

Here is some of my code:

http://pastebin.com/qnQBhKCX

When I kill a parachuter, it get killed, but I get this error message:

Runtime error ...e/main.lua:514: attempt to index field 'other' (a nil value) stack traceback: [C]: ? ...er/main.lua:514: in function <...er><br> ?: in function <?:218><br>

Line 514 is this (135 on pastebin):
if (self.name == "bullet" and event.other.name == "copter") then

Line 457 is this (99 on pastebin):
function onCollision(self, event)

TimeSpaceMagic:
I need the physics so that the parachuters, bombs etc. fall down in a realistic way. The grenade explosions are just randomly placed; the grenade throw is just an animation.

I would love if you guys could check out my code! It’s not good though, but I’m just learning :slight_smile:

Best regards,
joelwe
[import]uid: 54640 topic_id: 27600 reply_id: 112566[/import] </…er>

To make a fast debug, you can do:

print("event.other.name: "…event.other.name)

before the that if.

Well, nothing:
event.other:removeSelf()
event.other = nil

You should use “else if” instead of other if. This is because you make it nil, and after you ask for him. It doesn’t exist. [import]uid: 116842 topic_id: 27600 reply_id: 112585[/import]

I see the problem.

Remember that there are multiple event phases in physics collisions, such as when it began and when it ended.

You’re testing on the first phase (“began”) of the collision, which is fine. But when you delete the parachuter (“event.other”), then second phase of the collision event happens as the self object is no longer in collision (“ended”).

A quick way of handling it is wrapping the whole if/then structure inside of a quick test to see if both objects are still there:

if self ~= nil and event.other ~= nil then (your code) end

Or, you can also add the test of the event phase like this:

if event.phase == "began" and (self.name == "bullet" and event.other.name == "para") then ...

See if that works and let me know. [import]uid: 6084 topic_id: 27600 reply_id: 112606[/import]

Hi!
Thanks for your replies correogracioso and BeyondtheTech! The elseif solved that problem!
I’ve tried to structure my code up, and with that came new problems. Before the structuring, I had made a solution that when the parachuter glider hit a platform, it deleted itself and then I made a new object[i] where >>i<< increased for every new parachuter, eg. a global table.

So, the parachuter first glides >> hits platform >> deletes itself >> makes a new object, paralanding[i] >> keeps falling >> hits a second platform >> deletes itself >> makes a new object, soldierfrag[i], with the same global i >> performs the grenade throw animation >> deletes itself >> makes a new object, soldierrun[i], with the same global i >> performs the running animation, transitions over the screen, then deletes itself.

This worked, but I don’t think it’s the right way to go…

This is the new code (with the platforms included):
http://pastebin.com/Cvhs9E9k

When I run this, if for example 3 parachuters jump on the same time, the first parachuter performs the whole sequence (gliding, landing, throwing and running). But the second and third only glides, lands and throws, then I get this error message:

Runtime error ...er/main.lua:936: attempt to index global 'soldierFrags' (a nil value) stack traceback: [C]: ? ...er/main.lua:936: in function 'goFrag' ...er/main.lua:960: in function '\_listener' ?: in function <?:517> ?: in function <?:218>

Row 936 is row 467 on pastebin.

IIt seems like the parachuters that are created in the function goParas() (row 230) get the same id or something, because when the first soldierFrags object get niled, the rest are affected by it. If I set paraNum = 1 (row 232), so that only 1 parachuter jump every time, I don’t get any errors. Do I have to use my previous solution to make this work? Or is it something that I have missed?

Best regards,
joelwe [import]uid: 54640 topic_id: 27600 reply_id: 112960[/import]

YEEEEEES! I finally did it! :smiley: I found what was wrong!! It was all in the soldierRun() function! I just changed “soldierFrags” to self and then everything just magically worked! Man, this problem has been screwing with me for months! I was about to give up! Thank you everyone for the feedback!

[code]
function onCatchPlatformCollision2(self, event)
if event.other.name == “paraLander” then
–Create running soldier animation
function soldierRun(self)
local thetime = tonumber(soldierFrags.x/0.128)

soldierRuns = getSoldierRun()
soldierRuns.x = self.x
soldierRuns.y = self.y

soldierRuns.xScale = 130/195
soldierRuns.yScale = 120/179
soldierRuns:play()

transition.to( soldierRuns, { time=thetime, alpha=1, x=-20, onComplete = function(self) self.parent:remove(self); self = nil; end } )
if self ~= nil then
self:removeSelf()
self = nil
end
end

–A grenade explosion appears on a randomly distance from the soldier
function goFrag()

– Sets random throw hit
stringX = math.random(130, 170)
stringY = math.random(10, 20)

–Removes 1HP from healthbar
health = health - 1;
myScore = myScore -1
t.text = myScore…"%";
moveHealth()

–Plays explosion sound
if mute == 1 then
audio.play(sounds.explode3)
end

local throwFrag = getFrag()
throwFrag.x = soldierFrags.x-stringX
throwFrag.y = soldierFrags.y-stringY
throwFrag.xScale = 260/395
throwFrag.yScale = 283/429

–Removes itself after animation
local function RemoveObj(self)
local obj=self
obj:removeSelf()
obj = nil
end
transition.to(throwFrag, { time=600, onComplete= RemoveObj})

end

–Starting an animation where the soldier throws a grenade
soldierFrags = getSoldierFrag()
soldierFrags.x = event.other.x-20
soldierFrags.y = event.other.y+40
soldierFrags.xScale = 130/195
soldierFrags.yScale = 120/179

–After the throw the goFrag() starts
local fragTimer = timer.performWithDelay( 1200, function() goFrag() end, 1)

–When the animation is over, the soldierRun() function is called
local solderTimer = transition.to( soldierFrags, { time=1200, alpha=1, onComplete=soldierRun } )

–Removes the parachuter’s landing animation-object
if event.other ~= nil then
event.other:removeSelf()
event.other = nil
end
end
end
[/code] [import]uid: 54640 topic_id: 27600 reply_id: 112965[/import]