Win an Ipad
  Developer   Demos & Samples   Box2DCreates

Box2DCreates

Screenshot
This sample demonstrates basic box2d functionality included in Moscrif. Box2D is a physical engine used for 2D games. Nintendo DS, Wii, several mobile platforms (including Android and iPhone) and the majority of the biggest operating systems also use this engine. In this sample, we created physics world with a few bodies. These bodies are influenced by gravity but they can also be moved by finger.

World

World is the main part of box2D. The box2D world simulates the real world with gravity as we know it. The world is a collection of bodies, fixtures and constraints that interact together. The most important world parts are:

  • Bodies: represent all objects in the world. Each body can have different properties like density, friction, bounce, width, height etc.; causing different behavior of the body.
  • Joints: hold two or more bodies together. Box2D supports several joint types: revolute, prismatic, distance and more. Some joints may have limits and motors.
  • Joint limit: restricts the range of motion of a joint. For example, human elbow only allows a certain range of angles.
  • Joint motor: drives the motion of the connected bodies according to the joint's degrees of freedom. For example, you can use a motor to drive the rotation of the elbow.

In our sample, we created a world using PhysicsScene class. Instance of this class may be created by create function. By default, the gravity is set to real world gravity, but if a device supports acceleration sensor, the gravity changes based on how the device is tilted.

Example: Create physics world

// creates physics world
var xGravity = 0.0;                 // zero gravity on x axis (horizontally)
var yGravity = -9.8;                // real gravity on y axis (vertically)
var sleep = false;                  // forbit sleeping (bodies fall asleep, when they are in rest) it improves performance
var enableCollisions = true;        // enable colisions between two bodies
// create physics scene
this._world = PhysicsScene.create(xGravity, yGravity, sleep, enableCollisions);

Bodies

Bodies portray physical objects in the world. They all have different properties like: density, friction, bounce etc. According to their properties, they have a mass and behave according to physical laws. Their behavior is also affected by a body type. There are three body types supported:

  • #static - static body does not move under simulation and behaves as infinite mass. Static bodies can be moved manually by setPosition. A static body has zero velocity and does not collide with other static or kinematic bodies.
  • #kinematic - kinematic body moves under simulation according to its velocity. Kinematic bodies do not respond to forces. They can be moved manually by the user, but normally, kinematic body is moved by setting its velocity. Kinematic bodies behave as if they had infinite mass, but they do not collide with other static or kinematic bodies.
  • #dynamic - dynamic body is fully simulated. It can be moved manually by setPosition, but normally they move according to forces. Dynamic body can collide with all body types and always has finite, non-zero mass. If you try to set the mass of a dynamic body to zero, it will automatically acquire a mass of one kilogram.

Borders

To prevent a body escape from the playground we need to create borders. Borders are box2d bodies and always static bodies. Due to their static type, they do not move under simulation and collide only with dynamic bodies.

Example: create borders around the playground

