agaskar.com

Apr 17 2008

Box2D AS3 HelloWorld boxDef extents ‘issue’.

You may have, like me, been very excited to use the AS3 Box2D library in a couple of little Flash experiments. You may have also, again, as I did, immediately pulled out the default Sprites that the HelloWorld example runs with and replaced them with your own (possibly drawn on the fly), only to find that nothing worked properly. Debugging the problem, after the jump. Is it the extents? Well, I suppose it *could* be — that was surely my first suspect. The best explanation of the extents I could find was in Paul Schoneveld’s post explaining Box2D on clickpopmedia’s site. Paul writes:

First we have the b2BoxDef class. The b2BoxDef has 4 important properties: 1.) Extents - this is a vector that essentially goes from one corner of the box to the exact center. In other words, half the width and hight. (box is a rectangle) 2.) Density - in the collision equations we use density * area = mass A density of 0 (zero) or null will make the object static and it will never move in the case of a collision or gravity. 3.) Friction - this is used to calculate the friction between 2 objects… you should keep it between 0.0 and 1.0 4.) Restitution - this is the bounciness of the object. Should probably also stay between 0.0 and 1.0
Regardless of adhering to half-the-object’s width and half-the-objects height as a guideline for the extents setting, I was still getting strange behavior. Falling objects seemed to fall through halfway through my ground object (constructed of a Sprite.roundRect 300 pixels long by 20 pixels high) on the solid side to the right, and bounce, then float in midair to the left. Looking back this should have been obvious, but it took me nearly an hour to figure out exactly what was going wrong, mostly because everything seemed to *almost* work (which, of course, is worse than simply not working at all). My initial code for my ground object was:
// Add ground body
            bodyDef = new b2BodyDef();
            boxDef = new b2BoxDef();
            boxDef.extents.Set(150, 10);
            boxDef.friction = 0.3;
            bodyDef.position.Set(300, 300);
            bodyDef.AddShape(boxDef);
            // Add sprite to body userData
            bodyDef.userData=new Sprite();
            bodyDef.userData.graphics.beginFill(0x335566);
            bodyDef.userData.graphics.drawRect(0,0,300,20);
            bodyDef.userData.graphics.endFill();
            addChild(bodyDef.userData);
            m_world.CreateBody(bodyDef);
Can you guess what my problem was? It’s quite possible this is one of the more obvious mistakes you can make in Flash, but it wasn’t my first thought. I ignored the registration point of the Sprite I created! This has bit me before in Flash — registration points for *many* Sprites are set at the upper left hand corner although when we think of modifications (rotation in particular), we often think that the registration point is in the center. I’m going to go out on a limb here and announce that for Sprites to work properly with Box2D, they MUST have CENTERED registration points. Fortunately, it’s fairly easy to center a registration point on a Sprite: simply set the X value to negative half the width, and the Y to negative half the height — this moves the Sprite by half towards the left and upwards, respectively, which means the registration point is now sitting dead center and will work just dandy with Box2D. With drawRect you can do this in one fell swoop by providing the negative x and y values along with the width and height, like so:
bodyDef.userData.graphics.drawRect(-150,-10,300,20); 
It’s easy to make a similar mistake with the Circle bodies, particularly if you’re still thinking along the lines of needing to ‘halve’ the width and heights. Both the drawCircle and b2CircleDef object take a radius, so it should be the same number in each case. Circles are also draw by the Flash graphics helper object with their registration point centered, rather than at the upper left, so you don’t need to offset any of the circular Sprites you draw. I found it’s quite easy to cascade a couple mistakes in defining bodies with Box2D and then have great difficulty telling where you went wrong from the resulting animation. Next time I’ll probably sanity check my reg points for each object before tweaking any other variables.

Comments (View)
Page 1 of 1
blog comments powered by Disqus