Box2D Game demo in Android

January 10th, 2012 by admin | Filed under Android Game Programming, Android Tutorials.

Lets see in this tutorial we will learn how to develop an android game with Box2d. There are following steps :

Step :1. Create a project using motodev.
1

Step :2. Create a lib folder inside the project and put jbox2d-2.0.1-full.jar file there.
lib_folder
Step :3. Open the project properties and add the jar file in the library.
import_Jbox
Step :4. Rename the MainActivity.java into Box2dGame.java put the same in AndroidManifest.xml. Now open the class and put following code

package com.physicssample;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

public class Box2dGame extends Activity
{
    private GLSurfaceView _surfaceView;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        _surfaceView = new ClearGLSurfaceView(this);
        setContentView(_surfaceView);
    }

    @Override
    protected void onPause() {
        super.onPause();
        _surfaceView.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        _surfaceView.onResume();
    }

}

Step :5. Now create a ClearGLSurfaceView.java class and put following code inside the class

package com.physicssample;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;

public class ClearGLSurfaceView extends GLSurfaceView
{
    ClearRenderer _refRenderer;
    public ClearGLSurfaceView(Context context) {
        super(context);
        _refRenderer = new ClearRenderer(context);
        setRenderer(_refRenderer);
    }

    public boolean onTouchEvent(final MotionEvent event) {
        _refRenderer.setSize(this.getWidth(),this.getHeight());
        queueEvent(new Runnable(){
            public void run() {
              _refRenderer.touchEvent(event.getX(), event.getY(), event.getAction());
            }});
            try {
                   Thread.sleep(20);
             } catch (InterruptedException e) {
                e.printStackTrace();
             }
            return true;
        }
}

Step :5. Now create a ClearRenderer.java class and put following code inside the class

package com.physicssample;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import org.jbox2d.collision.PolygonShape;
import org.jbox2d.collision.Shape;
import org.jbox2d.collision.ShapeType;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.view.MotionEvent;

public class ClearRenderer implements GLSurfaceView.Renderer
{
    private PhysicsWorld _physicsWorld;
    private ObjectCreater _refBox;
    private Context _context;
    private int _width;
    private int _height;

    public ClearRenderer(Context newContext)
    {
        _context = newContext;
        _refBox = new ObjectCreater(new float[]{-1,-1,0,1,-1,0,1,1,0,-1,1,0}, new float[]{ 0f,1f, 1f,1f, 1f,0f,0f,0f},new short[]{0,1,2,3,0},5);
        _physicsWorld = new PhysicsWorld();
        _physicsWorld.createWorld();
        _physicsWorld.addBox(0f, -25f, 50f, 10f, 0f, false);
    }

public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
            GLU.gluOrtho2D(gl, -12f, 12f, -20f, 20f);
	        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
	        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
	        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
            GL10.GL_REPEAT);
	        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
            GL10.GL_REPEAT);
	        _refBox.loadTexture(gl, _context, R.drawable.box);
}

public void onSurfaceChanged(GL10 gl, int w, int h)
{
    gl.glViewport(0, 0, w, h);
}

public void onDrawFrame(GL10 gl)
{
    gl.glClearColor(0f, 0, 0.5f, 1.0f);
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
    GL10.GL_REPLACE);
    gl.glColor4f(1f, 1f, 1f, 1f);
    Vec2 vec;
    Body _body = _physicsWorld.getBodyList();
    do
    {
            Shape _shape = _body.getShapeList();
            if (_shape != null)
            {
                    vec = _body.getPosition();
                    float rot = _body.getAngle() * 57f;
                    if (ShapeType.POLYGON_SHAPE == _shape.getType())
                    {
                        Vec2[] _vertexes = ((PolygonShape)_shape).getVertices();
                       _refBox.draw(gl, vec.x, vec.y, 0f, rot, _vertexes[2].x, _vertexes[2].y);
                    }

            }
            _body = _body.getNext();
    }
    while (_body != null);
    _physicsWorld.update();
}

public void touchEvent(float x, float y, int eventCode)
{
    float _worldX = ((x-(this._width/2))*12f)/(this._width/2);
    float _worldY = ((y-(this._height/2))*-20f)/(this._height/2);
    if (eventCode == MotionEvent.ACTION_UP)
    {
        _physicsWorld.addBox(_worldX, _worldY, .98f, .98f, 0f, true);                             

    }
 }

public void setSize(int x, int y)
{
    this._width = x;
    this._height = y;
}
}

Step :6. Now create a PhysicsWorld.java class and put following code inside the class

package com.physicssample;
import org.jbox2d.collision.AABB;
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;

public class PhysicsWorld
{
    final private int MAXBOX = 20;
    final private float FRAMERATE = 30f;
    private float _timeStep = (1f / FRAMERATE);
    private int _iterations = 5;
    private int _count = 0;

