Removing spawned objects separately when colliding with other objects

Hello

I have a bunch of balls spawned on the screen.  I want the balls (spawned objects) to remove itself (the object spawned that collided) only if it collides with a wall, but I don’t seem to get this because the ball and the walls are in separate functions and I’m still a noob at coding.

I’m thinking that I can create an array for every ball spawned, but I don’t know how to do that

How can I make this possible??

Thanks for your reply! :slight_smile:

You want to be assigning a value to each object you create to indicate what type of object it is, when it is created or spawned. I like to use

.class = 'ball'

for example.

So, I would create a ball in a spawning function like this:

function newBall(ballsGrp,x,y,radius) local ball = display.newCircle(ballsGrp,x,y,radius) ball.class = "ball" physics.addBody(ball,"dynamic",{radius=radius}) return ball end

The parameters are the parent display group of the balls (this should be different to the parent display group of the walls) and the location and size of the ball (which would be randomly generated by your code, I assume.)

So, you would create a wall in a similar way - I won’t provide that code because it is simply a rectangle with a static body type and .class=“wall”

Now, you could attach a collision listener to either the ball or the wall, but I would attach to the ball - personal preference, but the logic of the ball should be encapsulated within the ball constructor (the function which creates the ball) I believe.

When the collision occurs with an object with class “wall”, fire a timer (because you can’t remove physics object during a collision) and remove the ball. Here’s the complete newBall() function:

function newBall(ballsGrp,x,y,radius) local ball = display.newCircle(ballsGrp,x,y,radius) ball.class = "ball" physics.addBody(ball,"dynamic",{radius=radius}) -- function to handle the collision on the ball function ball:collision(e) -- only perform logic when the ball is colliding with a wall if (e.other.class == "wall") then -- cannot remove objects during a collision, so wait a short moment for it to end timer.performWithDelay(1, function() -- remove the ball ball:removeSelf() end, 1) end -- always return true because we have handled the collision return true end -- attach a collision listener to the ball ball:addEventListener("collision",ball) return ball end

You want to be assigning a value to each object you create to indicate what type of object it is, when it is created or spawned. I like to use

.class = 'ball'

for example.

So, I would create a ball in a spawning function like this:

function newBall(ballsGrp,x,y,radius) local ball = display.newCircle(ballsGrp,x,y,radius) ball.class = "ball" physics.addBody(ball,"dynamic",{radius=radius}) return ball end

The parameters are the parent display group of the balls (this should be different to the parent display group of the walls) and the location and size of the ball (which would be randomly generated by your code, I assume.)

So, you would create a wall in a similar way - I won’t provide that code because it is simply a rectangle with a static body type and .class=“wall”

Now, you could attach a collision listener to either the ball or the wall, but I would attach to the ball - personal preference, but the logic of the ball should be encapsulated within the ball constructor (the function which creates the ball) I believe.

When the collision occurs with an object with class “wall”, fire a timer (because you can’t remove physics object during a collision) and remove the ball. Here’s the complete newBall() function:

function newBall(ballsGrp,x,y,radius) local ball = display.newCircle(ballsGrp,x,y,radius) ball.class = "ball" physics.addBody(ball,"dynamic",{radius=radius}) -- function to handle the collision on the ball function ball:collision(e) -- only perform logic when the ball is colliding with a wall if (e.other.class == "wall") then -- cannot remove objects during a collision, so wait a short moment for it to end timer.performWithDelay(1, function() -- remove the ball ball:removeSelf() end, 1) end -- always return true because we have handled the collision return true end -- attach a collision listener to the ball ball:addEventListener("collision",ball) return ball end

Hi horacebury,

I ran into similar issue and it seems that your post is the way out. I’ve setup the things in the same way but I get the following error:

Attempt to remove an object that's already been removed from the stage or whose parent/ancestor group has already been removed.

This happens just after the ball:removeSelf() method is fired.

Can you give me some guide, please,

Cheers

I’ve found the answer:

local function onCollision( self, event ) if ( event.phase == "began" ) then -- Check if body still exists before removing! if ( crate1 ) then crate1:removeSelf() crate1 = nil end end end

‘crate1’ appears to be a global variable so no matter how many crates you create it will only ever refer to the last one.

You need to attach the listener to the crate then remove each crate individually. There is also one gotcha in that you cannot remove an object during a collision. The solution to this has been posted many times before (a few by me) so I’ll give you some hints and let you read up. If you can’t get it working soon let me know and I’ll post the code.

