-
2D Physics on Android (using Box2D)
Posted on March 4th, 2009 4 comments
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.
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:

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
- Box2D User Manual describes how to get started with the library, explains the basic principles and contains example codes (highly suggested read!)
- Box2D Class Reference
- JBox2D Wiki explains the differences from the C++ to the Java version
Importing the library
Let’s import the jar file into our current project in Eclipse.
- Download jbox2d-2.0.1-library-only.jar and save it anywhere as jbox2d.jar
- 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 to the right.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.
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:
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:
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.
I’d be delighted to hear suggestions, remarks, feedback, … (please post a comment below!).
[update]Further discussion about the performance and patches on anddev and box2d forums.[/update]
Related Posts
4 Responses to “2D Physics on Android (using Box2D)”
-
Very nice tutorial Chris! I was wondering how to do this and now you’ve gone and figured it out .. I guess its time to focus on the fun stuff now - what to *do* with such power! :)
-
schwiz March 10th, 2009 at 8:14 am
great tutorial but I keep getting a force close. :(
-
Strange, I don’t get a force close here. Maybe have a look over to anddev and post about your problem (include the “adb logcat” output): http://www.anddev.org/viewtopic.php?t=5099
-
Do you have complete working android project?
Digg it
Save this page
Submit to reddit