    private AABB _box2dWorld;
    private World _myWorld;

    public void createWorld()
    {
        _box2dWorld = new AABB();
        _box2dWorld.lowerBound.set(new Vec2(-100f, -100f));
        _box2dWorld.upperBound.set(new Vec2(100f, 100f));

        Vec2 gravity = new Vec2(0f, -10f);
        boolean doSleep = false;
        _myWorld = new World(_box2dWorld, gravity, doSleep);

    }

    public void setGrav(float x, float y)
    {
        _myWorld.setGravity(new Vec2(x,y));
    }

    public void addBox(float x, float y, float xr, float yr, float angle, boolean dynamic)
    {
        if (_count < (MAXBOX-1))
        {
                BodyDef _groundBody;
                _groundBody = new BodyDef();
                _groundBody.position.set(new Vec2(x, y));
                _groundBody.angle = angle;
                Body groundBody = _myWorld.createBody(_groundBody);

                PolygonDef _groundShape;
                _groundShape = new PolygonDef();
                _groundShape.setAsBox(xr, yr);
                _groundShape.density = 1.0f;
                groundBody.createShape(_groundShape);
                if (dynamic)
                {
                        groundBody.setMassFromShapes();
               }
               if (dynamic)
               {
                        _count++;
                }
        }
    }

    public void update()
    {
        _myWorld.step(_timeStep, _iterations);
    }

    public int getCount()
    {
        return _count;
    }

    public Body getBodyList()
    {
        return _myWorld.getBodyList();
    }
}

Step :6. Now create a ObjectCreater.java class and put following code inside the class

package com.physicssample;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;

public class ObjectCreater
{
        private FloatBuffer _vertexBuffer;
        private ShortBuffer _indexBuffer;
        private FloatBuffer _texBuffer;
        private int _vertexCount = 0;
        private boolean _hasTexture = false;
        private int[] _texture = new int[1];

        public ObjectCreater(float[] coords, float[] tcoords, short[] icoords, int vertexes)
        {
                this(coords, icoords, vertexes);
                _texBuffer = makeFloatBuffer(tcoords);
        }

        public ObjectCreater(float[] coords, short[] icoords, int vertexes)
        {
            _vertexCount = vertexes;
            _vertexBuffer = makeFloatBuffer(coords);
            _indexBuffer = makeShortBuffer(icoords);
        }

    protected static FloatBuffer makeFloatBuffer(float[] arr) {
        ByteBuffer bb = ByteBuffer.allocateDirect(arr.length*4);
        bb.order(ByteOrder.nativeOrder());
        FloatBuffer fb = bb.asFloatBuffer();
        fb.put(arr);
        fb.position(0);
        return fb;
    }

    protected static ShortBuffer makeShortBuffer(short[] arr) {
        ByteBuffer bb = ByteBuffer.allocateDirect(arr.length*4);
        bb.order(ByteOrder.nativeOrder());
        ShortBuffer ib = bb.asShortBuffer();
        ib.put(arr);
        ib.position(0);
        return ib;
    }

        public void loadTexture(GL10 gl, Context mContext, int mTex) {
                _hasTexture = true;
		        gl.glGenTextures(1, _texture, 0);
		        gl.glBindTexture(GL10.GL_TEXTURE_2D, _texture[0]);
		        Bitmap bitmap;
		        bitmap = BitmapFactory.decodeResource(mContext.getResources(), mTex);
		        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
		        bitmap.recycle();
                gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR );
                gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR );
        }

       public void draw(GL10 gl) {
                if (_hasTexture) {
                gl.glEnable(GL10.GL_TEXTURE_2D);
                gl.glBindTexture(GL10.GL_TEXTURE_2D, _texture[0]);
                    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, _texBuffer);
                } else {
                    gl.glDisable(GL10.GL_TEXTURE_2D);
                }
	            gl.glFrontFace(GL10.GL_CCW);
	            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);
	            gl.glDrawElements(GL10.GL_TRIANGLE_FAN, _vertexCount, GL10.GL_UNSIGNED_SHORT, _indexBuffer);
                gl.glDisable(GL10.GL_TEXTURE_2D);
        }

        public void draw(GL10 gl, float x, float y, float z, float rot, float scale) {
                this.draw(gl, x, y, z, rot, scale, scale);
        }

        public void draw(GL10 gl, float x, float y, float z, float rot, float scaleX, float scaleY) {
                gl.glPushMatrix();
                gl.glTranslatef(x, y, z);
                gl.glRotatef(rot, 0f, 0f, 1f);
                gl.glScalef(scaleX, scaleY, 1f);
                this.draw(gl);
                gl.glPopMatrix();
        }

}

Step :6. Run your app it will look like this . If you have any question or need more clarification please write on forum.dremsus.com.
final

Tags: , , , , , , , , , , , , , , , , , , , ,

Leave a Reply