Use a table listener to attach the onCollision to your crate.
Do not use global variables for individual on-screen objects, try to always keep them in a display group.
In onCollision wrap the :removeSelf() in a timer.performWithDelay, for 1 millisecond.

That’s it. Good luck and shout if you need to.

Hi horacebury,

I ran into similar issue and it seems that your post is the way out. I’ve setup the things in the same way but I get the following error:

Attempt to remove an object that's already been removed from the stage or whose parent/ancestor group has already been removed.

This happens just after the ball:removeSelf() method is fired.

Can you give me some guide, please,

Cheers

I’ve found the answer:

local function onCollision( self, event ) if ( event.phase == "began" ) then -- Check if body still exists before removing! if ( crate1 ) then crate1:removeSelf() crate1 = nil end end end

‘crate1’ appears to be a global variable so no matter how many crates you create it will only ever refer to the last one.

You need to attach the listener to the crate then remove each crate individually. There is also one gotcha in that you cannot remove an object during a collision. The solution to this has been posted many times before (a few by me) so I’ll give you some hints and let you read up. If you can’t get it working soon let me know and I’ll post the code.

Use a table listener to attach the onCollision to your crate.
Do not use global variables for individual on-screen objects, try to always keep them in a display group.
In onCollision wrap the :removeSelf() in a timer.performWithDelay, for 1 millisecond.

That’s it. Good luck and shout if you need to.

hi

regarding removing on collision

some cases you might get a lot of collision after the first one, is it ok do do try and catch with pcall?

That way I it really dont mather if more collisions happend… you just do do anything for the next ones…

Or will that result in any problems that I dont know of

Hi @vegar.ringdal,

Generally, you shouldn’t get multiple collisions if you conditionally handle the first collision even using the “began” phase, as shown earlier in this thread. You can then remove the object upon collision, or remove its collision listener, and you shouldn’t receive additional collision events following that point.

Best regards,

Brent Sorrentino

hi

regarding removing on collision

some cases you might get a lot of collision after the first one, is it ok do do try and catch with pcall?

That way I it really dont mather if more collisions happend… you just do do anything for the next ones…

Or will that result in any problems that I dont know of

Hi @vegar.ringdal,

Generally, you shouldn’t get multiple collisions if you conditionally handle the first collision even using the “began” phase, as shown earlier in this thread. You can then remove the object upon collision, or remove its collision listener, and you shouldn’t receive additional collision events following that point.

Best regards,

Brent Sorrentino

Nil error when on going to next level. ; how to create best in project…

/Users/Library/Application Support/luaglider2/dev/ProjectBuilds/Out(Builds)/Out(default)/Out/level1.lua:471: attempt to index global ‘self’ (a nil value)

message

stack traceback:

?: in function <?:221>

/Users/Library/Application Support/luaglider2/dev/ProjectBuilds/Out(Builds)/Out(default)/Out/level1.lua:471: in function ‘onEvent’

/Users/Library/Application Support/luaglider2/dev/ProjectBuilds/Out(Builds)/Out(default)/Out/ui.lua:107: in function </Users/Library/Application Support/luaglider2/dev/ProjectBuilds/Out(Builds)/Out(default)/Out/ui.lua:47>

?: in function <?:221>

Hi @lnwpen88,

Do you “return true” in your collision listener function? Can you post the code for the community and staff to see? Please surround it by “lua” tags for clarity:

[lua] ... [/lua]

Thanks,

Brent

Nil error when on going to next level. ; how to create best in project…

/Users/Library/Application Support/luaglider2/dev/ProjectBuilds/Out(Builds)/Out(default)/Out/level1.lua:471: attempt to index global ‘self’ (a nil value)

message

stack traceback:

?: in function <?:221>

/Users/Library/Application Support/luaglider2/dev/ProjectBuilds/Out(Builds)/Out(default)/Out/level1.lua:471: in function ‘onEvent’

/Users/Library/Application Support/luaglider2/dev/ProjectBuilds/Out(Builds)/Out(default)/Out/ui.lua:107: in function </Users/Library/Application Support/luaglider2/dev/ProjectBuilds/Out(Builds)/Out(default)/Out/ui.lua:47>

?: in function <?:221>

Hi @lnwpen88,

Do you “return true” in your collision listener function? Can you post the code for the community and staff to see? Please surround it by “lua” tags for clarity:

[lua] ... [/lua]

Thanks,

Brent