How to Implement Box2D in Adobe AIR?

By | February 4, 2011

Everyone will be fascinated how flash games are built on the web that implements the real world physics. Well for your information there are a lot of physics engines available.
One of them is the Box2D. Box2D was written in C++. Then it was converted to flash.

So now I am going to show you how to build these games on your desktop.
For this you need the Adobe Flashbuilder 4.
Download it from here http://www.adobe.com/products/flashbuilder/
And follow these steps.

1. First you have to download the Box2D library for flash.
2. Create a Flex Project for the desktop(i.e for Adobe AIR) and name it “Test”.
3. Create a folder named libs inside the project folder.
4. Right click on the libs and import the downloaded Box2D swc into it.
Or Right click on the project folder and click properties, add swc folder named libs which
contains your Box2D library for flash. After that a folde named “Referenced Libraries” will
appear.
See the figure below.

Now right click on the project folder and new-> Actionscript class-> name it “Ball” and press enter. A file named Ball.as will be created. Now copy the following code to this file.

/************************************** Ball.as ***********************************/

package
{
 import flash.display.Sprite;
 import flash.geom.Matrix;
 import mx.controls.Alert;

 public class Ball extends Sprite
 {
 private var mc:Sprite;
 public function Ball(radius:Number, color:Number = 0x660033)
 {
 super();
 mc = new Sprite();
 setRegistrationPoint( mc, mc.width >> 1, mc.height >> 1, true);
 mc.graphics.lineStyle(1, 0x000000);
 mc.graphics.beginFill(color);
 mc.graphics.drawCircle(0, 0, radius);
 mc.graphics.endFill();

 addChild(mc);
 }
 public function setRegistrationPoint(s:Sprite, regx:Number, regy:Number, showRegistration:Boolean) : void
 {
 s.transform.matrix = new Matrix(1, 0, 0, 1, -regx, -regy);
 if (showRegistration)
 {
 var mark:Sprite = new Sprite();
 mark.graphics.lineStyle(1, 0x000000);
 mark.graphics.moveTo(-5, -5);
 mark.graphics.lineTo(5, 5);
 mark.graphics.moveTo(-5, 5);
 mark.graphics.lineTo(5, -5);
 s.addChild(mark);
 }
 }
 }
}

