Problem removing object from table and timer

Hello - 

I have been working on porting one of my games from another language to Corona.  So far I’ve managed to do the various scenes and am currently working on the game scene.  I’ve done the buttons (widgets), the player’s ship, which rotates, moves forward, wraps around the screen, and fires lasers.

I’m currently having some issues with the lasers.  The lasers are fired facing the ship’s rotation, move forward, and wrap around the screen.  Where I am currently stuck is in removing the laser.  Let’s say the timer for the laser’s removal is 1000ms.  If I fire one laser, said laser exists for one second, enough to wrap around y (top) twice with the current parameters.  If I fire a second laser within a second’s time (notice the timer value of 1000), the second laser disappears when it reaches the top of the screen; it does not wrap like the other.  If I wait a second or more, the next laser will perform like the first one.  In other words, a first laser (or laser salvo) will last the 1000ms, but the second laser (or laser salvo) will not make it past a screen edge if fired within 1000ms of the previous laser (or laser salvo).

Any pointers as to what’s wrong?  Wrong code?  Wrong placement?  Relevant code is nestled within gameLoop.  Thanks, regards.

BTW - the lasers are in a table so they can keep their own direction (rotation) and wrap around the screen accordingly.

local function gameLoop() -- Create new asteroid -- wrap lasers around screen for i = #laserTable, 1, -1 do local thisLaser = laserTable[i] if (thisLaser.x \> display.contentWidth + (fudgeNum \* .5)) then thisLaser.x = -(fudgeNum \* .5) else if (thisLaser.x \< -(fudgeNum \* .5)) then thisLaser.x = display.contentWidth + (fudgeNum \* .5) else if (thisLaser.y \< -(fudgeNum \* .5)) then thisLaser.y = display.contentHeight + (fudgeNum \* .5) else if (thisLaser.y \> display.contentHeight + (fudgeNum \* .5)) then thisLaser.y = -(fudgeNum \* .5) end end end end local function removeLaser() display.remove(thisLaser) table.remove(laserTable,i) end timer.performWithDelay ( 1000, removeLaser ) end end

If I fire a second laser within a second’s time (notice the timer value of 1000), the second laser disappears when it reaches the top of the screen; it does not wrap like the other.  If I wait a second or more, the next laser will perform like the first one.

The implication here is that the timer created for removing the first laser blast also removes the second laser blast. The fact that the second laser reaches the edge of the screen is probably incidental.

I have reformatted your code to check the ‘end’ statements and it looks like either you’ve not posted enough code or you’re not structuring the ‘if’ statements correctly…

local function gameLoop() -- Create new asteroid -- wrap lasers around screen for i = #laserTable, 1, -1 do local thisLaser = laserTable[i] if (thisLaser.x \> display.contentWidth + (fudgeNum \* .5)) then thisLaser.x = -(fudgeNum \* .5) elseif (thisLaser.x \< -(fudgeNum \* .5)) then thisLaser.x = display.contentWidth + (fudgeNum \* .5) elseif (thisLaser.y \< -(fudgeNum \* .5)) then thisLaser.y = display.contentHeight + (fudgeNum \* .5) elseif (thisLaser.y \> display.contentHeight + (fudgeNum \* .5)) then thisLaser.y = -(fudgeNum \* .5) end end end end -- ??? local function removeLaser() display.remove(thisLaser) table.remove(laserTable,i) end timer.performWithDelay ( 1000, removeLaser ) end end

I suspect that what you were going for is more along these lines…

local function gameLoop() -- Create new asteroid -- wrap lasers around screen for i = #laserTable, 1, -1 do local thisLaser = laserTable[i] if (thisLaser.x \> display.contentWidth + (fudgeNum \* .5)) then thisLaser.x = -(fudgeNum \* .5) elseif (thisLaser.x \< -(fudgeNum \* .5)) then thisLaser.x = display.contentWidth + (fudgeNum \* .5) elseif (thisLaser.y \< -(fudgeNum \* .5)) then thisLaser.y = display.contentHeight + (fudgeNum \* .5) elseif (thisLaser.y \> display.contentHeight + (fudgeNum \* .5)) then thisLaser.y = -(fudgeNum \* .5) end local function removeLaser() display.remove(thisLaser) table.remove(laserTable,i) end timer.performWithDelay ( 1000, removeLaser ) end end

The problem is that you’re removing all lasers each time the timer fires. If you’re creating a timer each time the laser is fired, why not just create it for that one laser - attach the timer() function to the laser object, call performWithDelay and pass the laser object as the parameter. That way the timer() function will get called on the laser object and it can remove itself.

