Simple Android ball game
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.




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
发表评论
DnwVtM very nice post, i actually love this website, keep on it
gVJqVR It as actually a wonderful and handy section of data. Now i am satisfied that you choose to discussed this useful details about. Remember to stop us educated like this. Many thanks for revealing.
ahHJH7 It as not that I want to copy your web-site, but I really like the design. Could you tell me which theme are you using? Or was it custom made?
SsZLTp Very neat article post.Thanks Again. Great.
I read your post and wished I'd wrttein it
RqmiiW You ave made some really good points there. I looked on the internet to find out more about the issue and found most individuals will go along with your views on this web site.
8rqRrK Well I truly liked reading it. This information procured by you is very practical for accurate planning.
chRQws particular country of the person. You might get one
jHOakO Thanks a lot for the article.Much thanks again. Want more.
It as enormous that you are getting ideas from this piece of writing as well as from our argument made at this place.
XmmVGw Wohh precisely what I was searching for, thankyou for putting up.
ifh3f5 Thanks so much for the article.Really looking forward to read more. Awesome.
wuzw6M Wow! Thank you! I always wanted to write on my blog something like that. Can I include a fragment of your post to my blog?
aCV2jR wonderful post, very informative. I wonder why the other specialists of this sector do not notice this. You must continue your writing. I am confident, you have a huge readers a base already!
ktmS5r
Yi2wGg This website was how do I say it? Relevant!! Finally I have found something which helped me. Thanks!
Zbhoy3 Woman of Alien Fantastic perform you might have accomplished, this page is really amazing with amazing facts. Time is God as strategy for holding almost everything from occurring at once.
kFaWPg Whoa! This blog looks exactly like my old one! It as on a entirely different topic but it has pretty much the same layout and design. Wonderful choice of colors!
MGxiSZ I think this is a real great blog post. Want more.
efNuAY You made some decent points there. I looked on the internet for the issue and found most persons will go along with with your site.
tqDhxM Wonderful article! We are linking to this particularly great content on our site. Keep up the great writing.
kIqjG9 Appreciate you sharing, great article post. Keep writing.
3jt96s I think this is a real great blog post.Really looking forward to read more. Will read on...
7KS2Ce you may have an important weblog here! would you like to make some invite posts on my weblog?
dH06OM whoah this weblog is wonderful i love studying your posts. Stay up the good work! You already know, a lot of persons are searching around for this information, you can help them greatly.
Cic0hd It's exhausting to search out educated people on this matter, however you sound like you understand what you're speaking about! Thanks
oRHqkr hello!,I like your writing so much! share we communicate more about your article on AOL? I require an expert on this area to solve my problem. Maybe that's you! Looking forward to see you.
5RV6iK Im obliged for the blog article.Thanks Again. Great.
ELU3dg I appreciate you sharing this article. Awesome.
MD3VfH Thanks for the article.Thanks Again. Want more.
hWliyk Thanks for the article.Really thank you! Awesome.
jbw9bZ Major thankies for the blog article.Much thanks again. Awesome.
jmFsPa A round of applause for your article post.Thanks Again. Will read on...
pFezJ1 Thanks so much for the article.Really looking forward to read more.
n4kVMO I appreciate you sharing this blog post.Really thank you! Awesome.
tfKa4B Major thankies for the blog article.Thanks Again. Will read on...
txi9Ow wow, awesome article post.Much thanks again. Cool.
73Vgiq Looking forward to reading more. Great blog article.Thanks Again. Great.
gDXO2i A round of applause for your blog post.Much thanks again. Really Cool.
Hi there, I have noticed that occasionally this site renders an 404 server error message. I figured you would like to know. Best wishes