Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Mobile / iOS

Box2d vehicles – part 3 – bike

5.00/5 (3 votes)
9 Oct 2012BSD3 min read 35.8K   2.1K  
How to create an amazing bike game for three platforms with only one code?
 
Image 1

Introduction

Last article showed how to make a car using box2d physical engine in Moscrif. In this article I’ll show how to create a bike. The result of this article is fully working game draft of cross-bike game. The concept of this game is used in many well known games, which have millions of downloads on app markets. To maximize the number of supported devices we use Moscrif SDK to create the game for three platforms with only one code.

Box2d

The box2d physical engine is commonly used in many 2d games. The physical world consists from bodies, which are connected together by joints. These joints connect bodies together and allow some time of movement between them. In this sample prismatic and revolute joints are used.

The prismatic joint allows translation of two bodies along a specified axis. It prevents relative rotation between the bodies.

The Revolute joint allows relative rotation of two bodies around an anchor point. We also use mouse joint, but it is used only to deny collisions detection between some bodies. Some joints like revolute and prismatic support limits (to restrict joint movement) and motors (to enforce joint movement).

Bike

Bike consists from five bodies, connected together with joints. The largest part of the bike is a frame. All other parts are connected onto the frame. The frame is used to apply angular impulse, which causes bike rotation. The bike’s position is also determined by the centre of the frame. The wheels are connected onto frame with front and back damper.



Image: bike’s parts

Image 2

All bike’s bodies are polygon dynamic bodies. The dynamic bodies are fully simulated and collide with other static bodies (ground and jumps).

Example: create all bike’s bodies

C++
function create(scene, x, y)
{
   // polygon shape of the body
   var shape = [
        {x:-30,y:-82},
        {x:100,y:-42},
        {x:50,y:82},
        {x:38,y:80},
        {x:-98,y:46},
        {x:-92,y:-76}
    ]
    this._frame = scene.addPolygonBody(this._images.frame, #dynamic, 1.0, 0.0, 0.0, shape);
    this._frame.z = 2;
    this._frame.setPosition(x, y);
 
    // FRONT
    this._frontDamper = scene.addPolygonBody(this._images.frontDamper, #dynamic, 1.0, 0.0, 0.0, this._images.frontDamper.width, this._images.frontDamper.height);
    this._frontDamper.z = 3;
    this._frontDamper.setPosition(x + 96, y + 35);
 
    this._frontWheel = scene.addCircleBody(this._images.wheel, #dynamic, 1.2, 1.0, 0.0, this._images.wheel.width / 2);
    this._frontWheel.z = 2;
    this._frontWheel.setPosition(x + 113, y + 73);
 
    // BACK
    this._backDamper = scene.addPolygonBody(this._images.backDamper, #dynamic, 1.0, 0.0, 0.0, this._images.backDamper.width, this._images.backDamper.height);
    this._backDamper.z = 3;
    this._backDamper.setPosition(x - 80, y + 70);
 
    this._backWheel = scene.addCircleBody(this._images.wheel, #dynamic, 1.2, 1.0, 0.0, this._images.wheel.width / 2);
    this._backWheel.z = 2;
    this._backWheel.setPosition(x - 120, y + 80);

Suspensions

Nowadays, almost every cross bike has suspension on both wheels. They make the ride more comfortable and safer. To make the simulation more realistic it also supports suspensions.

Front damper

The main part of front suspension is a prismatic joint which connects frame and front damper. The prismatic joint has a motor, which tries to move the frame up with some force. However, the upper transition of the joint is restricted by the limit. It means that the frame moves only up to the upper limit. If the front wheel hits some hurdle, the front damper is affected by force, which tries to move it up. This force is larger than maximum force of the joint, which caused that instead of joint motor the front dumper moves up - closer to the frame. Finally, when the front wheel comes over the hurdle, the force onto front damper is smaller and the joint can move damper to the lower position again.

Image: front damper

Image 3

Back damper

The back damper uses revolute joint. The revolute joint also supports limits and motor, but they are defined by angle not by distance. The back damper rotates around the point on the frame. Limits restricts the joint rotation and motor enforce it rotation.

Image: back damper

Image 4

Example: connect dampers onto frame

C++
// JOINTS
// connect front damper onto frame
var jointDef = {
    lowerTranslation    : -0.2, //(damperHeight / 5) / scene.scale,  /*meters*/
    upperTranslation    : 0.0,  /*meters*/
    enableLimit         : true,
    enableMotor         : true,
    motorSpeed          : 2.0,
    maxMotorForce       : this._frame.getMass() * 9.8,
}
this._joints.push(scene.createPrismaticJoint(this._frontDamper, this._frame, x + 96, y + 35, -0.4, 1.0, 0.0, jointDef, false));
// connect back damper onto frame
jointDef = {
    enableMotor     : true,     // enable motor
    maxMotorTorque  : 150,      // maximum torque
    motorSpeed      : -0.9,     // it is changed latery
    lowerAngle      : 0.2, //(damperHeight / 5) / scene.scale,  /*meters*/
    upperAngle      : 0.45,
    enableLimit     : true,
}
this._joints.push(scene.createRevoluteJoint(this._backDamper, this._frame, x - 50, y + 55, jointDef, false));

Wheels

Bikes are always powered by back wheel. The both wheels are connected onto damper by revolute joint without limit. The back wheel is connected with revolute joint with motor to speed the bike up or down.

Example: Connect wheels

C++
/ front wheel - without motor
this._joints.push(scene.createRevoluteJoint(this._frontDamper, this._frontWheel, x + 113, y + 73, null, false));
// back wheel - with motor
jointDef = {
    enableMotor     : true,         // enable motor
    maxMotorTorque  : 1500000,         // maximum torque
    motorSpeed      : -2.0,         // it is changed latery*/
}
this._motorJoint = scene.createRevoluteJoint(this._backDamper, this._backWheel, x - 120, y + 80, jointDef, false);

Angular impulse

Bike is applying also angular impulse in regular time intervals. The appliance of angular impulse allows to create flips or stabilize the bike after jumps.

Example: Apply angular impulse

C++
// apply angular impulse in regular intervals. The angular damping allows to create flip or stabilize bike after jump
        this._angularImpulse = 0.0;
        var process = new Timer(50, true);
        process.onTick = function()
        {
            this super._frame.applyAngularImpulse(this super._angularImpulse);
        }
        process.start(50);

Speed and rotation control

The bike’ speed and size of angular impulse is controlled by two bars on the left and right side of the screen. The height of the bar is 300 pixels to enable comfortable controlling by finger. Every time, when finger moves on the screen a pointerDragged method is called.

Example: manage pointer dragged method

C++
function pointerDragged (x, y, pointer)
{
    super.pointerDragged(x, y);
 
    var maxSpeed = 33;
    var maxPlayer = 1.4 * this._bike.getMass();
    if (y < System.height / 2 - 150)
        y = System.height / 2 - 150;
    else if (y > System.height / 2 + 150)
        y = System.height / 2 + 150;
 
    if (x > 3*System.width / 4) {
        this._bike.player = (System.height / 2.0 - y) / 150 * maxPlayer;
        this._anglePaint.shader = this._createAngleShader(y);
    } else if (x < System.width / 4){
        this._bike.speed = -1*(System.height / 2.0 - y) / 150 * maxSpeed;
        this._speedPaint.shader = this._createSpeedShader(y);
    }
}

Summary

This article showed how to create a realistic bike simulation using box2d engine. The result is a full working game draft, which is available to download for free. To make the development process more effective we used Moscrif SDK.

License

This article, along with any associated source code and files, is licensed under The BSD License