If you go that route, you probably don’t need a table to manage the lasers, you can just rely on them being removed from their parent display group and more easily cease to exist.

Thanks for the reply and the code cleanup; much appreciated.

I tried creating a timer when I create the laser, but it still affects the next laser.  I’ll continue to work on the code to see if I reach the solution.

Just a thought - within the “for i = #laserTable, 1, -1 do” routine above, is there a way to add an if statement that would measure time since the thisLaser object was created?  That way, within this routine, which itself is within the gameLoop function, the code would determine which lasers have an existence of over 1000ms and then remove them?

How do I go about  attaching the timer() function to the laser object and passing the laser object as the parameter?  It sounds quite simple but I can’t figure it out from the API reference library, and am searching for an example but have yet to find one.  Thanks much.

Why don’t you give each “laser object” an ID and then use that for cleanup - either time-based or bounds-based?

What I would do is add in your table the start time (of the laser) and then cull based on start time + 1000ms < current time. Assuming the lifetime of a laser was 1 second.

If I fire a second laser within a second’s time (notice the timer value of 1000), the second laser disappears when it reaches the top of the screen; it does not wrap like the other.  If I wait a second or more, the next laser will perform like the first one.

The implication here is that the timer created for removing the first laser blast also removes the second laser blast. The fact that the second laser reaches the edge of the screen is probably incidental.

I have reformatted your code to check the ‘end’ statements and it looks like either you’ve not posted enough code or you’re not structuring the ‘if’ statements correctly…

local function gameLoop() -- Create new asteroid -- wrap lasers around screen for i = #laserTable, 1, -1 do local thisLaser = laserTable[i] if (thisLaser.x \> display.contentWidth + (fudgeNum \* .5)) then thisLaser.x = -(fudgeNum \* .5) elseif (thisLaser.x \< -(fudgeNum \* .5)) then thisLaser.x = display.contentWidth + (fudgeNum \* .5) elseif (thisLaser.y \< -(fudgeNum \* .5)) then thisLaser.y = display.contentHeight + (fudgeNum \* .5) elseif (thisLaser.y \> display.contentHeight + (fudgeNum \* .5)) then thisLaser.y = -(fudgeNum \* .5) end end end end -- ??? local function removeLaser() display.remove(thisLaser) table.remove(laserTable,i) end timer.performWithDelay ( 1000, removeLaser ) end end

I suspect that what you were going for is more along these lines…

local function gameLoop() -- Create new asteroid -- wrap lasers around screen for i = #laserTable, 1, -1 do local thisLaser = laserTable[i] if (thisLaser.x \> display.contentWidth + (fudgeNum \* .5)) then thisLaser.x = -(fudgeNum \* .5) elseif (thisLaser.x \< -(fudgeNum \* .5)) then thisLaser.x = display.contentWidth + (fudgeNum \* .5) elseif (thisLaser.y \< -(fudgeNum \* .5)) then thisLaser.y = display.contentHeight + (fudgeNum \* .5) elseif (thisLaser.y \> display.contentHeight + (fudgeNum \* .5)) then thisLaser.y = -(fudgeNum \* .5) end local function removeLaser() display.remove(thisLaser) table.remove(laserTable,i) end timer.performWithDelay ( 1000, removeLaser ) end end

The problem is that you’re removing all lasers each time the timer fires. If you’re creating a timer each time the laser is fired, why not just create it for that one laser - attach the timer() function to the laser object, call performWithDelay and pass the laser object as the parameter. That way the timer() function will get called on the laser object and it can remove itself.

If you go that route, you probably don’t need a table to manage the lasers, you can just rely on them being removed from their parent display group and more easily cease to exist.

Thanks for the reply and the code cleanup; much appreciated.

I tried creating a timer when I create the laser, but it still affects the next laser.  I’ll continue to work on the code to see if I reach the solution.

Just a thought - within the “for i = #laserTable, 1, -1 do” routine above, is there a way to add an if statement that would measure time since the thisLaser object was created?  That way, within this routine, which itself is within the gameLoop function, the code would determine which lasers have an existence of over 1000ms and then remove them?

How do I go about  attaching the timer() function to the laser object and passing the laser object as the parameter?  It sounds quite simple but I can’t figure it out from the API reference library, and am searching for an example but have yet to find one.  Thanks much.

Why don’t you give each “laser object” an ID and then use that for cleanup - either time-based or bounds-based?

What I would do is add in your table the start time (of the laser) and then cull based on start time + 1000ms < current time. Assuming the lifetime of a laser was 1 second.