Now copy the below code to Test.MXML

    xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:mx="library://ns.adobe.com/flex/mx" applicationComplete="init()">


   import mx.controls.Alert;
   import mx.core.UIComponent;
   import flash.display.Sprite;
   import flash.events.Event;
   import flash.events.MouseEvent;
   import flash.display.Stage;
   import Box2D.Dynamics.*;
   import Box2D.Collision.*;
   import Box2D.Collision.Shapes.*;
   import Box2D.Common.Math.*;

   public var the_ball:Ball;
   public var main:Main;
   public var m_dbgSprite:Sprite;
   public var m_world:b2World;
   public var m_phys_scale:Number = 30;
   public var m_timestep:Number = 1.0/30.0;
   public var m_iterations:N umber = 10.0;

   //initial box coordinates when we first press mouse down
   public var initX:Number = 0.0;
   public var initY:Number = 0.0;
   public var drawing:Boolean = false;
   public var b:b2Body;
   private var colorArray:Array = new Array(0xFFFF33, 0xFFFFFF, 0x79DCF4, 0xFF3333, 0xFFCC33, 0x99CC33);

   public function init():void{

    var gravity:b2Vec2 = new b2Vec2(0,9.8);
    var worldAABB:b2AABB = new b2AABB();
    worldAABB.lowerBound.Set(-1000,-1000);
    worldAABB.upperBound.Set(1000,1000);
    m_world = new b2World(worldAABB,gravity,true);

    //Add our ground and walls
    addStaticBox(250/m_phys_scale,510/m_phys_scale,250/m_phys_scale,10/m_phys_scale);
    addStaticBox(250/m_phys_scale,-10/m_phys_scale,250/m_phys_scale,10/m_phys_scale);
    addStaticBox(-10/m_phys_scale,250/m_phys_scale,10/m_phys_scale,250/m_phys_scale);
    addStaticBox(510/m_phys_scale,250/m_phys_scale,10/m_phys_scale,250/m_phys_scale);

    addEventListener(Event.ENTER_FRAME, update);
    stage.addEventListener(MouseEvent.MOUSE_DOWN,mousePressed);
    stage.addEventListener(MouseEvent.MOUSE_MOVE,mouseMoved);
    stage.addEventListener(MouseEvent.MOUSE_UP,mouseReleased);

    var dbgDraw:b2DebugDraw = new b2DebugDraw();
    var dbgSprite:Sprite = new Sprite();
    var ui:UIComponent = new UIComponent();
    ui.addChild(dbgSprite);
    this.addElement(ui);
    //addChild(dbgSprite);
    dbgDraw.m_sprite = dbgSprite;
    dbgDraw.m_drawScale = 20.0;
    dbgDraw.m_fillAlpha = 0.0;
    dbgDraw.m_lineThickness = 1.0;
    //dbgDraw.m_drawFlags = 0xFFFFFFFF;
    //dbgDraw.m_drawFlags=b2DebugDraw.e_shapeBit|b2DebugDraw.e_jointBit|b2DebugDraw.e_coreShapeBit|b2DebugDraw.e_aabbBit|b2DebugDraw.e_obbBit|b2DebugDraw.e_pairBit|b2DebugDraw.e_centerOfMassBit;

    m_world.SetDebugDraw(dbgDraw);
   }
   public function mousePressed(e:MouseEvent) : void {
    //Store initial X and Y position
    initX = e.localX;
    initY = e.localY;

    var randomColorId:Number = Math.floor(Math.random()*colorArray.length);

    the_ball = new Ball(50, colorArray[randomColorId]);

    the_ball.x = mouseX;
    the_ball.y = mouseY;
    the_ball.width = 1;
    the_ball.height = 1;
    var ui:UIComponent = new UIComponent();
    ui.addChild(the_ball);
    this.addElement(ui);

    drawing = true;
   }
   public function mouseMoved(e:MouseEvent) : void {
    if (drawing) {
     the_ball.x = mouseX;
     the_ball.y = mouseY;
    }
   }
   public function mouseReleased(e:MouseEvent) : void {
    drawing = false;
    addCircle( mouseX,  mouseY, the_ball.width/2,the_ball);
   }
   public function addCircle(_x:Number, _y:Number, _radius:Number, ballclip:Ball) : void {
    var bd:b2BodyDef = new b2BodyDef();
    var cd:b2CircleDef = new b2CircleDef();
    var area:Number = Math.floor(_radius*_radius*Math.PI/25)/100;

    cd.radius = Math.abs(_ra dius)/m_phys_scale;
    cd.density = 2;
    cd.restitution = 0.7;
    cd.friction = 2;
    bd.position.Set(_x/m_phys_scale, _y/ m_phys_scale);
    bd.userData = ballclip;
    b = m_world.CreateBody(bd);
    b.CreateShape(cd);
    b.SetMassFromShapes();
   }
   public function addStaticBox(_x:Number,_y:Number,_halfwidth:Number,_halfheight:Number) : void {
    var bodyDef:b2BodyDef = new b2BodyDef();
    bodyDef.position.Set(_x,_y);
    var boxDef:b2PolygonDef = new b2PolygonDef();
    boxDef.SetAsBox(_halfwidth,_halfheight);
    boxDef.density = 0.0;
    var body:b2Body = m_world.CreateBody(bodyDef);
    body.CreateShape(boxDef);
    body.SetMassFromShapes();
   }
   public function update(e:Event) : void {
    //We need to do this to simulate physics
    if (drawing) {
     the_ball.width+=2;
     the_ball.height+= 2;
    }
    m_world.Step(m_timestep,m_iterations);
    for (var bb:b2Body=m_world.m_bodyList; bb; bb=bb.m_next) {
     if (bb.m_userData is Sprite) {
      bb.m_userData.x=bb.GetPosition().x * 30;
      bb.m_userData.y=bb.GetPosition().y * 30;
      bb.m_userData.rotation=bb.GetAngle() * 180 / Math.PI;
     }
    }
   }
  ]]>
 

If you have errors that you can’t find in your file then go to window-> problems. Look for the problem.
If the problem is about the SDK . then right click on the project folder and properties and change the default SDK to FLEX 4.

2 thoughts on “How to Implement Box2D in Adobe AIR?

  1. karthik

    Unable to locate specified base class 'spark.components.WindowedApplication' for component class 'Test'. Test.mxml /Test/src Unknown Flex Problem __________——what can i do for this sir..

    Reply
  2. Mr. Coder

    Which SDK are you using?
    Are you using Flex Builder instead of Flash Builder?
    If you are using Flash builder then right click on the project and go to properties and change the SDK to 4.1
    The spark components were introduced in SDK 4.1
    It's not in the older SDK less than 4.1.
    Let me know if you are getting any errors then.

    Reply

Leave a Reply to karthik Cancel reply

Your email address will not be published. Required fields are marked *