Monday, December 24, 2012

Box2D in Flash and AS3.. explained for beginners Part 3

For Part one Click here
For Part two Click here

That's what we have done till now


If you have seen the demo in the first part of this series you can see that we can't shoot the player unless it's on the ground, also we added some more walls in the scene and so in this tutorial we will be creating more walls and limit the shooting to only on the ground.

Creating more walls

We would need also to create one more thing and that is to set the returned b2Body for the creation of the wall that represents the ground to a ground object, so let's define that ground first

private var ground:b2Body;

In the init method

public function init(e:Event = null):void
{  
    
    createWorld();
    
    player = createPlayer(40, 50, 50, 10);
    
    addEventListener(Event.ENTER_FRAME, update);
    stage.addEventListener(MouseEvent.CLICK, stageClicked);
    
    var th:uint = 10;
    // Vertical walls
    createWall(0, 0                    , th, stage.stageHeight);
    createWall(stage.stageWidth - th, 0, th, stage.stageHeight);
    // Horizontal walls
    createWall(0, 0                     , stage.stageWidth, th);
    ground = createWall(0, stage.stageHeight - th, stage.stageWidth, th);
    
    createWall(200, 300 , th, 100);
    createWall(350, 300 , th, 100);
    createWall(250, th , th, 200);

}

You can see how easy and fast it's to create walls using our createWall method.

Shooting player when only on the ground

What we would like to do here is when the mouse is clicked we need to check if the player is colliding with the ground or not to allow shooting.
Each b2Body has a list of bodies that it's in contact with, we will loop through them and check if one of them is the ground to execute the shooting algorithm.

for (var contact:b2ContactEdge = player.GetContactList(); contact; contact = contact.next) 
{
    if (contact.other == ground)
    {
        var force_x:Number = (mouseX / PM - player.GetPosition().x);
        var force_y:Number = (mouseY / PM - player.GetPosition().y);
        
        var force:b2Vec2 = new b2Vec2(force_x, force_y);
        force.Multiply( 2 / 3 );
        player.ApplyImpulse(force, player.GetPosition());
    }
}

That loop looks like the one in the second part of this series, GetContactList() method gets the first contactEdge in the list and saves the next contactEdge in the "next" variable.
We have checked if the ground is the same as the b2body object saved in the "other" variable, "other" means the other body that is in contact with the player.

Part 3 All come together

The final code

public class Main extends MovieClip
{
    
    public static var world:b2World;
    public static const PM:uint = 30;
    private var player:b2Body;
    private var ground:b2Body;
    
    public function Main() 
    {
        if (stage) init();
        else addEventListener(Event.ADDED_TO_STAGE, init);
    }
    
    public function init(e:Event = null):void
    {  
        
        createWorld();
        
        player = createPlayer(40, 50, 50, 10);
        
        addEventListener(Event.ENTER_FRAME, update);
        stage.addEventListener(MouseEvent.CLICK, stageClicked);
        
        var th:uint = 10;
        // Vertical walls
        createWall(0, 0                    , th, stage.stageHeight);
        createWall(stage.stageWidth - th, 0, th, stage.stageHeight);
        // Horizontal walls
        createWall(0, 0                     , stage.stageWidth, th);
        ground = createWall(0, stage.stageHeight - th, stage.stageWidth, th);
        
        createWall(200, 300 , th, 100);
        createWall(350, 300 , th, 100);
        createWall(250, th , th, 200);
    }
    
    public function stageClicked(e:MouseEvent):void
    {
        for (var contact:b2ContactEdge = player.GetContactList(); contact; contact = contact.next) 
        {
            if (contact.other == ground)
            {
                var impulse_x:Number = (mouseX / PM - player.GetPosition().x);
                var impulse_y:Number = (mouseY / PM - player.GetPosition().y);
                
                var impulse:b2Vec2 = new b2Vec2(impulse_x, impulse_y);
                impulse.Multiply( 2 / 3 );
                player.ApplyImpulse(impulse, player.GetPosition());
            }
        }
    }
    
