Adding physics body inside collision event handler crashes Corona...

The following 20 line program crashes the Corona Game Edition 2010.109 simulator when I try to create a display object and try to add it to the physics engine inside of a “collision” event handler:

[lua]local physics = require(“physics”)
physics.start()
physics.setScale( 60 )
physics.setGravity( 0, 10 )
–physics.setDrawMode(“debug”)

local ground = display.newRect( 0, display.contentHeight-20, display.contentWidth, 20 )
physics.addBody( ground, “static”, { friction=0.5 } )

local nc0 = display.newCircle( 150, 50 , 25 )
nc0:setFillColor( 255, 255, 0)
physics.addBody( nc0, { density=1, friction=0.5, bounce=0.5, radius=25 } )

local function onGlobalCollision( event )
local nc1 = display.newCircle( 50, 50 , 25 )
nc1:setFillColor( 0, 255, 0)
physics.addBody( nc1, { density=1, friction=0.5, bounce=0.5, radius=25 } )
end

Runtime:addEventListener( “collision”, onGlobalCollision )[/lua]

Hopefully the following console output with some details about the assertion failure is helpful:

Copyright (C) 2009-2010 A n s c a , I n c .  
 Version: 1.0.0  
 Build: 2010.109  
The file sandbox for this project is located at the following folder:  
 (/Users/franks/Library/Application Support/Corona Simulator/Worm6-add-BEEE207118EEE1847DB4E01F5289DB3A)  
Assertion failed: (IsLocked() == false), function CreateBody, file /Users/ansca/.hudson/jobs/Pong-DMG/workspace/platform/mac/../../external/Box2D\_v2.1.2/Box2D/Box2D/Dynamics/b2World.cpp, line 84.  
/Applications/Corona Game Edition 2010.109/simulator: line 9: 19252 Abort trap "$path/Corona Simulator.app/Contents/MacOS/Corona Simulator" $\*  
~\>  

This same bug has been haunting me in the previous game edition releases, but I wasn’t able to isolate it because of the now-fixed, debug draw mode bus-error.

Please confirm that this is a bug… and that I’m not doing anything “wrong”.

Thanks, Frank.

[import]uid: 8093 topic_id: 2662 reply_id: 302662[/import]

The following change to the code (=ugly hack), makes it all work:
[lua]local physics = require(“physics”)
physics.start()
physics.setScale( 60 )
physics.setGravity( 0, 10 )
–physics.setDrawMode(“debug”)

local ground = display.newRect( 0, display.contentHeight-20, display.contentWidth, 20 )
physics.addBody( ground, “static”, { friction=0.5 } )

local nc0 = display.newCircle( 150, 50 , 25 )
nc0:setFillColor( 255, 255, 0)
physics.addBody( nc0, { density=1, friction=0.5, bounce=0.5, radius=25 } )

hackState = false

local function onGlobalCollision( event )
hackState = true
–[[
local nc1 = display.newCircle( 50, 50 , 25 )
nc1:setFillColor( 0, 255, 0)
physics.addBody( nc1, { density=1, friction=0.5, bounce=0.5, radius=25 } )
–]]
end

Runtime:addEventListener( “collision”, onGlobalCollision )

local hack = function( event)
if(hackState) then
local nc1 = display.newCircle( 50, 50 , 25 )
nc1:setFillColor( 0, 255, 0)
physics.addBody( nc1, { density=1, friction=0.5, bounce=0.5, radius=25 } )
hackState = false
end
end
Runtime:addEventListener( “enterFrame”, hack )[/lua]

The code-change essentially delays the physics.addBody() to the next enterFrame event handler call, which makes all work as expected.
Guess that this narrows down the bug to specifically the collision event handler.

-Frank.
[import]uid: 8093 topic_id: 2662 reply_id: 7717[/import]

@Frank, thanks for this, I’ve had to remove features from a few of my games because of this bug. [import]uid: 7587 topic_id: 2662 reply_id: 8015[/import]

