Introduction 

This is tutorial for developing Ball Game in Android OS. It will introduce you with developing android games using AndEngine(free Android 2d open source game engine). To understand this tutorial, you will need to have some basic knowledge about AndEngine and programming in Java. If you don't have knowledge about AndEngine, you should check this link. Goal of this tutorial is to teach you how to make your own Android game.

The Game 

It's classic game idea implemented in modern way. You control ball using the accelerometer sensor and your goal is to collect all "diamants", avoid enemy balls and to come safetly to the end.

pic1.jpg

pic2.jpg

 pic3.jpg

pic4.jpg

What you need to start?   

To start developing your own Android games, you need SDK and game engine (it will make your life way easier!). I used Eclipse SDK and game engine called AndEngine. Are you wondering how to setup Eclipse SDK and AndEngine together? Click on the link to see "Getting started with AndEngine" tutorial.

Let's coding!

Let's see what is hidding in the code! Please note that I didn't paste full source code here. I just past some snippets. You can download full project to see full souce code.

First we will take short tour in main class.   

public class GameLogicController extends BaseGameActivity implements IAccelerometerListener{
                 public PlayerProfileManager playerProfileManager; 
                 public LevelController levelController;
                 private Camera camera;
                 protected PhysicsWorld mPhysicsWorld;
                 public Texture mTexture;
                 public TextureRegion enemyTextureRegion;
                 private float mGravityX;
                 private float mGravityY;
                 private final Vector2 mTempVector = new Vector2();
                 public TiledTextureRegion mCircleFaceTextureRegion;
                 private RepeatingSpriteBackground mGrassBackground;
                 private Sound mGameOverSound;
                 ...
}
GameLogicController is base class in our game, BaseGameActivity is base class in AndEngine and IAccelerometerListener is interface used to get data from your mobile phone accelerometer sensor. PlayerProfileManager and LevelController are just some game classes that you will know it later.

@Override
public Engine onLoadEngine() {
		...

		levelController.mCameraWidth = 460;
		levelController.mCameraHeight = 320;
		camera = new Camera(0, 0, levelController.mCameraWidth, levelController.mCameraHeight);
		return new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(levelController.mCameraWidth, levelController.mCameraHeight), camera).setNeedsSound(true));  
}

Method onLoadEngine create new game engine. First we need to create Camera for declaring screen resolution. Important and very useful thing is, that Camera resolution isn't connected with mobile phone resolution. That will save you really a lot of work with graphics positions! For example, we declared screen resolution 460x320. You don't need to take care about mobile phone resolution, because you will always use AndEngine resolution (460x320) and AndEngine will automatically recalculate AndEngine resolution to real mobile phone resolution. Next step is to create new Engine. You just need to declare screen orientation (landscape or portrait), screen resolution and custom options. We used only one custom option, for enabling sound.  

public Scene newGameLevelScene(int levelId){
		Scene scene = new Scene(2);
		this.mPhysicsWorld = new FixedStepPhysicsWorld(60, new Vector2(0, 0), false);
		levelController.setScene(scene);
		levelController.setmPhysicsWorld(mPhysicsWorld);
		levelController.createFrame();
		levelController.loadLevel(levelId);
		this.enableAccelerometerSensor(this);
		scene.registerUpdateHandler(this.mPhysicsWorld);
		return scene;
	}

Here you can see four very important things. First we need to create new display Scene and FixedStepPhysicWorld. FixedStepPhysicWorld is 2D simulation of real world physic model. It's used for calculating gravity, collision detection... Let's focus on PhysicWorld. It takes three parameters. First one is frames per seconds (how many times per second should screen be refreshed), second is gravity vector and third is just if we want to allow PhysicWorld sleeping. At the end we need to set enableAccelerometerSensor and registerUpdateHandler

@Override
public void onAccelerometerChanged(AccelerometerData pAccelerometerData) {
		this.mGravityX = pAccelerometerData.getY() * 2;
		this.mGravityY = pAccelerometerData.getX() * 2;
		if(this.mGravityX > con)
			this.mGravityX = con;
		if(this.mGravityY > con)
			this.mGravityY = con;
		if(this.mGravityX < con * (-1))
			this.mGravityX = con * (-1);
		if(this.mGravityY < con * (-1))
			this.mGravityY = con * (-1);
		this.mTempVector.set(this.mGravityX, this.mGravityY);
		this.mPhysicsWorld.setGravity(this.mTempVector);
	}

In method newGameScene we enabled accelometerSensor that control method onAccelerometerChanged. This method is called whenever is accelerometer changed. 

