Limit collision frequency

Hi,

Currently I am implementing an explosive game, with dynamite that collide with several objects, and explode.

I add a collision listener to the dynamite, however, when the dynamite spawned and collide with several objects, the event handler will be fired several times.

The problem happens, because I will remove the dynamite with removeSelf() in the event handler, so only the first event handler will successful complete, while second and onward will fail with “ERROR: Attempt to remove an object that’s already been removed from the stage or whose parent/ancestor group has already been removed.”

Here is the on collision code:

function onDynamiteCollision(self, event)  
  
 --triggered when dynamite collide with anything  
 if event.phase == "began" then  
  
 local explosion = ""  
 local circle = ""  
  
 local function blast ()  
  
 if(self.y ~= nil) then  
 circle = display.newCircle(self.x, self.y, 60)  
  
 --create the explosion sprite  
 local spriteSheet = sprite.newSpriteSheet("explosion.png", 100, 100)  
 local spriteSet = sprite.newSpriteSet(spriteSheet, 1, 12)  
 sprite.add(spriteSet, "explode", 1, 12, 500)  
 explosion = sprite.newSprite(spriteSet)  
 explosion.x = self.x  
 explosion.y = self.y  
 audio.play(explosionSound)  
 explosion:prepare("explode")  
 explosion:play()  
 circle:setFillColor(0,0,0,0)  
 circle.myName = "circle"  
 display.remove(self)  
 --self:removeSelf()   
 --self = nil  
 --self.isBodyActive = false  
 --self.isVisible = false  
 --display:remove(dynamite)  
 physics.addBody(circle, "static", {isSensor = true})  
 circle.isBullet = true  
 circle.collision = onExplodeCollision  
 circle:addEventListener("collision", circle)  
 end  
 end  
  
 local function removeAll()  
  
 if( circle ~= "") then  
 circle:removeSelf() --error happen here  
 end  
  
 if(explosion ~= "") then  
 explosion:removeSelf()  
 end  
 end  
  
 if(self ~= nil) then  
 timer.performWithDelay(1, blast)   
 timer.performWithDelay(1001, removeAll) --error happen here too  
 end  
 return true  
 end  
  
end  

What should I do to ignore the extra event handler call?

Thanks. [import]uid: 138320 topic_id: 24574 reply_id: 324574[/import]

I’m not 100% on this particular coding style (attempting to remove in a handler without timer.performWithDelay()), but in regards to your general issue, I’ve had to deal with the same issue. I solved by first checking if a variable “.alive” == true before proceeding. Immediately following, set the variable “.alive” = false, then proceed with your logic. I use this to stop “double-taps” as well. This is just the way that I have solved, there may be others…

Hope this moves you along. :slight_smile: [import]uid: 21331 topic_id: 24574 reply_id: 99494[/import]

What if you just remove the listener in collision event handler first? Your object won’t register any more collisions after the initial one. [import]uid: 31262 topic_id: 24574 reply_id: 99524[/import]

Hi, thanks for all replies. I had found a solution for my case.

@aaaron, because I am throwing an object to another group of objects, so the collision might happen with many target objects, thus each collision will fire the event handler and run together, and no time to remove the event handler.

My solution is to check the range of collision coordinate, like this:

[code]
local dynamiteCollX = 0
local dynamiteCollY = 0

function onDynamiteCollision(self, event)
if event.phase == “began” then
print("onDynamiteCollision " … self.name … " bang " … event.other.name)
if dynamiteCollX - 30 <= self.x and self.x <= dynamiteCollX + 30 and dynamiteCollY - 30 <= self.y and self.y <= dynamiteCollY + 30 then
print("displace " … self.x - dynamiteCollX)
print(“same collision event”)
return true
else

dynamiteCollX = self.x
dynamiteCollY = self.y
end
–handle your event here
end
end
[/code] [import]uid: 138320 topic_id: 24574 reply_id: 99532[/import]