Removing spawned objects on collision issue

I’m having an odd issue with the removal of collided objects.  I’m creating a series of random falling circles that are removed when they collide with a barrier (much like rain).  However, some of the newly spawned objects are removed before they impact the barrier.  It think it has to do with the same table index # being assigned twice.

i.e. object at table index 5 is removed on impact with barrier and the index count is reduced to 4 —> a newly generated object fills index 5, but is also simultaneously removed.

---Define variables: local W = display.actualContentWidth local H = display.actualContentHeight local math\_r = math.random display.setStatusBar( display.HiddenStatusBar ) --Start physics: local physics = require("physics") physics.start() --Create table & group to hold circles/spawns: local circles = {} local circle\_group = display.newGroup( ) --Create wall to trigger circle removal: local removeThreshold = display.newRect(W\*0.5, H\*0.5, W, 50) physics.addBody( removeThreshold, { density = 10, friction = 0.5, bounce = 0 } ) removeThreshold.bodyType = "static" removeThreshold.isSensor = true removeThreshold.name = "threshold" removeThreshold.collision = onCollision removeThreshold:addEventListener( "collision", removeThreshold ) --Function for spawning circles: local function spawnCircle() local onCollision = function ( self, event ) if ( event.phase == "began" ) then display.remove(self.tableID[self.index]) self.tableID[self.index] = nil elseif ( event.phase == "ended" ) then end return true end local r = math\_r(25,50); g = math\_r(254,254); b = math\_r(25,50) local circle = display.newCircle( 0, 0, 10 ) circle:setFillColor(r,g,b) circle\_group:insert(circle) circle.x = math\_r(0, W) circle.group = circle\_group circle.name = "circle" circle.collision = onCollision circle:addEventListener( "collision", circle ) physics.addBody(circle, {density=50, bounce=0, radius=30}) circle.bodyType = "dynamic" circle.isSensor = true circle.y = math\_r(-100, -10) circle.tableID = circles circle.index = #circles + 1 circle:setLinearVelocity(0, math\_r(50, 200)) circles[circle.index] = circle return circle end local spawnTimer = timer.performWithDelay(50, spawnCircle, 0)

Never mind, I fixed it. Turns out that flagging an object as it collides, and checking that it’s colliding the object you want, fixes it!

Here’s how to fix it:

I check for that my objects are colliding specifically with the threshold (necessary!), and whether an impact has occurred (the second check seems to be optional):

 if event.other.name == "threshold" and self.hasImpacted == false then self.hasImpacted = true

then in the object creation function I add a flag as property of the object (only if you use the 2nd check):

circle.hasImpacted = false

In context:

--Function for spawning circles: local function spawnCircle() local onCollision = function ( self, event ) if ( event.phase == "began" ) then if event.other.name == "threshold" and self.hasImpacted == false then --\< added self.hasImpacted = true --\< added display.remove(self.tableID[self.index]) self.tableID[self.index] = nil end --\< added elseif ( event.phase == "ended" ) then end return true end local r = math\_r(25,50); g = math\_r(254,254); b = math\_r(25,50) local circle = display.newCircle( 0, 0, 10 ) circle:setFillColor(r,g,b) circle\_group:insert(circle) circle.x = math\_r(0, W) circle.group = circle\_group circle.name = "circle" circle.collision = onCollision circle:addEventListener( "collision", circle ) physics.addBody(circle, {density=50, bounce=0, radius=30}) circle.bodyType = "dynamic" circle.isSensor = true circle.y = math\_r(-100, -10) circle.tableID = circles circle.index = #circles + 1 circle:setLinearVelocity(0, math\_r(50, 200)) circles[circle.index] = circle circle.hasImpacted = false --\< added return circle end

Here’s an interesting twist, as soon as I added a config.lua to the project, I ran into issues with level cleanup. If I pause physics and spawn timers, and then attempt to remove the remaining objects, those that have not yet impacted the barrier, they don’t all remove.

Here is my cleanup code, mind you, it works perfectly when the config.lua file is not present!

