Handling a Box2D Collision
Collision detection is done by extending the b2ContactListener class,
overriding all its methods and passing it to the SetContactListener()
method of the b2World. This is just a system of class callback so don’t
expect the dispatch of an event here. Up to you to implement the
IEventDispatcher interface and have your callback class dispatch events.
One important thing to notice here is that the BeginContact() method is called only once when the contact begins and the EndContact() method is called obviously when the contact stop colliding. To resume, you’ll know when two contact start touching and when they stop touching but you’ll have to assume what happens in between. For example if you want to know if two contacts are still touching you need to check if a EndContact() has been called for them. If not then you can assume they are still touching.
Let’s get started by creating our class. We simply extend the b2ContactListener class and override all its methods. Let’s call our class ContactCallback. Then we need to pass it to our world:
And voila, it’s already working. If you put some traces in each
ContactCallback methods you’ll see that they are all called each time a
The BeginContact() method and the EndContact() method are giving us a b2Contact object. With this object we can have access to two fixtures, the two fixtures that collided. Remember that a b2Body is made up with fixtures, one or many. So instead of telling you which b2Body collided, the b2Contact tells you which fixture collided. To know which b2Body was involved in the collision you can retrieve a reference to the fixture:
var firstbody:b2Body = firstfixture.GetBody();
That simple. You need of course to keep a reference to your b2Body
and why not to your fixtures as well in order to take appropriate
action. A b2Contact has also a GetFixtureB() method so you can
reference the second fixture.
Let’s put this in action with two simple examples.
Let’s trigger a sound when a basketball touches the floor. Basically I keep a reference of the ground body and I create a ContactCallback instance for which I keep a reference:
[AS]private var contacttarget:b2Body;
private var contactcallback:ContactCallback;[/AS]
I modify a bit that class to accept a target public variable and a callback function to which I will pass the b2Body that collided with the ground. (I don’t use callbacks usually but I use it here to quickly illustrate the implementation) In that callback function I do:
Now let’s destroy all crosses when they touch the ground. That means get rid of the graphic but also get rid of the b2Body of course which is not as easy as you might think. You actually cannot destroy a b2Body from within a BeginContact() or EndContact(). Instead you need to qualify those b2Body for destruction and destroy them after the world step. I just put them in an array here:
Here is what happens in our callback function:
if (mc.numChildren > 0)
if (mc.getChildAt(0) is Wood || mc.getChildAt(0) is Tube)
mc.visible = false;
Now after the world step I destroy them safely:
while (destroyedbody.length > 0)
var bodytodestroy:b2Body = destroyedbody.shift();
note that there’s also a b2DestructionListener that you can implement the same way. This is used to deal properly with the remaining objects after destroying a b2Body. Now you probably know how to implement that callback class. Now it’s time to check controllers and see what they can do and how to use them.