Getting Started with Box2D Physics

The past few days I've been messing around with the Box2D physics engine. For someone who spends his days buried in business applications, this has been a fun bit of learning. Box2D has been ported to a ton of languages and I found a nice port to javascript called box2dweb.

First, let's look at a simple demo:


Click here for full jsFiddle

The first thing you'll need to do is set up a world and a loop to update it. The basics look like this:

var world = new b2World(
   new b2Vec2(0, 10), //gravity vector
   true
);

setInterval(function(){
    world.Step(1 / 60, 10, 10);
    world.ClearForces();
},1000/60);

We just declared a world with some gravity. In the example above, we're applying gravity down, but you can have it pushing any direction you'd like. Next we set up an interval to run 60 times per second. Inside of that we tell the world to step 1/60th of a second while specifying the velocity and position iterations. For the velocity and positon iterations, the values can be altered to meet your needs. Lower will yield better performance, higher will yield better accuracy.

So, now you have a world with nothing in it. What fun is that? We'll need to add some stuff and start crashing it into each other.

There are two type of objects you can create. Static objects, like the triangle above, are fixed in the space. They are not affected by gravity or other objects. Dynamic objects are the fun ones that you get to move around. Our circles above are created and then nudged slightly to make them fall on either side of the triangle.

Triangle

var fixDef = new b2FixtureDef;
fixDef.shape = new b2PolygonShape;
fixDef.density = 1.0;
fixDef.friction = 0.5;
fixDef.restitution = .5;
         
fixDef.shape.SetAsArray([
    new b2Vec2(-1, 0),
    new b2Vec2(0, -1),
    new b2Vec2(1, 0)],3
);

var bodyDef = new b2BodyDef;
bodyDef.type = b2Body.b2_staticBody;    
bodyDef.position.Set(7, 7);
world.CreateBody(bodyDef).CreateFixture(fixDef);

Circle

//Same fixture density, friction and restitution from above.
fixDef.shape = new b2CircleShape(.5);
bodyDef.position.Set(7,0);
var body=world.CreateBody(bodyDef);
body.CreateFixture(fixDef);

I mentioned above that I'm nudging the circles. In order to push the shapes, we can use the ApplyImpulse method. It needs two parameters, a vector defining the force to be applied and a point that it should be applied to. Take a moment to go poke around in the fiddle and change the vector for the impulse. You can do some fun stuff like punch them straight up in the air. Go ahead, I'll wait.

There is one last bit you'll need to get your own samples going. All of the code we've done above describes the objects and their interactions. We still need a way to visualize it though. Luckily box2dweb has a debug drawing mode to render the objects on a canvas element. Here's what you need to set it up:

var debugDraw = new b2DebugDraw();
debugDraw.SetSprite(document.getElementById("playground").getContext("2d"));
debugDraw.SetDrawScale(20.0);
debugDraw.SetFillAlpha(0.5);
debugDraw.SetLineThickness(1.0);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit);
world.SetDebugDraw(debugDraw);

With that, all that is left is to call world.DrawDebugData() right after you step. Now we can see our demolition derby in action!

I think that covers the basics. There is a lot of fun things you can do with the sample. Try changing the restitution (bounciness), the force of gravity, the direction of gravity, which direction you "nudge" the falling circles... heck, just start changing stuff and watch. It's way more fun than it should be.