Quick Box2D

Actionscript:
  1. [SWF(backgroundColor = 0x333333)]
  2.  
  3. import com.actionsnippet.qbox.*;
  4.  
  5. // setting debug = true, will use the Box2D debug rendering
  6. var sim:QuickBox2D=new QuickBox2D(this, {debug:false, gravityY:10});
  7.  
  8. // creates static boxes on all sides of the screen
  9. sim.createStageWalls({lineAlpha:0, fillColor:0xFF9900});
  10.  
  11. // add 25 boxes
  12. for (var i:int = 0; i<25; i++){
  13.     var xp:Number = 3 + (i % 5);
  14.     var yp:Number = 1 + int( i / 5);
  15.     sim.addBox({x:xp, y:yp, width:1, height:1, fillColor: i * 10 <<16, lineAlpha:0, angularDamping:5});
  16. }
  17.  
  18. sim.addBox({x:7, y:10, width:3, height:.2, angle:-.3, density:0,lineAlpha:0, fillColor:0xFF9900});
  19.  
  20. sim.addCircle({x:3, y:14, radius:2, fillColor:0xCC0000, lineColor:0x333333});
  21.  
  22. sim.addPoly({x:13, y:5, verts:[[1,0,2,2,1,1.33],[1,0,1,1.33,0,2]], angle: .4, density:1});
  23.  
  24. // begins the simulation
  25. sim.start();
  26.  
  27. // all non-static objects can be dragged
  28. sim.mouseDrag();

I've been messing with Box2D for the past few weeks - I decided to create a library (QuickBox2D) for quick prototyping. This snippet makes use of this library, so in order to run it you'll need to download the zip included at the end of this post...

If you don't already know, Box2D is a great physics library created by Erin Catto. It was ported to AS3 by Matthew Bush and John Nesky. You can download the AS3 version of the library here.

Today's snippet creates this swf (click any image to view demo):

QuickBox2D

QuickBox2D simplifies Box2D instantiation and makes it easy to skin rigid bodies with Library assets... normally you need to do something like this to create a box in Box2D:

Actionscript:
  1. var bodyDef:b2BodyDef = new b2BodyDef();
  2. bodyDef.position.Set(3, 3);
  3. var boxDef:b2PolygonDef = new b2PolygonDef();
  4. boxDef.SetAsBox(1, 1);
  5. boxDef.density = 1;
  6. var body:b2Body = w.CreateBody(bodyDef);
  7. body.CreateShape(boxDef);
  8. body.SetMassFromShapes();

and this doesn't include setting up the physics world and the main loop to run the simulation... after writing a good deal of repetitive code I decided to make QuickBox2D. After writing lots of QuickBox2D style instantiation I decided to create an editor so that I could just draw circles, boxes, polygons and joints and then test and save them in real time (will be posting this editor in the near future). The next few posts will be about this mini-library and I'll be writing up some real documentation for it... as of now, it doesn't have any...

You can download Box2D here

You can download QuickBox2D here

and you can view some AS3 Box2D demos here

This entry was posted in QuickBox2D, motion and tagged , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