<span lang="en" class="short_text" id="result_box"><span class="hps" title="Kliknite za druge prevode"></span>protected Scene createQuitScene() {
		
		Scene scene = new Scene(2);
		scene.setBackground(this.mMenuBackground);
		Sprite buttonLevel = new Sprite(100, 100, 250, 70, this.mMenuOkTextureRegion)
		{
			@Override
			public boolean onAreaTouched(TouchEvent pSceneTouchEvent,float pTouchAreaLocalX, float pTouchAreaLocalY)
			{
				if(checkTouchTime())
					GameLogicController.getInstance().finish();
				
				return true;
			}
		};
		
		scene.registerTouchArea(buttonLevel);
		scene.getTopLayer().addEntity(buttonLevel);
		...
          }</span> <span lang="en" class="short_text" id="result_box">
</span> 

Sprite is just graphic on the scene. Much more interesting is method onAreaTouched. It is callback and whenever someone will press on the button (sprite) this method will be called. Don't forget to register touch area (registerTouchArea) and to add button (addEntity) to scene! 

We just finished with main class, so we can move LevelController class. 

public class LevelController   {
        private ArrayList<Shape> enemyList;
	private ArrayList<Shape> goodsList;
	private ArrayList<Shape> endPointList;
        ...

public void createPlayer(TiledTextureRegion mCircleFaceTextureRegion, int x, int y){
		//mPlayer = new Player(x, y, mCameraHeight/10,mCameraHeight/10,mCircleFaceTextureRegion, this);
		mPlayer = new Player(x, y, 30,30,mCircleFaceTextureRegion, this);
		FixtureDef FIXTURE = PhysicsFactory.createFixtureDef(1, 0.5f, 0.5f);
		Body body;
		body = PhysicsFactory.createCircleBody(mPhysicsWorld, mPlayer, BodyType.DynamicBody, FIXTURE);
		
		mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(mPlayer, body, true, true, false, false));
		scene.getTopLayer().addEntity(mPlayer);
		
         }
...
}

LevelController class is responsible for loading levels and controlling level events.Arraylists enemyList, goodsList and endPointList are used  for storing enemy balls, goods (diamants) and end points (finish line). Method createPlayer create new player on position x,y with size 30x30, PhysicFactory.CreateFixtureDef create new physical object. Physical object should be registered to mPhysicsWorld for collision detection.  

public void callbackCollisionGoods(int i){
		Shape goodShape = goodsList.get(i);
		scene.getBottomLayer().removeEntity(goodShape);
		goodsList.remove(i);
	}

If player collect diamond, callbackCollisionGoods is called. In this method we remove diamont from goodsList and goodShape from scene.

Other methods in this class are very similar and I won't describe it to details. 

Next class is PlayerProfileManager. In this class you will find only basic java code except method WriteSettings.

private void WriteSettings() {
		String FILENAME = "settings2";
		FileOutputStream fos = null;
		DataOutputStream dos;

		try {
			fos = gameLogicController.openFileOutput(FILENAME, Context.MODE_PRIVATE);

		} catch (FileNotFoundException e) {
			
		}
		try {
			dos=new DataOutputStream(fos);
			
			dos.writeInt(unlockedLevelId);
			
		} catch (IOException e) {
		}
		try {
			fos.close();
		} catch (IOException e) {
		}
	}

In method WriteSettings we save level information to mobile phone. It's necessary to open, write and close file. Actually we save only one number - ID of last unlocked level. For example, if level ID is 5, then levels 1 ,2 ,3, 4 and 5 are unlocked. 

Last described class is Player.  

public class Player extends AnimatedSprite   {
...
@Override
	protected void onManagedUpdate(final float pSecondsElapsed) {
		super.onManagedUpdate(pSecondsElapsed);
		onBeforePositionChanged();
	}

private boolean onBeforePositionChanged(){
		
		//speed up
		if(frameCount < 2){
			frameCount++;
			return true;
		}
		frameCount = 0;
		
		int enemyListSize = levelController.getEnemyList().size();
		for(int i = 0; i < enemyListSize; i++)
			if(this.collidesWith(levelController.getEnemyList().get(i)))
			{
				levelController.callbackCollisionEnemy();
				return false;
			}
		for(int i = 0; i < levelController.getGoodsList().size(); i++)
			if(this.collidesWith(levelController.getGoodsList().get(i)))
			{
				levelController.callbackCollisionGoods(i);
				return false;
			}

		for(int i = 0; i < levelController.getEndPointList().size(); i++)
			if(this.collidesWith(levelController.getEndPointList().get(i)))
			{
				levelController.callbackCollisionWithEndPoint();
				return false;
			}
		return true;
	}
...
} 

Player class is extended AnimatedSprite. Different between Sprite and AnimatedSprite is just one - animated sprite is consists of more pictures (animation) while Sprite consist of one picture. OnManagedUpdate is callback executed every "x" miliseconds. OnBeforePositionChanged check if player is in collision with enemy, diamond or end point. If it's in collision then appropriate callback is executed.

Android game developing       

I hope you see that android game developing isn't too hard. With some practice, you can develop your android dream game. On the end of the tutorial i would like to thank you for your attention. This is my first article and i would be really glad if you give me any feedback


History   

  • 29 april, 2011- Article uploaded 
推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架