четверг, 17 ноября 2011 г.

Using AndEngine and physicsbox2d







AndEngine is one of the most popular free game engine for Android. Physicsbox2d seems to be powerful toll to create physics world in you game. It's easy to use them together, and I want to show you, how to:

1. Create Android project. Add libs andengine.jar, andenginephysicsbox2dextension.jar,
and folder armeabi that contains files libandenginephysicsbox2dextension.so, armeabilibxmp.so.

2. Inherit your activity class from BaseGameActivity, implement onLoadEngine and onLoadScene. Here is the code with comments:

   
public class MainActivity extends BaseGameActivity
{
    // Camera screen width
    private static final int CAMERA_WIDTH = 800;
    // Camera screen height
    private static final int CAMERA_HEIGHT = 480;
    // Physics Environment parameters
    private static final FixtureDef FIXTURE_DEF = PhysicsFactory.createFixtureDef(1, 0.5f, 0.5f);
    // Camera to look at world
    private Camera mCamera;
    // Scene, we look at through camera
    private Scene mScene;
    // Physical world
    private PhysicsWorld mPhysicsWorld;
    
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
    }

    // Loading engine
    public Engine onLoadEngine() {
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
        return new Engine(new EngineOptions(true, ScreenOrientation.PORTRAIT,
                new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT),
                this.mCamera));
    }

    public void onLoadResources() {
    }

    public Scene onLoadScene() {
        // Creating new one-layer scene
        mScene = new Scene(1);
        // Creating physical world with gravity
        this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false);
        mScene.registerUpdateHandler(mPhysicsWorld);
        return mScene;
    }

    public void onLoadComplete() {
    }
}


After starting project, we see friendly vacuum, our world is still empty.

2. Adding textures. We'll make special class for that. It's good idea to use static methods.

  
public class Textures {

    private Texture mTexture;
    private static TextureRegion mBallTextureRegion;
    private static TextureRegion mBackgroundTextureRegion;

    public Textures(final BaseGameActivity activity, final Engine engine) {
        // Atlas for textures
        mTexture = new Texture(1024, 1024,
                TextureOptions.BILINEAR_PREMULTIPLYALPHA);

        // Image size - 512x1024.
        mBackgroundTextureRegion = TextureRegionFactory.createFromAsset(
                mTexture, activity, "gfx/bkg.png", 0, 0);
        mBallTextureRegion = TextureRegionFactory.createFromAsset(
                mTexture, activity, "gfx/ball.png", 512, 0);

        engine.getTextureManager().loadTexture(mTexture);
    }

    public static TextureRegion getBackground() {
        return mBackgroundTextureRegion;
    }

    public static TextureRegion getBallTextureRegion() {
        return mBallTextureRegion;
    }
}



3. Initializing this object in activity

   
public void onLoadResources() {
        mTextures = new Textures(this, getEngine());
    }


4. And the last thing: fill Scene with sprites and objects.
   
public Scene onLoadScene() {
        mScene = new Scene(1);
        this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false);
        mScene.setBackground(new SpriteBackground(new Sprite(0, 0, Textures.getBackground())));
        
        // Lines will be borders
        Line line_top = new Line(0, 0, CAMERA_WIDTH, 0, 5.0f * metrics.density);
        Line line_left = new Line(0, 0, 0, CAMERA_HEIGHT, 5.0f * metrics.density);
        Line line_right = new Line(CAMERA_WIDTH, 0, CAMERA_WIDTH, CAMERA_HEIGHT, 5.0f * metrics.density);
        Line line_bottom = new Line(0, CAMERA_HEIGHT, CAMERA_WIDTH, CAMERA_HEIGHT, 5.0f * metrics.density);
        // Physical bodies based on lines
        Body wall_top = PhysicsFactory.createLineBody(mPhysicsWorld, line_top, FIXTURE_DEF);
        Body wall_left = PhysicsFactory.createLineBody(mPhysicsWorld, line_left, FIXTURE_DEF);
        Body wall_right = PhysicsFactory.createLineBody(mPhysicsWorld, line_right, FIXTURE_DEF);
        Body wall_bottom = PhysicsFactory.createLineBody(mPhysicsWorld, line_bottom, FIXTURE_DEF);

        // Ball sprite
        Sprite mSprite = new Sprite(0.0f, 0.0f, 100, 100, Textures.getBallTextureRegion());
        mSprite.setPosition(100, 100);
        // Ball body
        Body mBody = PhysicsFactory.createCircleBody(mPhysicsWorld, 100, 100, 50, 0, BodyType.DynamicBody, FIXTURE_DEF);
               
        // Connecting sprites with physical bodies
        this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(line_top, wall_top, true, true));
        this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(line_left, wall_left, true, true));
        this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(line_right, wall_right, true, true));
        this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(line_bottom, wall_bottom, true, true));
        mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(mSprite, mBody, true, true));
        
        // Attaching sprites to scene
        this.mScene.attachChild(mSprite);
        this.mScene.attachChild(line_top);
        this.mScene.attachChild(line_left);
        this.mScene.attachChild(line_right);
        this.mScene.attachChild(line_bottom);
 
        mScene.registerUpdateHandler(mPhysicsWorld);
        return mScene;
    }



That's all! Start project, and you see ball, falling and jumping according to physics laws.