Keeping Track of Individual Enemies Through Time Delays

function randomPaths:newPath(object) local random = math.ceil(math.random() \* 1) --random number from 1 to 10 print(random) if random == 1 then local flyInTime = 1500 local initfaceShipTime = 100 local faceShipTime = 2000 local flyOutTime = 1000 translateEnemy(object, {414.5,217.5}, {-81.5,150}, flyInTime, easing.outCubic) --move enemy into screen timer.performWithDelay(flyInTime, function () transition.to(object, {time = initfaceShipTime, rotation = angleBetween(object.x, object.y, ship.x, ship.y) }) timer.performWithDelay(initfaceShipTime, function() shipRotateTimer = timer.performWithDelay(17, function() object.rotation = --after the enemy flies in have the enemy face the ship angleBetween( object.x, object.y, ship.x, ship.y ) end, 0) timer.performWithDelay(faceShipTime, function() timer.cancel(shipRotateTimer) -- cancel enemy facing the ship translateEnemy(object, {object.x,-100}, {object.y,object.y}, flyOutTime, easing.inCubic) --move enemy off the screen timer.performWithDelay(flyOutTime, function() display.remove(object); object = nil; end) --make the enemy nil after it has completed its path end) end) end) end 

I have this (admittedly messy) chunk of code whose purpose is to make my enemies fly around and it works fine for just one enemy, but gives me problems when I have more than one. At the end of the code block above, I make “object” nil and remove it from the display to avoid memory leaks. I call this block of code like this:

e = Enemy1:new(W/2, -250) randomPaths:newPath(e)

My code gives an error saying object is nil as soon as the first ship is set to nil. I know I am approaching this situation wrong, I assume all instances of this code are referencing the same “object” variable. What is the correct way to approach this problem of moving multiple enemies at once? How do I make the code keep track the multiple instances of enemies and keep their data separate from the other enemies?

Can anyone help me out here?

No, the object variable is unique to each instance of the closures that you make per call to newPath(), so it’s not that (though if e is global you might run into issues of that sort elsewhere). Setting object to nil is actually redundant here, since it goes out of scope at that point; you do still need to remove it from Corona, though.

Is there any call stack around your error message, nailing down one of the lines? object is a pretty common name, so perhaps you’ve used it elsewhere, say in translateEnemy().

The only-with-two-objects thing might be a red herring. My best guess is that there’s a subtle timing issue, where the transition happens after the timer, and still gets executed. If it turns out to be that, the easiest fix in this case would simply be to use display.remove() as the enemy transition’s onComplete handler and dispense with the final timer.

Can anyone help me out here?

No, the object variable is unique to each instance of the closures that you make per call to newPath(), so it’s not that (though if e is global you might run into issues of that sort elsewhere). Setting object to nil is actually redundant here, since it goes out of scope at that point; you do still need to remove it from Corona, though.

Is there any call stack around your error message, nailing down one of the lines? object is a pretty common name, so perhaps you’ve used it elsewhere, say in translateEnemy().

The only-with-two-objects thing might be a red herring. My best guess is that there’s a subtle timing issue, where the transition happens after the timer, and still gets executed. If it turns out to be that, the easiest fix in this case would simply be to use display.remove() as the enemy transition’s onComplete handler and dispense with the final timer.