13 Comments

  1. Brendan Lee
    Posted April 30, 2009 at 2:54 pm | Permalink

    Thanks ! I have something I quickly put together here:

    http://yourcall.ribbit.com/

    it’s kinda crummy ( my first Box2D project ) but I have a lot of love for the library!

    thanks for this…

    b

  2. Posted April 30, 2009 at 6:10 pm | Permalink

    cool! Yeah, Box2D is just plain awesome :)

  3. Brendan Lee
    Posted May 9, 2009 at 5:41 pm | Permalink

    Quick Question -

    I am trying to add a feature to your framework to move the “simulation boundary” boxes on stage resize firing.

    I can think of two options, the better ( in my opinion) being just physically moving them or affecting width | height on them on RESIZE ( them being the stage walls )

    How does this affect the Box2D world? It seems to not acknowledge when I move the boundaries … I guess I don’t know enough about it to know if this is breaking the simulation or not.

    It was also really hackish for me to crack into the y / x / width / height properties, if you might be able to suggest a better way, im all ears.

    *** WARNING THIS IS SUPER HACK CODE, I WAS JUST TRYING TO ACCESS THE PROPERTIES ****

    package util {

    import com.actionsnippet.qbox.*;
    import flash.display.*;

    public class DyBox2D extends QuickBox2D {

    // Constants:
    // Public Properties:
    // Private Properties:

    // Initialization:
    private var ceiling:QuickObject;
    private var rightwall:QuickObject;
    private var leftwall:QuickObject;
    private var floor:QuickObject;

    public function DyBox2D(main:MovieClip, param:Object=null)
    {
    super(main, param);

    }

    override public function createStageWalls(p:Object=null):void{
    var defaults:Object = {lineColor:0×000000, lineAlpha:1, fillColor:0xCCCCCC, fillAlpha:1};
    if (p == null){
    p = new Object();
    }

    for (var key:String in defaults){
    if (p[key] == null){
    p[key] = defaults[key];
    }
    }
    var sw:Number = main.stage.stageWidth / 30;
    var sh:Number = main.stage.stageHeight / 30;

    floor=addBox({x:sw / 2, y:sh, width:sw - 1, height:1, density:.0, lineColor: p.lineColor, lineAlpha: p.lineAlpha, fillColor: p.fillColor, fillAlpha: p.fillAllpha});
    leftwall=addBox({x:sw / 2, y:0, width:sw - 1, height:1, density:.0, lineColor: p.lineColor, lineAlpha: p.lineAlpha, fillColor: p.fillColor, fillAlpha: p.fillAllpha});
    ceiling=addBox({x:0, y:sh / 2, width:1, height:sh , density:.0, lineColor: p.lineColor, lineAlpha: p.lineAlpha, fillColor: p.fillColor, fillAlpha: p.fillAllpha});
    rightwall=addBox({x:sw, y:sh / 2, width:1, height:sh , density:.0, lineColor: p.lineColor, lineAlpha: p.lineAlpha, fillColor: p.fillColor, fillAlpha: p.fillAllpha});
    }

    public function moveStageWalls():void
    {

    var sw:Number = main.stage.stageWidth / 30;
    var sh:Number = main.stage.stageHeight / 30;

    //ceiling
    ceiling.bodyDef.position.y = sh / 2;
    ceiling.bodyDef.position.x = 0;
    ceiling.bodyDef.userData.width = 1;
    ceiling.bodyDef.userData.height = sh;

    //leftwall
    leftwall.bodyDef.position.y = 0;
    leftwall.bodyDef.position.x = sw / 2;
    leftwall.bodyDef.userData.width = sw - 1;
    leftwall.bodyDef.userData.height = 1;

    rightwall.bodyDef.position.y = sh/2;
    rightwall.bodyDef.position.x = sw;
    rightwall.bodyDef.userData.width = 1;
    rightwall.bodyDef.userData.height = sh;

    floor.bodyDef.position.y = sh;
    floor.bodyDef.position.x = sw / 2;
    floor.bodyDef.userData.width = sw - 1;
    floor.bodyDef.userData.height = 1;

    }

    // Public Methods:
    // Protected Methods:
    }

    }

    *** AND HERE IS HOW IM CALLING IT ***

    private function resizeHandler(event:Event):void {
    //trace(”resizeHandler: ” + event);
    //trace(”stageWidth: ” + stage.stageWidth + ” stageHeight: ” + stage.stageHeight);

    sim.moveStageWalls();

    }

    sorry if this seems spammy, any advice is much appreciated -

    b

  4. Posted May 10, 2009 at 10:18 am | Permalink

    This should do the trick. Problem is that as far as I know you can’t resize rigid bodies in Box2D you need to destroy and recreate them:

    import com.actionsnippet.qbox.*;

    // setting debug:true, will use the Box2D debug rendering
    var sim:QuickBox2D = new QuickBox2D(this, {debug:true, gravityY:10});

    var box:QuickObject = sim.addBox({x:3, y:3, width:1, height:1});

    var resizing:Boolean = false;
    var walls:Array = new Array();
    stage.align=StageAlign.TOP_LEFT;
    stage.addEventListener(Event.RESIZE, onResizeStage);
    onResizeStage();
    function onResizeStage(evt:Event=null):void{
    var sw:Number = stage.stageWidth / 30;
    var sh:Number = stage.stageHeight / 30;

    // you could also stop the simulation sim.stop()
    // and only draw the walls once rather than over and over
    updateWalls();
    // you’ll need to loop through and do this to all bodies
    if (box.x > sw){
    box.x = sw - .5;
    }
    if (box.y > sh){
    box.y = sh - .5;
    }
    }

    function updateWalls():void{
    for (var i:int = 0; i if (walls[i]){
    walls[i].destroy();
    }
    }
    var sw:Number = stage.stageWidth / 30;
    var sh:Number = stage.stageHeight / 30;
    walls[0] = sim.addBox({x:sw / 2, y:sh, width:sw - 1, height:1, density:.0});
    walls[1] = sim.addBox({x:sw / 2, y:0, width:sw - 1, height:1, density:.0});
    walls[2] = sim.addBox({x:0, y:sh / 2, width:1, height:sh , density:.0});
    walls[3] = sim.addBox({x:sw, y:sh / 2, width:1, height:sh , density:.0});
    }

    // begins the simulation
    sim.start();
    sim.mouseDrag();

  5. Brendan Lee
    Posted May 10, 2009 at 3:07 pm | Permalink

    Thanks Zevan !

    * as a ” further reading ” resource for anyone that happens upon this thread -

    http://www.box2d.org/wiki/index.php?title=Manual/AS3

  6. Posted May 18, 2009 at 11:42 am | Permalink

    thanks for you help, I used if for a super simple site for a very subtle effect, check out the results:

    http://brendanlee.org/

  7. Posted May 18, 2009 at 11:51 am | Permalink

    No problem. Nice work. Cool site.

  8. Posted June 8, 2009 at 4:51 pm | Permalink

    This is the kind of wrapper that you keep doing again and again every time you start a project that uses box2D. Good idea to get done with a reusable one!

    Having said that, a very interesting feature this could have would be to be able to turn the simulation in realtime mode.

    Usually the problem with box2d is that the same simulation will go faster or slower depending of the cpu power. Making it go realtime would be to keep it synchronised with the timer, doing as many world.steps as needed to catch up on the desired simulation. And interpolate the positions if needed. This will make all simulations run at the same time in any machine, but only the fps will change.

  9. Posted June 9, 2009 at 8:33 am | Permalink

    That’s a good idea - I’ll give it a try… I think I recall seeing something about this on the Box2D forums…. (googling)

    Yeah, here it is. Thanks for the suggestion :)

  10. Larsen
    Posted June 11, 2009 at 9:40 pm | Permalink

    Hi there,

    is it possible to scaleUp or scaleDown the created QuickObjects at runtime.

    When I start my application all QuickObjects should growUp to a bigger size.

    Thanks for any suggestions…

  11. Posted June 12, 2009 at 3:28 pm | Permalink

    Hey Larsen,

    Unfortunately the only way to scale Box2D objects is to destroy them and re-create them…. have a look at some of the comments above and that should help..

  12. Andrew
    Posted March 7, 2010 at 10:25 pm | Permalink

    This should do the trick. Problem is that as far as I know you can’t resize rigid bodies in Box2D you need to destroy and recreate them:

    import com.actionsnippet.qbox.*;

    // setting debug:true, will use the Box2D debug rendering
    var sim:QuickBox2D = new QuickBox2D(this, {debug:true, gravityY:10});

    var box:QuickObject = sim.addBox({x:3, y:3, width:1, height:1});

    var resizing:Boolean = false;
    var walls:Array = new Array();
    stage.align=StageAlign.TOP_LEFT;
    stage.addEventListener(Event.RESIZE, onResizeStage);
    onResizeStage();
    function onResizeStage(evt:Event=null):void{
    var sw:Number = stage.stageWidth / 30;
    var sh:Number = stage.stageHeight / 30;

    // you could also stop the simulation sim.stop()
    // and only draw the walls once rather than over and over
    updateWalls();
    // you’ll need to loop through and do this to all bodies
    if (box.x > sw){
    box.x = sw - .5;
    }
    if (box.y > sh){
    box.y = sh - .5;
    }
    }

    function updateWalls():void{
    for (var i:int = 0; i if (walls[i]){
    walls[i].destroy();
    }
    }
    var sw:Number = stage.stageWidth / 30;
    var sh:Number = stage.stageHeight / 30;
    walls[0] = sim.addBox({x:sw / 2, y:sh, width:sw - 1, height:1, density:.0});
    walls[1] = sim.addBox({x:sw / 2, y:0, width:sw - 1, height:1, density:.0});
    walls[2] = sim.addBox({x:0, y:sh / 2, width:1, height:sh , density:.0});
    walls[3] = sim.addBox({x:sw, y:sh / 2, width:1, height:sh , density:.0});
    }

    // begins the simulation
    sim.start();
    sim.mouseDrag();

    ……………………………………………………………………………………………
    function updateWalls():void{
    for (var i:int = 0; i if (walls[i]){
    walls[i].destroy();
    }
    }
    ……………………………………………………………………………………………
    i canot work it out.is that wrong?

  13. d
    Posted October 23, 2010 at 3:09 am | Permalink

    thanks, looking forward to trying it out - appreciate it.

    d

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*