white space for now

 
« Back to blog

Fun with Curves and Box2D

(download)

So I finally got around to learning Box2D to help me prototype a skeeball game. It sucks there is barely any info on version 2.1, so I'll probably have to learn both versions for now. There's a surprising lack of info on drawing arcs/curves in general, so I thought I should share what I've figured out for v2.1 even though no one will ever read this :). There is an SVG parser for 2.0, which looks awesome, but for basic curves you can just loop through some points and apply it to a b2EdgeChainDef. First, I grabbed an arc drawing function from this wonderfully altruistic person. Second, I pushed the x and y coordinates into the b2EdgeChainDef.vertices array. Somehow I figured out to use the SetAsArray method on the b2PolgyonShape passing in those coordinates and set everything else as normally. You get nice curves in the debug draw, though the bigger the radius, the more dot-like the arc will be, but it doesn't seem to matter.

In the movie above (refresh to watch the ball motion), I needed 3 arcs: a big bottom rim, a smaller rim, and an outer facing rim. Seriously, if there is an easier way to create an empty shape, please tell me. As far as I know, there's no easy way to create an ellipse, so I overlap the 2 top arcs to simulate one. I'll keep the curved sprite in there so you can see it looking prettier than the debug draw output.

In the constructor:

_curve = new Sprite();
addChild(_curve);
_curve.graphics.lineStyle(10,0xFFFFFF,1);
drawArc(_curve,125,160,125,20,160,1);  //big bottom arc
drawArc(_curve,125,130,70,20,160,1); //middle bottom arc
drawArc(_curve,125,157,65,180,360,1); //top arc

In the body:

public function drawArc(sprite:Sprite, center_x:Number, center_y:Number, radius:Number, angle_from:Number, angle_to:Number, precision:Number):void {
            var angle_diff:Number=angle_to-angle_from;
            var steps:Number=Math.round(angle_diff*precision);
            var angle:Number=angle_from;
            var px:Number=center_x+radius*Math.cos(angle* Math.PI/180);
            var py:Number=center_y+radius*Math.sin(angle* Math.PI/180);

            sprite.graphics.moveTo(px,py);
           
            var chainDef:b2EdgeChainDef=new b2EdgeChainDef;
            chainDef.isALoop=false;
            chainDef.vertices.length=0;

            var chainShape:b2PolygonShape = new b2PolygonShape();
            var chainBodyDef:b2BodyDef = new b2BodyDef();

            var my_fixture:b2FixtureDef = new b2FixtureDef();
            my_fixture.friction = 0.5;
            my_fixture.restitution = 0.0;
            my_fixture.density = 0.0;
            my_fixture.userData = "vertex";

            var chainBody:b2Body;
            var vertexList:Array;
           
            for (var i:int=1; i<=steps; i++) {
                angle=angle_from+angle_diff/steps*i;
                px=center_x+radius*Math.cos(angle* Math.PI/180);
                py=center_y+radius*Math.sin(angle* Math.PI/180);
              
               sprite.graphics.lineTo(px,py); //non-box2D curve is drawn here
               
                vertexList=[{x:px,y:py}, {x:px+1,y:py-1}]; /// not sure the best way to handle the second b2Vec2, but you get interesting shapes when you play with the numbers
                for (var j:int=0; j < vertexList.length; j++) {
                       chainDef.vertices.push(new b2Vec2(vertexList[j].x / 30,vertexList[j].y / 30));
                }
                chainDef.vertexCount=chainDef.vertices.length;            
                chainShape.SetAsArray(chainDef.vertices, chainDef.vertexCount);           
                my_fixture.shape = chainShape;           
                chainBody = world.CreateBody(chainBodyDef);
                chainBody.CreateFixture(my_fixture);
               
                //clear the arrays
                vertexList.splice(0);
                chainDef.vertices.splice(0);
            }
           
        }

 

Comments (3)

Oct 24, 2011
Anton said...
b2EdgeChainDef is useless in this code
Oct 24, 2011
Gina Binetti said...
how else would you provide the coordinates for the points in the chainBody and use them to set the shape of its fixture? Note that I ask if there is a better way, please provide.
Oct 24, 2011
chainDef is used as temporary holder of points and length. You can use just one array of b2Vec2.

Actualy I am working on this right now, searching web for info how to make edge chain in Box2d v2.1 and found nothing so far. I think b2EdgeChainDef is strange class. May be it has present in Box2d by mistake ? Nobody used this class.

Leave a comment...