Thanks for providing test code! Filed internal issue #1617. [import]uid: 6787 topic_id: 2662 reply_id: 8663[/import]

if you look at the Box2D forums, you’re not meant to do anything to world objects inside these events. For destroys, you’re meant to set a flag to say the object is ready for removal etc, and then do the removal in the next safe update loop, outside of the physics step. This is probably partly why you are crashing… it’s probably the same for adding objects. My guess is that you’re putting stuff into the world that it doesn’t recognize yet

http://www.box2d.org/forum/viewtopic.php?f=3&t=3592
http://blog.allanbishop.com/box2d-2-1a-tutorial-–-part-4-collision-detection/ [import]uid: 6645 topic_id: 2662 reply_id: 8707[/import]

Interesting!

It probably also explains why my “hack” works as inside of the “collision” handler, I postpone the actual adding of the physics object to the “enterFrame” handler.

So it may be solved by documenting the following clearly:

* Do NOT change the physics world inside of “collision” handlers!

* What other events are similar to “collision” in the sense that they are “in the middle” of physics calculations and one should not change the state?

* What are the operations that change the physics world and should not be used inside of the before mentioned set of events handlers?

* Is the “enterFrame” a safe event to use to change the physics world (…or was I just lucky)?

* What other events are “safe update” points to change the physics state?

Thanks for investigating this at the Box2D source!

Regards, Frank.
[import]uid: 8093 topic_id: 2662 reply_id: 8708[/import]

good question… in Flash I think we manually call world.step() and I’m guessing this doesn’t happen in Corona as they’re not exposing Box2D directly. Ansca would need to add a BEFORE_STEP and AFTER_STEP event/function or something like that.

I see that this “issue” is meant to be dealt with by their engine, so I guess it’ll just be down to a bug-fix

“As of Alpha 3, you should be able to freely destroy bodies and joints whenever you like. Corona will automatically handle the process of holding onto the corresponding Box2D objects until the end of the current physics world step, and then safely dispose of them.”

note the Box2D contact functions do seem to be available but they’re still within the physics step I guess

BOX2D
“You can receive contact data by implementing b2ContactListener. The contact listener supports several events: begin, end, pre-solve, and post-solve.”
http://www.box2d.org/manual.html#_Toc258082975

CORONA
http://developer.anscamobile.com/content/game-edition-collision-detection
“preCollision”/“postCollision”
[import]uid: 6645 topic_id: 2662 reply_id: 8712[/import]

There is another thread relating to this that I’m having trouble with located here http://developer.anscamobile.com/forum/2010/12/14/making-physics-objects-stick-one-another

I’ve tried making physics objects stick to each other outside of the collision handler but I’m not having any luck.

Anyone here have any input?

[import]uid: 9046 topic_id: 2662 reply_id: 14283[/import]

Whats the code for a collision event [import]uid: 20355 topic_id: 2662 reply_id: 20519[/import]

This is an interesting issue. I’m trying to pull some stuff out of my main file and put it into re-useable files. One example is a lamp I created. It swings, it breaks, it does everything I want it to EXCEPT:

During postCollision I want to create a piece of it that flies off (ie, glass etc) So something hits it, the image changes, and a part of the lamp falls to the ground with realistic physics. This obviously crashes the game because I am trying to do an addBody during a collision event.

The alternative is to set a flag, and have it created in the “enterFrame” section. This is stupid, since I now have a standalone lampCreator.lua file that now needs a flag set, and a function to actually create the lamp during the enterFrame…

In box2d you can do a world.doOutSideOfPhysicsLoop or something along those lines. Can this be called in Corona?

Is there another elegant solution that allows this to happen within a self contained file. Ideally I’d love to just include my .lua files and have it work in a object oriented design way.

Ideas?

Thanks,
-d

[import]uid: 27681 topic_id: 2662 reply_id: 37172[/import]