local cleanupTimer ... --Stop physics and timers and clean (all objects and tables): local function cleanAll() print("pre\_removal:"..#circles) physics.stop() if spawnTimer then timer.cancel(spawnTimer) spawnTimer=nil local function remove() local i for i = #circles, 1, -1 do display.remove(circles[i]) circles[i] = nil end print("post\_removal:"..#circles) end local r\_timer = timer.performWithDelay(1000, remove) end if #circles == 0 then timer.cancel(removeTimer) removeTimer = nil print("all done!") end end cleanupTimer = timer.performWithDelay(2000, cleanAll,1)

A very basic config.lua for testing:

application = { content = { width = 320, height = 480, scale = "letterbox", }, launchPad = false }

You can try with “object.isBullet = true” and using 

object:removeSelf()

instead of display.remove(self.tableID[self.index])

self.tableID[self.index] = nil

Other that day i dont see any problem.

Oh, I should have been clearer in my description of the problem. I am talking about removal in regards to level cleanup, the removal on impact with the barrier works as expected.

Say I’m either leaving or resetting the level. I will have to remove whatever objects remain. Problem is, when I pause everything, and then attempt removal of what remains, it doesn’t work. It worked when the config.lua file was not present, oddly enough.

Never mind, I fixed it. Turns out that flagging an object as it collides, and checking that it’s colliding the object you want, fixes it!

Here’s how to fix it:

I check for that my objects are colliding specifically with the threshold (necessary!), and whether an impact has occurred (the second check seems to be optional):

 if event.other.name == "threshold" and self.hasImpacted == false then self.hasImpacted = true

then in the object creation function I add a flag as property of the object (only if you use the 2nd check):

circle.hasImpacted = false

In context:

--Function for spawning circles: local function spawnCircle() local onCollision = function ( self, event ) if ( event.phase == "began" ) then if event.other.name == "threshold" and self.hasImpacted == false then --\< added self.hasImpacted = true --\< added display.remove(self.tableID[self.index]) self.tableID[self.index] = nil end --\< added elseif ( event.phase == "ended" ) then end return true end local r = math\_r(25,50); g = math\_r(254,254); b = math\_r(25,50) local circle = display.newCircle( 0, 0, 10 ) circle:setFillColor(r,g,b) circle\_group:insert(circle) circle.x = math\_r(0, W) circle.group = circle\_group circle.name = "circle" circle.collision = onCollision circle:addEventListener( "collision", circle ) physics.addBody(circle, {density=50, bounce=0, radius=30}) circle.bodyType = "dynamic" circle.isSensor = true circle.y = math\_r(-100, -10) circle.tableID = circles circle.index = #circles + 1 circle:setLinearVelocity(0, math\_r(50, 200)) circles[circle.index] = circle circle.hasImpacted = false --\< added return circle end

Here’s an interesting twist, as soon as I added a config.lua to the project, I ran into issues with level cleanup. If I pause physics and spawn timers, and then attempt to remove the remaining objects, those that have not yet impacted the barrier, they don’t all remove.

Here is my cleanup code, mind you, it works perfectly when the config.lua file is not present!

local cleanupTimer ... --Stop physics and timers and clean (all objects and tables): local function cleanAll() print("pre\_removal:"..#circles) physics.stop() if spawnTimer then timer.cancel(spawnTimer) spawnTimer=nil local function remove() local i for i = #circles, 1, -1 do display.remove(circles[i]) circles[i] = nil end print("post\_removal:"..#circles) end local r\_timer = timer.performWithDelay(1000, remove) end if #circles == 0 then timer.cancel(removeTimer) removeTimer = nil print("all done!") end end cleanupTimer = timer.performWithDelay(2000, cleanAll,1)

A very basic config.lua for testing:

application = { content = { width = 320, height = 480, scale = "letterbox", }, launchPad = false }

You can try with “object.isBullet = true” and using 

object:removeSelf()

instead of display.remove(self.tableID[self.index])

self.tableID[self.index] = nil

Other that day i dont see any problem.

Oh, I should have been clearer in my description of the problem. I am talking about removal in regards to level cleanup, the removal on impact with the barrier works as expected.

Say I’m either leaving or resetting the level. I will have to remove whatever objects remain. Problem is, when I pause everything, and then attempt removal of what remains, it doesn’t work. It worked when the config.lua file was not present, oddly enough.