    public function update(e:Event):void
    {
        world.Step(1 / 30, 10, 10);
        var temp:Sprite;
        for (var body:b2Body = world.GetBodyList(); body != null; body = body.GetNext())
        {
            if (body.GetUserData())
            {
                temp = body.GetUserData() as Sprite;
                temp.x = body.GetPosition().x * PM;
                temp.y = body.GetPosition().y * PM;
                temp.rotation = body.GetAngle() * (180 / Math.PI); // radians to degrees
            }
        }
    }
    
    public function createWorld():void
    {
        var gravity:b2Vec2 = new b2Vec2(0, 9.8);
        var sleep:Boolean = true;
        
        world = new b2World(gravity, sleep);
    }
    
    public function createWall(_x:Number, _y:Number, _width:Number, _height:Number):b2Body
    {    
        _x = _x + _width / 2;
        _y = _y + _height / 2;
        
        // Create Wall Sprite Using code
        var wallSprite:Sprite = new Sprite();
        wallSprite.graphics.beginFill(0xe7d7c0, 1);
        wallSprite.graphics.drawRect( -_width / 2, -_height / 2 , _width, _height);
        wallSprite.graphics.endFill();
        wallSprite.x = _x;
        wallSprite.y = _y;
        addChild(wallSprite);
        
        // Create body definition
        var bodyDef:b2BodyDef = new b2BodyDef();
        bodyDef.userData = wallSprite;
        bodyDef.type     = b2Body.b2_staticBody;
        bodyDef.position.Set( _x / PM, _y / PM);
        
        // Create body from world using bodyDef
        var body:b2Body = world.CreateBody(bodyDef);
        
        // Create shape
        var shape:b2PolygonShape = new b2PolygonShape();
        shape.SetAsBox((_width / 2) / PM, (_height / 2) / PM);
        
        // Create fixtureDef giving shape
        var fixtureDef:b2FixtureDef = new b2FixtureDef();
        fixtureDef.shape       = shape;
        fixtureDef.restitution = 0.2;
        fixtureDef.friction    = 1;
        fixtureDef.density     = 0.5;
        
        // Pass the fixtureDef to the createFixture method in the body object
        body.CreateFixture(fixtureDef);
        
        return body;
    }
    
    public function createPlayer(_x:Number , _y:Number, _width:Number, _height:Number):b2Body
    {
        // Create car sprite
        var carSprite:Sprite = new Sprite();
        carSprite.graphics.beginFill(0xafafaf, 1);
        carSprite.graphics.drawRect( -_width / 2, -_height / 2 , _width, _height);
        carSprite.graphics.endFill();
        carSprite.x = _x;
        carSprite.y = _y;
        addChild(carSprite);
        
        // Create body definition
        var bodyDef:b2BodyDef = new b2BodyDef();
        bodyDef.userData = carSprite;
        bodyDef.type     = b2Body.b2_dynamicBody;
        bodyDef.position.Set(_x / PM, _y / PM);
        
        // Create body from world using bodyDef
        var body:b2Body = world.CreateBody(bodyDef);
        
        // Create shape
        var shape:b2PolygonShape = new b2PolygonShape();
        shape.SetAsBox(_width / 2 / PM, _height / 2 / PM);
        
        // Create fixtureDef giving shape
        var fixtureDef:b2FixtureDef = new b2FixtureDef();
        fixtureDef.shape       = shape;
        fixtureDef.restitution = 0.2;
        fixtureDef.friction    = 1;
        fixtureDef.density     = 0.5;
        
        // Pass the fixtureDef to the createFixture method in the body object
        body.CreateFixture(fixtureDef);
        
        return body;
    }
    
}

Saturday, December 22, 2012

Box2D in Flash and AS3.. explained for beginners Part 2

For part one click here.
See the demo from here.

In this Part we will update the world, create some walls and apply impulse on the player when the mouse is clicked, so lets get started

Make things come alive!

We will do that by updating the box2D world every frame, first add an ENTER_FRAME event listener and create the handler method like this
public function init(e:Event = null):void
{    
    createWorld();
    
    player = createPlayer(40, 50, 50, 10);
        
    // When Clicking on stage
    stage.addEventListener(MouseEvent.CLICK, stageClicked);
    // Enter frame listener
    addEventListener(Event.ENTER_FRAME, update);
}
    
