I have a singleton Physics class that wraps the functionality of Box2d. It implements ContactListener which exposes the body contact events -- beginContact and endContact being the methods of interest. Both of these callbacks receieve a Contact object which has getFixtureA().getBody() and getFixtureB().getBody().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
| public final class Physics implements ContactListener { private static Physics _physics = null;
private final World _world; private final ArrayList<HitWatcher> _hitWatchers; private final ArrayList<Body> _bodyQueue; private final ArrayList<HitWatcher> _hitWatcherRemovalQueue;
private Physics() { _world = new World(new Vec2(0, Constants.GAME_PHYSICSGRAVITY), false); _hitWatchers = new ArrayList<>(); _bodyQueue = new ArrayList<>(); _hitWatcherRemovalQueue = new ArrayList<>(); _world.setContactListener(this); }
public synchronized void registerHitWacher(final HitWatcher hitWatcher) { _hitWatchers.add(hitWatcher); }
public synchronized void removeHitWatcher(final HitWatcher hitWatcher) { _hitWatcherRemovalQueue.add(hitWatcher); }
public static Physics getInstance() { if (_physics == null) { reset(); } return _physics; }
public static float toMeters(final int pixels) { return pixels * 0.02f; }
public static int toPixels(final float meters) { return (int)(meters * 50.0f); }
public Body createBody(final BodyDef bodyDef) { return _world.createBody(bodyDef); }
public synchronized void removeBody(final Body body) { _bodyQueue.add(body); }
public static void reset() { if (_physics != null) { Body b2Body = getInstance()._world.getBodyList(); while(b2Body != null) {
getInstance()._world.destroyBody(b2Body); b2Body = b2Body.getNext(); } } _physics = new Physics(); Player.getInstance().initializePhysics(); }
public synchronized void step() {
if ((_bodyQueue.size() > 0) && !_world.isLocked()) { for(HitWatcher hitWatcher : _hitWatcherRemovalQueue) { _hitWatchers.remove(hitWatcher); } _hitWatcherRemovalQueue.clear();
for(Body body : _bodyQueue) {
Body b = _world.getBodyList();
do { if (b == body) { _world.destroyBody(body); break; } } while ((b = b.getNext()) != null);
}
_bodyQueue.clear(); }
final int _velocityIterations = 12; final int _positionIterations = 4; _world.step(Constants.GAME_PHYSICSTIME, _velocityIterations, _positionIterations);
}
@Override public void beginContact(final Contact contact) { for (final HitWatcher hitWatcher : _hitWatchers) {
if ( (hitWatcher.getBody() != contact.getFixtureA().getBody()) && (hitWatcher.getBody() != contact.getFixtureB().getBody()) ) { continue; }
hitWatcher.getHitHandler().HitOccured( contact.getFixtureA().getBody(), contact.getFixtureB().getBody() ); } }
@Override public void endContact(final Contact contact) { }
@Override public void preSolve(final Contact contact, final Manifold manifold) { }
@Override public void postSolve(final Contact contact, final ContactImpulse contactImpulse) { } } |
With this, I have created two support classes. HitWatcher is used to store a body to watch for, and a handler callback to call when this body is involved in a collision event. I define it as so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| final class HitWatcher { private final HitHandler _hitHandler; private final Body _body;
public HitWatcher(final HitHandler hitHandler, final Body body) { _hitHandler = hitHandler; _body = body; }
public HitHandler getHitHandler() { return _hitHandler; }
public Body getBody() { return _body; } } |
Then of course is the HitHandler, which is simply an interface any class can implement to support hit events:
1 2 3
| public interface HitHandler { public void HitOccured(Body body1, Body body2); } |
With that, I can do very easy hit detection:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| public final class Coin implements HitHandler { private Body _body; private HitWatcher _hitWatcher; private final int _startX; private final int _startY; private final Vec2 _force;
public Coin(final int x, final int y, final Vec2 force) { _startX = x; _startY = y; _force = force; }
public void initializePhysics() { BodyDef bodyDef = new BodyDef(); bodyDef.type = BodyType.DYNAMIC; bodyDef.position.set(Physics.toMeters(_startX), Physics.toMeters(_startY)); _body = Physics.getInstance().createBody(bodyDef); CircleShape dynamicBox = new CircleShape(); float width = Physics.toMeters(Constants.GAME_TILESIZE)/ 2.0f; dynamicBox.m_radius = width * 0.8f; FixtureDef fixtureDef = new FixtureDef(); fixtureDef.shape = dynamicBox; fixtureDef.density = 0.5f; fixtureDef.friction = 0.1f; _body.createFixture(fixtureDef); _body.setFixedRotation(true); _body.applyForce(_force, _body.getWorldCenter()); _hitWatcher = new HitWatcher(this, _body); Physics.getInstance().registerHitWacher(_hitWatcher); }
public void freePhysics() { Physics.getInstance().removeBody(_body); }
public int getX() { return Physics.toPixels(_body.getPosition().x) + 5; }
public int getY() { return Physics.toPixels(_body.getPosition().y) + 5; }
@Override public void HitOccured(final Body body1, final Body body2) {
if ((body1 != Player.getInstance().getBody()) && (body2 != Player.getInstance().getBody())){ return; } MusicPlayer.playSound(SoundEffect.Coin); Player.getInstance().setCoins(Player.getInstance().getCoins() + 1); Physics.getInstance().removeHitWatcher(_hitWatcher); Messenger.getInstance().pushMessage(new Message(MessageClass.Stage, MessageType.CoinDestroyed, this)); } } |
When the above object is initiated, the code calls the theObect.initalizePhysics() method which sets up the physical body for box2d. The very last line of that code is:
1 2
| _hitWatcher = new HitWatcher(this, _body); Physics.getInstance().registerHitWacher(_hitWatcher); |
This is all I have to do to attach to the physics engine and listen in to hit events without adding bulk to the physics class itself.
When this object is destroyed you do have to remember to remove the watcher from the physics engine (which I do on the HitOccured event in the above case):
1
| Physics.getInstance().removeHitWatcher(_hitWatcher); |
This is how I implemented collision in my game and it seems to work great, and keeps my code clean and object oriented

In the game loop you just call Physics.getInstance().step() to keep the physics engine moving along.