// create ground
var (width, height) = (System.width, 50);
this._ground = this._world.addPolygonBody(null, #static, 0.0 /*density*/, 5.2/*friction*/, 0.0/*bounce*/, width, height);
this._ground.setPosition(System.width/2, System.height - height/2);
this._ground.onDraw = :sender, canvas :canvas.drawRect(-sender.width/2, -sender.height/2, sender.width/2, sender.height/2, paint);   // create walls (width, height) = (1, System.height);
var leftMantinel = this._world.addPolygonBody(null, #static, 0.0/*density*/, 0.0/*friction*/, 0.0/*bounce*/, width, height);
leftMantinel.setPosition(leftMantinel.width/2, System.height/2);   (width, height) = (1, System.height);
var rightMantinel = this._world.addPolygonBody(null, #static, 0.0/*density*/, 0.0/*friction*/, 0.0/*bounce*/, width, height); rightMantinel.setPosition(System.width - (rightMantinel.width/2), System.height/2);   (width, height) = (System.width, 1);
var topMantinel = this._world.addPolygonBody(null, #static, 0.0/*density*/, 0.0/*friction*/, 0.0/*bounce*/, width, height);
topMantinel.setPosition(System.width/2, (topMantinel.height/2));

Crates

According to the screen dimensions, our application can fit three or more crates. They are dynamic type, which means that they move according to gravity and also collide with static bodies (borders). The bounce property is set to 0.9. It means that the crates bounce with a small damping. The value 1.0 causes bounce without damping.

Example: create crates

// create crates
var (crateWidth, crateHeight) = (imgBox.width, imgBox.height);
this._bodies = new Array();
// set number of crates acording to screen width
const cratesNum = System.width > 320 ? 12 : 4;
for (var i = 0; i < cratesNum; i++) {
    var body = this._world.addPolygonBody(imgBox, #dynamic, 0.9 /*density*/, 0.0/*friction*/, 0.0/*bounce*/, crateWidth, crateHeight);
    // place body to random position
    body.setPosition((System.width / (5)) * (i%4 + 1) + rand(10), (System.height-(130+(i%5)*130) - rand(30)) - height/2, 0);
    // push the body to the array
    this._bodies.push(body);
}

Mouse joint

The bodies may be moved by user’s finger movement on the screen. To move the bodies according to the user’s requirement, one needs to implement mouse joint. Mouse joint is one of eight joints supported by box2D in Moscrif and it allows moving bodies to required positions. The mouse joint is created when user taps on a crate on the screen.

Example: pointer pressed event

app.onPointerPressed = function(sender, x, y)
{
    ....     this._mouseJoint = null;
    for(var body in this._bodies) {
        // calculate border of body
        var (bx, by) = body.getWorldCenter();
        var realBx1 = bx - body.width/2;
        var realBx2 = bx + body.width/2;
        var realBy1 = by - body.height/2;
        var realBy2 = by + body.height/2;
        // check if user cliked inside dthe body
        if ((realBx1 <= x && x <= realBx2) && (realBy1 <= y && y <=  realBy2)) {
            // create additional joint settings
            var mouseJointDef = {
                maxForce        : 2500,
                frequencyHz     : 10000,
                dampingRatio    : 0.0,
                targetX         : x / this._world.scale,
                targetY         : (System.height-y) / this._world.scale
            };
            // crate mouse joint
            this._mouseJoint = this._world.createMouseJoint(this._ground, body, mouseJointDef, true);
        }
    }
}

Every time the users moves their finger, the crate moves as well because we set a new target for mouse joint.

Example: pointer dragged event

app.onPointerDragged = function(sender, x, y)
{
    // check if mouse joint exists
    if (this._mouseJoint != null) {
        // convert screen to box2d coordinates
        var b2y = (System.height-y) / this._world.scale;
        var b2x = x / this._world.scale;
        // set new target to mouse joint
        this._mouseJoint.setTarget(b2x, b2y);
    }
}

More about mouse joint can be found in Mouse joint sample.

Sensors

This sample also reacts based on device's tilt change. The gravity affecting the crates depends on the device position. The acceleration sensor responds to device tilt. This sensor is managed by Sensor class and raised onDataReceived event when it gets new information about the device tilt. The third parameter of this event is array which contains three values: g-force on X, Y and Z axis.

Example: manage sensors

// check if device supports acceleration sensor
if (Sensor.isAvailable(#acceleration)) {
    // create sensor
    var sensor = new Sensor(#acceleration, 40);
    sensor.onDataReceived = function(sender, timestamp, params)
    {
        // set gravity acording to device position
        this super._world.setGravity(-params[0] * 10., -params[1] * 10.);
    };
    // start senzor data receiving
    sensor.start();
}

More information about sensors is availabale in sensors sample.

 

 Box2DCrates   Gradients 
Write a Comment (0)
Subject
Please complete this mandatory field.
HTML Tags Not Allowed!
Comment
Please complete this mandatory field.