In my new tower defence project I need to know when certain things are touching, or when object A is within range of object B, and other nonsenses like that. It seems perverse now, but the first time I had to implement collision code a few years ago I didn’t know why the computer couldn’t TELL there was a collision: The blue circle is halfway-inside the red square, surely that’s obvious? But implement I did, and it was horrible and rough, but for that project it didn’t matter at all.

In the early days of this project I implemented a collision system again with just two shape types: Rectangle and circle. It worked well enough, but the performance was awful — I had time to knock together a few arrays and an update loop, but more advanced stuff like knowing which objects could be safely ignored to speed the whole process up takes time to write and test. Having experience with it previously, I ran back to Box2D, dropping the source in to my project so I could begin prodding.


As it turns out, disabling the actual physics simulation bit of Box2D and just notifying objects of collisions is pretty easy… In fact, if you stumble upon the right comment in the right class, it’s written right there for you…

 

/*
* This is called after a contact is updated. This allows you to inspect a 
* contact before it goes to the solver. If you are careful, you can modify the
* contact manifold (e.g. disable contact).
*/

 

All the work you need to do is in box2d.dynamics.B2ContactListener. The first two functions, beginContact and endContact, are where you’ll want to notify your game objects of the start and end of collisions. Box2D only executes these functions once (not every frame the collision is occuring), so develop accordingly. The third function, preSolve, is where that comment comes from, and is where we’ll disable all further processing. To make this work I also had to add a reference to the parent sprite to each B2Body so we know what to contact. My code is as follows:

 

public function beginContact(contact:B2Contact):Void { 
  contact.m_fixtureA.getBody().parentSprite.collision(contact);
  contact.m_fixtureB.getBody().parentSprite.collision(contact);
}

public function endContact(contact:B2Contact):Void {
  contact.m_fixtureA.getBody().parentSprite.endCollision(contact);
  contact.m_fixtureB.getBody().parentSprite.endCollision(contact);
}

public function preSolve(contact:B2Contact, oldManifold:B2Manifold):Void {
  contact.setEnabled(false);
}

 

As you can see, my recieving functions in the sprites take the B2Contact object as their parameter since it already contains all the data they need, so to make everything a bit easier on the other end I added a few methods to box2d.contacts.B2Contact to retrieve the “other” sprite, body and shape.

 

public function getOtherBody(b:B2Body):B2Body { 
  if (b == this.m_fixtureA.m_body) return this.m_fixtureB.m_body;
  return this.m_fixtureA.m_body;
}
public function getOtherSprite(b:Sprite):Sprite {
  if (b == this.m_fixtureA.m_body.parentSprite) return this.m_fixtureB.m_body.parentSprite;
  return this.m_fixtureA.m_body.parentSprite;
}
public function getOtherShape(s:B2Shape):B2Shape {
  if (s == this.m_fixtureA.m_shape) return this.m_fixtureB.m_shape;
  return this.m_fixtureA.m_shape;
}

 

Presto, I hope that helps someone someday :)
– B