I’ve recently started working on a new game that uses box2d for it’s physics simulation and thought I’d share some of my finding so far.
First I created a prototype of the game to show proof of concept and also test performance. This involved building a simple level out of box2d objects and running it. The prototype was a success but building and positioning all the box2d objects in code was a slow process, I had intended to use DAME to draw my physics objects and add properties but after a quick search I found RUBE (Really Useful Box2d Editor).
As the name suggest RUBE is a “really useful box2d editor” and you would be crazy not to use such a tool when creating a box2d game. It exports to JSON which is awesome and it is built with QT which from what I have seen, creates some really nice cross-platform applications. There is a licence fee if you want to export your levels but at the price of a few pints of beer (London prices) you can’t go wrong (£15).
There is one downside to using RUBE when targeting JavaScript or Flash and that is based on their coordinate systems. Both JavaScript and Flash have an inverted Y-axis whilst RUBE doesn’t, this means the exported objects appear upside down. The developer of RUBE (I-Force Chris Campbell) suggests inverting the canvas context which is what he has done in the JavaScript examples. This works and with the helper/loader functions he provides for JavaScript you can have your simulation looking correct.
However, from what I can gather, this would mean I need to build all my menus and ui upside down which would just be crazy. So what I am currently doing is translating the “view” of my game objects so that they are using inverted versions of the box2d bodies. This has to be done every time to objects position is changed but is simple maths so the overhead should be minimal.
First invert and re-position the debug draw canvas:
// get the debug canvas var debugCanvas = document.getElementById( "debugCanvas" ); if ( debugCanvas ) { var ctx = debugCanvas.getContext( "2d" ); ctx.scale( 1, -1 ); ctx.translate( 0, - debugCanvas.height ); var debugDraw = new b2DebugDraw(); debugDraw.SetSprite( debugCanvas.getContext( "2d" ) ); debugDraw.SetDrawScale( 30 ); debugDraw.SetFillAlpha( 0.5 ); debugDraw.SetLineThickness( 0.5 ); debugDraw.SetFlags( b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit ); this.world.SetDebugDraw( debugDraw ); }
Then for all your views of the box2d objects, subtract the box2d position from the height of your canvas and invert any rotations:
var SCALE = 30; this.view.x = this._body.GetTransform().position.x * SCALE; this.view.y = canvas.height - ( this._body.GetTransform().position.y * SCALE ); this.view.rotation = - ( this._body.GetAngle() * ( 180 / Math.PI ) );
So far this technique seems to work fine, I have tested it on a few irregular bodies and a simple revolute joint. I will be testing more complex scenarios later so will see how it goes.
An alternative to this process would be to actually flip all the box2d objects. This sadly is not something that is build into box2d and would mean having to save the shapes vertices, translate the vertices and then destroy the shape and rebuild it with the new vertices. This should be simple enough but you would also have to do the same for all the joints and this may not be so simple. I hope to try this method because it would be nice to know everything is running at 1-1 but I am secretly hoping that I-Force will add an option to RUBE that allows you to export the world with an inverted y-axis… :)
Share Your Thoughts