I’m starting to love box2dweb.
I’ve been working on a revisions for the new edition of our O’Reilly book on the HTML5 Canvas, and I thought it would be nice to add some coverage of box2d to chapter 5 (Math and Physics).
There are two box2d implementations for JavaScript. The first is box2djs, and the other is box2dweb. Apparently box2dweb is the latest and greatest, so that is the one I chose to use.
At first, it took me a little while to understand what was going on. I kept wanting to attach images or drawing objects to the output from debugDraw, Then, all of a sudden, things clicked. box2dweb is simply a model of the physics. My job is to apply it to the Canvas.
One of the biggest hurdles with applying box2d models to the Canvas is that box2d uses mts units (metre–tonne–second) instead of pixels. This complicates applying models the Canvas because, for 2D game developers, pixels are a way of life. Since mts units are designed to apply to the real world (which is good for physics) I needed a way to convert those units to pixels to then apply them to the Canvas.
After a bit of trial and error, I came up with a factor of 30.
var scaleFactor = 30;
To create the walls that bound the Canvas (the walls that the balls bounce off of) I would do something like this. notice, these are in pixels relative the Canvas.
var wallDefs = new Array(
{x:theCanvas.width,y:0,w:theCanvas.width ,h:1}, //top {x:theCanvas.width,y:theCanvas.height,w:theCanvas.width ,h:1}, //bottom {x:0,y:theCanvas.height,w:1 ,h:theCanvas.height}, //left {x:theCanvas.width,y:theCanvas.height,w:1 ,h:theCanvas.height}
); //right
When I go to define my walls in box2dweb, I apply the scaleFactor to size and position of walls using division.
var walls = new Array(); for (var i = 0; i <wallDefs.length; i++) { ... wallDef.position.Set(wallDefs[i].x/scaleFactor, wallDefs[i].y/scaleFactor); ... wallFixture.shape.SetAsBox(wallDefs[i].w/scaleFactor, wallDefs[i].h/scaleFactor); }
When I go to draw my objects on the Canvas, I multiply the mts units in box2dweb by scaleFactor, so I know the size and position of my objects relative to the the Canvas.
context.arc(position.x * scaleFactor , position.y * scaleFactor ,shape.GetRadius() *scaleFactor ,0,Math.PI*2,true);
Depending on your application, this factor will probably need to be adjusted based on the scale of the world you are simlulating.
To test to make sure all of this works, I make sure to set the debugDraw scale to 30 as well:
debugDraw.SetDrawScale(scaleFactor);
Below is the a screen shot of the bouncing balls demo using two canvases (I can’t post the code yet because it is for the new book). The first shows the canvas version of the demo, and the second shows the debugDraw() version.