android10

  • Increase font size
  • Default font size
  • Decrease font size

2D Physics on Android (using Box2D Engine)

E-mail Print
( 8 Votes )
Share

Introduction

This post is a brief tutorial on getting started with 2D physics on Android.
2D physics can greatly enrich games by realistic behavior of objects such as polygons (boxes, rectangles, polys) and circles in a world setting. The engine calculates collisions, angles, forces and momentums based on user-defined settings such as gravity, density, friction, elasticity, etc.
This post is a brief tutorial on getting started with 2D physics on Android.
2D physics can greatly enrich games by realistic behavior of objects such as polygons (boxes, rectangles, polys) and circles in a world setting. The engine calculates collisions, angles, forces and momentums based on user-defined settings such as gravity, density, friction, elasticity, etc.

2d_physics_on_android_00


The Engine

There are a couple of good open-source 2d physics engines, most notably Box2D and Chipmunk. For this project we’ll use Box2D due to it’s better performance (see next figure, detailled comparison and speed tests). The following figure is from benchmarks made on the xo laptop:

2d_physics_on_android_01

Luckily there is a Java port of the Box2D libraries called JBox2D (released under the zlib license). JBox2D is using the processing library for displaying things, which we’re not gonna use on Android :D.


JBox2D

The library is bundled the 154kb file jbox2d-2.0.1-library-only.jar from their svn. This file includes the whole Box2D functionality and is very easy to implement in custom Java projects.

Guides & Docs


Importing the library

Let’s import the jar file into our current project in Eclipse.

1- Download jbox2d-2.0.1-library-only.jar and save it anywhere as jbox2d.jar

2- In Eclipse
  • Create a folder /lib/
  • Right Click on /lib, select Import
  • Select General / File System
  • Choose the directory of jbox2d.jar
  • Import the file jbox2d.jar
  • Right click on the project and select “Properties”
  • Click on “Java Build Path” and select the “Libraries” tab
  • Click on “Add JARs…” and pick the file jbox2d.jar
That’s it; we can use Box2D by now and can access the library reference in Eclipse as seen in the figure below.

2d_physics_on_android_02


Physical Hello World

Let’s write a quick hello world app, that basically follows the Box2D User Manual, doing the following:
  • Initialize a new world
  • Add a ground box
  • Create some dynamic bodies (balls)
  • Simulate the world
This code is not drawing anything on the screen yet. It only calculates the physical behaviour and prints a log message about the latest added element (position and angle).

The following code is a class that handles the physics only. It can be implemented by any activity, and the update() function has to be called periodically.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import org.jbox2d.collision.AABB;
import org.jbox2d.collision.CircleDef;
import org.jbox2d.collision.PolygonDef;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.World;
 
import android.util.Log;
 
public class PhysicsWorld {
    public int targetFPS = 40;
    public int timeStep = (1000 / targetFPS);
    public int iterations = 5;
 
    private Body[] bodies;
    private int count = 0;
 
    private AABB worldAABB;
    private World world;
    private BodyDef groundBodyDef;
    private PolygonDef groundShapeDef;
 
    public void create() {
        // Step 1: Create Physics World Boundaries
        worldAABB = new AABB();
        worldAABB.lowerBound.set(new Vec2((float) -100.0, (float) -100.0));
        worldAABB.upperBound.set(new Vec2((float) 100.0, (float) 100.0));
 
        // Step 2: Create Physics World with Gravity
        Vec2 gravity = new Vec2((float) 0.0, (float) -10.0);
        boolean doSleep = true;
        world = new World(worldAABB, gravity, doSleep);
 
        // Step 3: Create Ground Box
        groundBodyDef = new BodyDef();
        groundBodyDef.position.set(new Vec2((float) 0.0, (float) -10.0));
        Body groundBody = world.createBody(groundBodyDef);
        groundShapeDef = new PolygonDef();
        groundShapeDef.setAsBox((float) 50.0, (float) 10.0);
        groundBody.createShape(groundShapeDef);
    }
 
    public void addBall() {
        // Create Dynamic Body
        BodyDef bodyDef = new BodyDef();
        bodyDef.position.set((float) 6.0+count, (float) 24.0);
        bodies[count] = world.createBody(bodyDef);
 
        // Create Shape with Properties
        CircleDef circle = new CircleDef();
        circle.radius = (float) 1.8;
        circle.density = (float) 1.0;
 
        // Assign shape to Body
        bodies[count].createShape(circle);
        bodies[count].setMassFromShapes();
 
        // Increase Counter
        count += 1;
    }
 
    public void update() {
        // Update Physics World
        world.step(timeStep, iterations);
 
        // Print info of latest body
        if (count > 0) {
            Vec2 position = bodies[count].getPosition();
            float angle = bodies[count].getAngle();
            Log.v("Physics Test", "Pos: (" + position.x + ", " + position.y + "), Angle: " + angle);
        }
    }
}


Using it in an Activity

It implement the PhysicsWorld class in an Activity is as simple as the following code blueprint:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
 
public class Physics extends Activity {
    PhysicsWorld mWorld;
    private Handler mHandler;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mWorld = new PhysicsWorld();
        mWorld.create()
 
        // Add 50 Balls
        for (int i=0; i<50; i++) {
            mWorld.addBall();
        }
 
        // Start Regular Update
        mHandler = new Handler();
        mHandler.post(update));
    }
 
    @Override
    protected void onPause() {
        super.onPause();
        mHandler.removeCallbacks(update);
    }
 
    private Runnable update = new Runnable() {
        public void run() {
            mWorld.update();
            mHandler.postDelayed(update, (long) (mWorld.timeStep*1000));
        }
    };
}

That’s it; congratulations, you’re now ready to use Box2D in every way you’d like to!


Drawing the Elements on the screen

Drawing the elements is a delicate task, as code performance matters a lot and it can speed things up or slow them down greatly! The android docs on 2D Graphics suggest the android.graphics.drawable and android.view.animation packages are where you’ll find the common classes used for drawing and animating in two-dimensions.

I’ll write about this with example code for drawing the elements another time, although it should be not very hard to get started with drawables, as there are many examples with source code.

It is important to keep two things in mind:
  • Axis orientations: the coordinate (0, 0) with the G1 is typically the upper left corner of the screen, while (0, 0) in Box2D is the bottom left corner of the screen.
  • The other thing are dimensions: Box2D works fine with dimensions from 0.1 to 10 times the typical earth dimensions such as density, friction, gravity, …. Internally the engine is using meters and we will need to convert them to pixels. If we say, 1 meter shall be 10 pixels, that function could look like this:

1
2
3
4
5
public Vec2 toScreen(Vec2 pos) {
    pos.x = pos.x*10;
    pos.y = 480 - (pos.y*10);
    return pos;
}

That’s it basically. If you’re doing cool stuff with it, we’d love to hear about it! :D.
These are the first steps...I hope you can find this article usefull...

I’d be delighted to hear suggestions, remarks, feedback, ….

[Source]

Comments (2)
  • mikos  - cool stuff

    questions:
    (1) where can we download the full project?
    (2) Is there samples with bitmap skinning available?
    Thanks a lot for this blog!

Only registered users can write comments!
 

ANDROID10 --- TIP!!!

android10 tipYou can edit your position easily: just click on your picture when you're logged in, then on the top you will find a menu, go there, edit your profile, go to your position tab and drag the icon in the map. That's all. Just easy!!!
contact android10!!!