public function update(e:Event):void
{
    // This method will be called every frame and here where we will update 
    // the box2D world
}
Good, now to update the box2d world we need to call a method called Step on the world object
public function update(e:Event):void
{
    world.Step(1 / 30, 10, 10);
}
This method takes three parameters ( time step, velocity iterations , position iterations ) :
  1. Time step: we set it here to 1 / 30, which means every frame the world will step only 1 / 30 seconds, this will give a fairly good simulation and realistic collisions, decreasing this will increase the accuracy of the calculations of collisions but also will decrease the speed of the animation.
  2. Velocity iterations and position iterations: usually we set it to 10. You can set it to lower or higher. The consequences of setting it lower is less fine detail in the simulation, but a possible speed increase. The opposite is true of setting them higher.
If you tested the project now, nothing would change, why? Because the sprites position will not be updated with the box2d object, so we have to update all the displays referenced by the box2d objects in the enter frame handler.
But before doing that, lets first know how we can iterate through all bodies in a b2World
for (var body:b2Body = world.GetBodyList(); body != null; body = body.GetNext())
how is that possible? We all know that for statement requires 3 parts
for ( Initialization ; Condition; Afterthough )
We start off by getting the first body in the list using the GetBodyList method, we will keep looping as long as the body is not equal to null, and every iteration we will go to the next body in the list, see the figure below
Back to updating the sprites referenced by the box2d objects, what we are going to do is update the position and rotation of the sprites in the userData of each box2d body.
public function update(e:Event):void
{
    world.Step(1 / 30, 10, 10);
    var temp:Sprite;
    for (var body:b2Body = world.GetBodyList(); body != null; body = body.GetNext())
    {
        if (body.GetUserData())
        {
            temp = body.GetUserData() as Sprite;
            temp.x = body.GetPosition().x * PM;
            temp.y = body.GetPosition().y * PM;
            temp.rotation = body.GetAngle() * (180 / Math.PI); // radians to degrees
        }
    }
}
We looped through all box2d bodies then we checked if GetUserData() is not null which means there is a sprite referenced by this body, then we saved this sprite in a var temp of type Sprite ( don't forget to cast to Sprite ), we then updated the position of this sprite after converting to pixels by multiplying with PM because sprites work with pixels not meters unlike box2d objects. One last thing we updated the rotation of the sprite, Note that GetAngle method returns radians so we have to convert it first to degrees.
That is it! You should now have a falling box ( player ).

Creating walls

The same way as we did before when we were creating the player except we will make it static instead of dynamic
public function createWall(_x:Number, _y:Number, _width:Number, _height:Number):b2Body
{    
    _x = _x + _width / 2;
    _y = _y + _height / 2;
    
    // Create Wall Sprite Using code
    var wallSprite:Sprite = new Sprite();
    wallSprite.graphics.beginFill(0xe7d7c0, 1);
    wallSprite.graphics.drawRect( -_width / 2, -_height / 2 , _width, _height);
    wallSprite.graphics.endFill();
    wallSprite.x = _x;
    wallSprite.y = _y;
    addChild(wallSprite);
    
    // Create body definition
    var bodyDef:b2BodyDef = new b2BodyDef();
    bodyDef.userData = wallSprite;
    bodyDef.type     = b2Body.b2_staticBody;
    bodyDef.position.Set( _x / PM, _y / PM);
    
    // Create body from world using bodyDef
    var body:b2Body = world.CreateBody(bodyDef);
    
    // Create shape
    var shape:b2PolygonShape = new b2PolygonShape();
    shape.SetAsBox((_width / 2) / PM, (_height / 2) / PM);
    
    // Create fixtureDef giving shape
    var fixtureDef:b2FixtureDef = new b2FixtureDef();
    fixtureDef.shape       = shape;
    fixtureDef.restitution = 0.2;
    fixtureDef.friction    = 1;
    fixtureDef.density     = 0.5;
    
    // Pass the fixtureDef to the createFixture method in the body object
    body.CreateFixture(fixtureDef);
    
    return body;
}

The first two lines in the method we added half the width and half the height to x and y respectively, why? As we said in part1 of this tutorial that the origin is in the center of the object, and that's fine for creating the player but when creating walls it would be a lot easier if the origin was at the top left not the center so we just take the supplied x and y ( that are supposed to be the top left coordinates ) and add them to half width and half height to get the center coordinates.
Note also that we set the type to static this time.

Now let us create some walls in the init() method
var th:uint = 10;
// Vertical walls
createWall(0, 0                    , th, stage.stageHeight);
createWall(stage.stageWidth - th, 0, th, stage.stageHeight);
// Horizontal walls
createWall(0, 0                     , stage.stageWidth, th);
createWall(0, stage.stageHeight - th, stage.stageWidth, th);
You should now see some walls and a player.

Adding mouse listener and applying Impulse to the player

We already added a mouse event listener to the stage in the init method, now create the MouseEvent handler and add this lines
public function stageClicked(e:MouseEvent):void
{
    var impulse_x:Number = (mouseX / PM - player.GetPosition().x);
    var impulse_y:Number = (mouseY / PM - player.GetPosition().y);
    
    var impulse:b2Vec2 = new b2Vec2(impulse_x, impulse_y);
    impulse.Multiply( 2 / 3 );
    player.ApplyImpulse(impulse, player.GetPosition());
}
lets go through this code.
We want to apply an impulse on the player, this impulse should increase when the mouse goes farther away from the player. So impulse_x and impulse_y calculate the distance between the mouse and the player in meters, that's why we divided mouseX and mouseY by PM.
Next we created a b2Vec2 from the impulse_x and impulse_y then we muliplied it by 2 / 3, why? It just seemed more realistic but you can escape this step, anyway this is a very useful method (remember it).
Finally we applied an impulse on the player using the impulse and player position ( the position where the impulse should be applied ).

Part 2: All come together

public class Main extends MovieClip
{
    
    public static var world:b2World;
    public static const PM:uint = 30;
    private var player:b2Body;
    
    public function Main() 
    {
        if (stage) init();
        else addEventListener(Event.ADDED_TO_STAGE, init);
    }
    
    public function init(e:Event = null):void
    {  
        
        createWorld();
        
        player = createPlayer(40, 50, 50, 10);
        
        addEventListener(Event.ENTER_FRAME, update);
        stage.addEventListener(MouseEvent.CLICK, stageClicked);
        
        var th:uint = 10;
        // Vertical walls
        createWall(0, 0                    , th, stage.stageHeight);
        createWall(stage.stageWidth - th, 0, th, stage.stageHeight);
        // Horizontal walls
        createWall(0, 0                     , stage.stageWidth, th);
        createWall(0, stage.stageHeight - th, stage.stageWidth, th);
        
    }
    
    public function stageClicked(e:MouseEvent):void
    {
        var impulse_x:Number = (mouseX / PM - player.GetPosition().x);
        var impulse_y:Number = (mouseY / PM - player.GetPosition().y);
        
        var impulse:b2Vec2 = new b2Vec2(impulse_x, impulse_y);
        impulse.Multiply( 2 / 3 );
        player.ApplyImpulse(impulse, player.GetPosition());
    }
    
    public function update(e:Event):void
    {
        world.Step(1 / 30, 10, 10);
        var temp:Sprite;
        for (var body:b2Body = world.GetBodyList(); body != null; body = body.GetNext())
        {
            if (body.GetUserData())
            {
                temp = body.GetUserData() as Sprite;
                temp.x = body.GetPosition().x * PM;
                temp.y = body.GetPosition().y * PM;
                temp.rotation = body.GetAngle() * (180 / Math.PI); // radians to degrees
            }
        }
    }
    
    public function createWorld():void
    {
        var gravity:b2Vec2 = new b2Vec2(0, 9.8);
        var sleep:Boolean = true;
        
        world = new b2World(gravity, sleep);
    }
    
    public function createWall(_x:Number, _y:Number, _width:Number, _height:Number):b2Body
    {    
        _x = _x + _width / 2;
        _y = _y + _height / 2;
        
        // Create Wall Sprite Using code
        var wallSprite:Sprite = new Sprite();
        wallSprite.graphics.beginFill(0xe7d7c0, 1);
        wallSprite.graphics.drawRect( -_width / 2, -_height / 2 , _width, _height);
        wallSprite.graphics.endFill();
        wallSprite.x = _x;
        wallSprite.y = _y;
        addChild(wallSprite);
        
        // Create body definition
        var bodyDef:b2BodyDef = new b2BodyDef();
        bodyDef.userData = wallSprite;
        bodyDef.type     = b2Body.b2_staticBody;
        bodyDef.position.Set( _x / PM, _y / PM);
        
        // Create body from world using bodyDef
        var body:b2Body = world.CreateBody(bodyDef);
        
        // Create shape
        var shape:b2PolygonShape = new b2PolygonShape();
        shape.SetAsBox((_width / 2) / PM, (_height / 2) / PM);
        
        // Create fixtureDef giving shape
        var fixtureDef:b2FixtureDef = new b2FixtureDef();
        fixtureDef.shape       = shape;
        fixtureDef.restitution = 0.2;
        fixtureDef.friction    = 1;
        fixtureDef.density     = 0.5;
        
        // Pass the fixtureDef to the createFixture method in the body object
        body.CreateFixture(fixtureDef);
        
        return body;
    }
    
    public function createPlayer(_x:Number , _y:Number, _width:Number, _height:Number):b2Body
    {
        // Create car sprite
        var carSprite:Sprite = new Sprite();
        carSprite.graphics.beginFill(0xafafaf, 1);
        carSprite.graphics.drawRect( -_width / 2, -_height / 2 , _width, _height);
        carSprite.graphics.endFill();
        carSprite.x = _x;
        carSprite.y = _y;
        addChild(carSprite);
        
        // Create body definition
        var bodyDef:b2BodyDef = new b2BodyDef();
        bodyDef.userData = carSprite;
        bodyDef.type     = b2Body.b2_dynamicBody;
        bodyDef.position.Set(_x / PM, _y / PM);
        
        // Create body from world using bodyDef
        var body:b2Body = world.CreateBody(bodyDef);
        
        // Create shape
        var shape:b2PolygonShape = new b2PolygonShape();
        shape.SetAsBox(_width / 2 / PM, _height / 2 / PM);
        
        // Create fixtureDef giving shape
        var fixtureDef:b2FixtureDef = new b2FixtureDef();
        fixtureDef.shape       = shape;
        fixtureDef.restitution = 0.2;
        fixtureDef.friction    = 1;
        fixtureDef.density     = 0.5;
        
        // Pass the fixtureDef to the createFixture method in the body object
        body.CreateFixture(fixtureDef);
        
        return body;
    }
    
}

Friday, December 21, 2012

Box2D in Flash and AS3.. explained for beginners Part 1

Here I go with my first tutorial! I have thought about writing tutorials along time ago, But my English language wasn't as that good, But it got a lot better over the last few months so I hope this tutorial would be helpful for you.

In this series of tutorial we will be creating a basic box2d game then we will extend that to create a very organized OO box2d project using the help of design patterns! But we will leave that for another series.

The final result: Click any where on the stage, as the mouse go far away from the box, the applied impulse increases.



Steps :
  1. Download and setup box2d physics engine for as3
  2. Understanding some box2d basics
  3. Creating the world
  4. Creating the player
  5. Make things come alive! ( the fun part )
  6. Creating walls
  7. Adding mouse listener and applying Impulse to the player
  8. The conclusion

Download and setup box2d physics engine for as3

Create a new folder and put your flash file in. Click here and download the latest box2d version that is compatible with your flash version ( I am using box2d v2.1a ), Then unzip the box2d compressed file anywhere and navigate to "Box2DFlashAS3 2.1a\Source", you should find a Box2D folder in there , copy that and into your flash project folder paste it, my flash project folder looks like this :-
That's it!, now let's make sure everything is working. Open your fla file and from properties write a name for the class, I usually call it Main ( some developers called it with the name of the project ), then create your main class file "Main.as", and write this basic code in the Main.as file

package  
{
    public class Main extends MovieClip
    {
        
        public function Main() 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        public function init(e:Event = null):void
        {
             trace("Working...");
        }
    }
}

Run your flash file and your should see "Working..." in the output window.

Understanding some box2d basics

Before we get into the code, we need first to understand how box2D works?, box2D is a physics engine that calculates all the positions and rotations for the objects you create through it.
e.g. if we needed to create a car with mass = 1000 kg that moves with a speed = 20 m/s, we will first need to create the world where our car should be, set its gravity and update the world every frame, Then we will create the body of the car, give it some physical properties and create a ground also give it some physical properties then we would apply an impulse on the car and it should move with a constant speed ( assuming no resistance ).
Calculating the Impulse :- Impulse = Mass * Velocity ( see wikipedia for more information ).
Impulse is a vector quantity ( which means it has x and y values ), The mass of the car is 1000 kg and we need the velocity to be equal to 20 m/s, we would need to apply an impulse = ( 20000 , 0 ), in another words 20000 in x direction and 0 in y direction.

Things to know About box2D

" Box2D works with meters not pixels "
How is that ?! If your stage size was 800 x 600 pixels, Box2D will assume each pixel = 1 meter.
Okay what is wrong with that ? the answer is simple, how tall are you? I am 1.7 meters so I would fill 1.7 pixels on the screen and that is just a dot! That is not good right..
There is a very simple approach to solve this. It is to work with pixels not meters and divide by a constant to convert to meters ( usually the constant equals 30 which means 30 pixels per meter ).

" Box2D doesn't display any graphics for you "
Yes it contains a debugdraw class that can be used to draw all the box2d objects you created, but this is usually used for testing, because in the real life you would need real graphics ( Sprites and MovieClips ) to represent objects in your game.
How to solve this? We will somehow make box2d objects contain reference for the sprites that act as the displays for this box2d objects. You have all the rights to not understand that at this level, but once we get into the code everything will be clear.

" Box2D object registration point is located at the center "
 You should be familiar with registration points in flash, e.g. if we were to create a box in box2d and give it a start position of (200 ,300), it will be placed like this
Why is this a problem? It's not but we have to make sure that all our sprites have the registration point at the center ( more about that later ).

Also you should know that all box2D classes start with 'b2', e.g. b2Body, b2World, b2Shape, ... etc

We can now simplify the steps to Implement our game
  1. Creating the world
  2. Creating the player ( car )
  3. Creating the ground
  4. Creating walls and obstacles.
  5. Update the world ( Make things come alive )
  6. Applying impulse on the player when mouse is clicked

Creating the world

To create the world we have to define a new object from the b2World class, and let's define it as a class variable to be able to access it anywhere in the project, also let's make a class constant PM which will be used to convert pixels to meters

public static var world:b2World;
public static const PM:uint = 30;

We will be creating each step in a separate method, so create a method call it createWorld()

public function createWorld():void
{
    var gravity:b2Vec2 = new b2Vec2(0, 9.8);
    var sleep:Boolean = true;
    
    world = new b2World(gravity, sleep);
}

Box2D has a class to represent vectors called b2Vec2.
The b2World constructor needs two parameters :
  • gravity : the force that will act on all the box2d objects, forces are represented by vectors, in our example we created a normal gravity vector with a y direction equals to 9.8.
  • sleep : when set to true the world will not simulate inactive bodies, so by setting it to true you increase the performance.

Creating the player ( car )

That's actually the messy part....
When creating physical objects in box2D we have to go through 5 steps :
  1. Create body definition
  2. Create body from world using body definition
  3. Create shape
  4. Create fixture definition
  5. Pass the fixture definition to the CreateFixture method in the body object
But when applying forces, impulses or changing anything on this box2d object we will need only its b2body object.

As we have said before we will create each step in a separate method, so make a method that takes 4 arguments ( x, y, width, height ) and call it createPlayer which returns the b2body to be used later.

public function createPlayer(_x:Number , _y:Number, _width:Number, _height:Number):b2Body
{
    // Create body definition
    var bodyDef:b2BodyDef = new b2BodyDef();
    bodyDef.type     = b2Body.b2_dynamicBody;
    bodyDef.position.Set(_x / PM, _y / PM);
    
    // Create body from world using bodyDef
    var body:b2Body = world.CreateBody(bodyDef);
    
    // Create shape
    var shape:b2PolygonShape = new b2PolygonShape();
    shape.SetAsBox(_width / 2 / PM, _height / 2 / PM);
    
    // Create fixtureDef giving shape
    var fixtureDef:b2FixtureDef = new b2FixtureDef();
    fixtureDef.shape       = shape;
    fixtureDef.restitution = 0.2;
    fixtureDef.friction    = 1;
    fixtureDef.density     = 0.5;
    
    // Pass the fixtureDef to the createFixture method in the body object
    body.CreateFixture(fixtureDef);
    
    return body;
} 

As you can see we first created bodyDef where we set the type ( dynamic ) and position ( remember to divide by the PM to convert pixels to meters ).
Then we created a body from the world using bodyDef.
Then we created a shape of type polygonShape, box2D has 3 types of shapes ( edge, circle and polygon ), In this tutorial we will use the polygon shape, b2PolygonShape has a method to easily create boxes called SetAsBox which takes two parameters ( half width and half height ), also don't forget to convert pixels to meters.
The fourth step which is creating the fixtureDef, it takes the shape and sets some physical properties, lets talk about each property we have set:
  1. Restitution : this video shows you the effect of increasing the restitution of bodies, for more information about the coefficient of restitution watch this video.
  2. Friction : by increasing this you increase the resistance between this object and any other object colliding with and therefore decreasing the time needed for this object to come to rest.
  3. Density : as you may know that mass = density * Volume, box2d compute the mass of an object from its density and its area multiplied by 4, Why 4? I don't know, maybe because it's convenient as the depth of the object. For our example here, the mass of this car will be equal to ( _height * _width * density * 4 ).
Finally, The last step is passing this fixtureDef we created to the createFixture method in the body object.
Don't forget to return the body for us to have full control over this object later.

That is it? No, we haven't created the sprite that will act as the display yet, so let's do that now, In the createPlayer method add this lines before creating the bodyDef

// Create car sprite
var carSprite:Sprite = new Sprite();
carSprite.graphics.beginFill(0xafafaf, 1);
carSprite.graphics.drawRect( -_width / 2, -_height / 2 , _width, _height);
carSprite.graphics.endFill();
carSprite.x = _x;
carSprite.y = _y;
addChild(carSprite);

That is a very basic way of drawing a rectangle in a sprite, Note that we have set the registration point to the center by drawing around the center ( - width / 2 and - height / 2).
Okay we now created our box2d object and the display sprite, how to make a reference to the sprite in the box2d object? Fairly easy, just add this line after creating bodyDef object

bodyDef.userData = carSprite;

 

Part 1: All come together

Nothing Impressive has happened yet, just a box hanging there on the air , but as you will see in the first section of the second part where we make everything come alive ...
Part1 final code :-

public class Main extends MovieClip
{
    
    public static var world:b2World;
    public static const PM:uint = 30;
    private var player:b2Body;
    
    public function Main() 
    {
        if (stage) init();
        else addEventListener(Event.ADDED_TO_STAGE, init);
    }
    
    public function init(e:Event = null):void
    {    
        createWorld();
        
        player = createPlayer(40, 50, 50, 10);
        
    }
    
    public function createWorld():void
    {
        var gravity:b2Vec2 = new b2Vec2(0, 9.8);
        var sleep:Boolean = true;
        
        world = new b2World(gravity, sleep);
    }
    
    public function createPlayer(_x:Number , _y:Number, _width:Number, _height:Number):b2Body
    {
        // Create car sprite
        var carSprite:Sprite = new Sprite();
        carSprite.graphics.beginFill(0xafafaf, 1);
        carSprite.graphics.drawRect( -_width / 2, -_height / 2 , _width, _height);
        carSprite.graphics.endFill();
        carSprite.x = _x;
        carSprite.y = _y;
        addChild(carSprite);
        
        // Create body definition
        var bodyDef:b2BodyDef = new b2BodyDef();
        bodyDef.userData = carSprite;
        bodyDef.type     = b2Body.b2_dynamicBody;
        bodyDef.position.Set(_x / PM, _y / PM);
        
        // Create body from world using bodyDef
        var body:b2Body = world.CreateBody(bodyDef);
        
        // Create shape
        var shape:b2PolygonShape = new b2PolygonShape();
        shape.SetAsBox(_width / 2 / PM, _height / 2 / PM);
        
        // Create fixtureDef giving shape
        var fixtureDef:b2FixtureDef = new b2FixtureDef();
        fixtureDef.shape       = shape;
        fixtureDef.restitution = 0.2;
        fixtureDef.friction    = 1;
        fixtureDef.density     = 0.5;
        
        // Pass the fixtureDef to the createFixture method in the body object
        body.CreateFixture(fixtureDef);
        
        return body;
    }
    
}