You can read about how collisions in Box2D work over in this tutorial, but in Moai you will find that a lot of the functions referenced there don’t actually exist. There is no way to get the full contact list of everything that is colliding through getContactList(). However, Moai does provide one way to respond to collisions – the MOAIBox2DFixture’s setCollisionHandler() function.
Here is an example of how you can call it:
function handler(phase, fixtureA, fixtureB, arbiter) print("we had a collision!") end myFixture:setCollisionHandler(handler, MOAIBox2DArbiter.END)
First we declare a function with the signature that the collision handler expects. This includes the following:
- Phase – this tells you which part of collision resolution called the helper. There are 4 types of collision phases – begin, end, pre-solve and post-solve. Begin and end (MOAIBox2DArbiter.BEGIN, MOAIBox2DArbiter.END) happen once per collision, when 2 things first collide, and after Box2D figures out how to make their geometries no longer overlap. In between are multiple calls to pre-solve and post-solve (MOAIBox2DArbiter.POST_SOLVE, MOAIBox2DArbiter.PRE_SOLVE) which are steps Box2D takes to try to separate the geometries.
- Fixture A – this is the first fixture in the collision, and the one you attached the collision handler to.
- Fixture B – this is the other fixture in the collision.
- Arbiter – This is a MOAIBox2DArbiter, which is an object you can use to query some information about the collision.
You can also optionally pass setCollisionHandler() a phase mask (in the example above, I only want to be notified when a collision is solved) and a category mark (I haven’t tried this, but you can assign your fixtures certain category numbers, and then only call the handler when certain categories collide).
If you follow these steps, then every time your fixture collides with something else, a message will be printed to the terminal. Not so bad right?
Things do get a little tricky if you want your collision handler function to be attached to a class. Lets say you want to define it as part of the class Foo, and you want to be able to access your member variables when handling the collision. You might want to do something like this:
function Foo:handler(phase, fixtureA, fixtureB, arbiter) print("we had a collision!") self:doSomething() end
However, remember that “:” makes this really shorthand for this:
function Foo.handler(self, phase, fixtureA, fixtureB, arbiter) print("we had a collision!") self:doSomething() end
Now it no longer matches up with what setCollisionHandler() wants to call! To get around it, you can try something like this:
myFixture:setCollisionHandler(function(phase, a, b, arbiter) self:handler(phase, a, b, arbiter) end, MOAIBox2DArbiter.END)
I’m not sure if this introduces some extra overhead – am I creating a new instance of a function everytime I call setCollisionHandler()? If I am, it probably isn’t that bad as long as there is only some reasonable number of these around.