Create a game like Flappy Bird in Android using AndEngine
DownloadKeywords: AndEngine AndEnginePhysicsBox2DExtension SimpleBaseGameActivity ResourceManager SceneManager MenuScene CameraScene AutoParallaxBackground AnimatedSprite DynamicSpriteBatch TiledSprite Sound Music HUD Font PhysicsHandler GenericPool PhysicsWorld Fixture Body ContactListener
Contents- Overview
- Create a new Eclipse Android project
- Add AndEngine library
- Add AndEngine Physics Box2D extension
- Android manifest
- AndEngine concepts
- Game Activity
- Resource Manager
- TextureAtlas & TextureRegion
- Font
- Sound & Music
- Scene Manager
- Base Scene
- Splash Scene
- Main Menu Scene
- Sub Menu Scene
- Game Scene
- Auto Parallax Background
- HUD
- Bird
- Pipes
- Generic Pool
- Physics World
- Body & Fixture
- Contact Listener
- Camera Scene
- What's next?
23. Physics World
Physics means real-world stuff like gravity, collision, density, friction etc. and is made available in AndEngine game through Box2D extension (AndEnginePhysicsBox2DExtension).We'll create a PhysicsWorld with gravity which will make the bird fall down and set a contact listener for the bodies. We also use scene touch listener created previously to impart upward velocity to the bird when user taps the screen.
Here are the modifications to GameScene class.
private PhysicsWorld mPhysicsWorld; @Override public void createScene() { //... mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false); mPhysicsWorld.setContactListener(createContactListener()); //TODO create body and fixture //... /* The actual collision-checking. */ registerUpdateHandler(new IUpdateHandler() { @Override public void reset() {} @Override public void onUpdate(float pSecondsElapsed) { //... mPhysicsWorld.onUpdate(pSecondsElapsed); } }); } @Override public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) { if(mPhysicsWorld != null) { if(!mGameOver && pSceneTouchEvent.isActionDown()) { jumpFace(mBird); return true; } } return false; } private void jumpFace(final AnimatedSprite face) { //TODO implement } private ContactListener createContactListener() { //TODO implement return null; }Notice the highlighted line of code that passes scene updates to the physics world. This is how physics world is connected to the engine.
24. Body & Fixture
In physics world, the objects we deal with are body and fixture. Fixture has real world properties like density, elasticity, friction. Body is made of fixture and has a shape.Let's create the bodies and fixtures relevant to the game.
@Override public void createScene() { //... //create body and fixture final FixtureDef wallFixtureDef = PhysicsFactory.createFixtureDef(0, 0, 0); final Body groundBody = PhysicsFactory.createBoxBody(mPhysicsWorld, ground, BodyType.StaticBody, wallFixtureDef); groundBody.setUserData("ground"); final FixtureDef birdFixtureDef = PhysicsFactory.createFixtureDef(1, 0, 0); final Body birdBody = PhysicsFactory.createCircleBody(mPhysicsWorld, mBird, BodyType.DynamicBody, birdFixtureDef); birdBody.setUserData("bird"); mBird.setUserData(birdBody); mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(mBird, birdBody, true, false)); //... } private void jumpFace(final AnimatedSprite face) { face.setRotation(-15); final Body faceBody = (Body)face.getUserData(); final Vector2 velocity = Vector2Pool.obtain(0, -5); faceBody.setLinearVelocity(velocity); Vector2Pool.recycle(velocity); }We create a body for ground and bird. Additionally, we register a physics connector for the bird that is how it falls due to gravity. The physics connector ties bodies and sprites together in order to translate the physics calculations into sprite movement.
Also, we implement jumpFace() to impart velocity to the bird body. Recall that this method gets called on scene touch event.
25. Contact Listener
In physics world, it is easy to detect contact between bodies using contact listener. We had already registered a contact listener in createScene() method of GameScene class.Let's now implement the empty createContactListener() method created previously in GameScene class.
private ContactListener createContactListener() { ContactListener contactListener = new ContactListener() { @Override public void beginContact(Contact pContact) { final Fixture fixtureA = pContact.getFixtureA(); final Body bodyA = fixtureA.getBody(); final String userDataA = (String) bodyA.getUserData(); final Fixture fixtureB = pContact.getFixtureB(); final Body bodyB = fixtureB.getBody(); final String userDataB = (String) bodyB.getUserData(); if (("bird".equals(userDataA) && "ground".equals(userDataB)) || ("ground".equals(userDataA) && "bird".equals(userDataB))) { mGameOver = true; mBird.stopAnimation(0); mPipe.die(); mAutoParallaxBackground.setParallaxChangePerSecond(0); if (score > most) { most = score; mActivity.setMaxScore(most); } mBird.setVisible(false); mHudText.setVisible(false); //TODO display game over with score } } @Override public void endContact(Contact contact) { } @Override public void preSolve(Contact contact, Manifold oldManifold) { } @Override public void postSolve(Contact contact, ContactImpulse impulse) { } }; return contactListener; }The important thing to note is that we have to check the user data of the bodies to know which entities collided. If bird touches the ground we end the game and display game over child scene.
We'll next implement the child scenes that are displayed before game start and after game over.