Handling animation in Android Game Programming

December 13th, 2011 by aabhaanjan

In this article we are going to learn how to handle the animations for a game in Android programming.
We are going to show an animation of duck and its creation on touch event. So lets begin it wih steps :

Step :1 Create a motodev Project .
1

Step :2 Now put your animation sprite(png) file into res/drawable folder.Your png will look like this
duck

Step :3 Open your Layout/Main.xml file and put following code there :

[xml]


[/xml]

Step :4 Open your values/String.xml and put following code inside that

[xml]


AnimatedDuck

[/xml]

Step :5 Your MainActivity class will look like this :
[xml]

package com.annimatedspriteapp;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

}

}
[/xml]

Step :6 Now create a Class for the Sprite . Here I am creating the class named ‘DuckSprite’.
and adding following codes :

[xml]

package com.annimatedspriteapp;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;

public class DuckSprite {
private Bitmap _duckAnim;
private int _xPos;
private int _yPos;
private Rect _duckRect;
private int _fps;
private int _frameCount;
private int _currentFrame;
private long _frameTimer;
private int _duckHeight;
private int _duckWidth;
private boolean _loop;
public boolean dispose;

public DuckSprite() {
_duckRect = new Rect(0, 0, 0, 0);
_frameTimer = 0;
_currentFrame = 0;
_xPos = 80;
_yPos = 200;
dispose = false;
}

public void Initialize(Bitmap __bitmap, int __height, int __width, int __fps, int __frameCount, boolean __loop) {
this._duckAnim = __bitmap;
this._duckHeight = __height;
this._duckWidth = __width;
this._duckRect.top = 0;
this._duckRect.bottom = _duckHeight;
this._duckRect.left = 0;
this._duckRect.right = _duckWidth;
this._fps = 1000 / __fps;
this._frameCount = __frameCount;
this._loop = __loop;
}

public int getXPos() {
return _xPos;
}

public int getYPos() {
return _yPos;
}

public void setXPos(int value) {
_xPos = value – (_duckWidth/2);
}

public void setYPos(int value) {
_yPos = value – (_duckHeight/2);
}

public void Update(long _totalTime) {
if( _totalTime > _frameTimer + _fps) {
_frameTimer = _totalTime;
_currentFrame += 1;

if( _currentFrame >= _frameCount ) {
_currentFrame = 0;

if(!_loop)
dispose = true;

}

_duckRect.left = _currentFrame * _duckWidth;
_duckRect.right = _duckRect.left + _duckWidth;
}
}

public void draw(Canvas canvas) {
Rect dest = new Rect(getXPos(), getYPos(), getXPos() + _duckWidth,
getYPos() + _duckHeight);
canvas.drawBitmap(_duckAnim, _duckRect, dest, null);
}
}

[/xml]

Step :7 Now I am going to create the View Class. Here I named it DuckView

[xml]

package com.annimatedspriteapp;

import java.util.ArrayList;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Handler;

import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

class DuckView extends SurfaceView implements SurfaceHolder.Callback {
class AnimationThread extends Thread {
private Bitmap _duck;
private ArrayList _mSpritesArray;
private ArrayList _mSpritesArraytoRemove;

private boolean _isRunning = false;
private SurfaceHolder _mSurfaceHolder;
private Resources _res;

public AnimationThread(SurfaceHolder surfaceHolder, Context context, Handler handler) {

_mSurfaceHolder = surfaceHolder;
_res = context.getResources();
_mSpritesArray = new ArrayList();
_mSpritesArraytoRemove = new ArrayList();

}

@Override
public void run() {
while (_isRunning) {
Canvas _mcanvas = null;
try {
_mcanvas = _mSurfaceHolder.lockCanvas(null);
synchronized (_mSurfaceHolder) {
updateAnimation();
doDraw(_mcanvas);
}
} catch(Exception e){

}finally {

if (_mcanvas != null) {
_mSurfaceHolder.unlockCanvasAndPost(_mcanvas);
}
}
}
}

private void doDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
for( DuckSprite _anDuck : _mSpritesArray){
_anDuck.draw(canvas);
}
canvas.restore();
}

private void updateAnimation() {
long _currentTime = System.currentTimeMillis();
synchronized(_mSpritesArray){
for( DuckSprite _anDuck : _mSpritesArray){
_anDuck.Update(_currentTime);
if(_anDuck.dispose)
_mSpritesArraytoRemove.add(_anDuck);
}
}

synchronized(_mSpritesArraytoRemove){
_mSpritesArray.removeAll(_mSpritesArraytoRemove);
_mSpritesArraytoRemove.clear();
}

}

public void doTouch(MotionEvent event){
int action = event.getAction();
float x = event.getX();
float y = event.getY();
switch(action){
case MotionEvent.ACTION_DOWN:
DuckSprite _anDuck = new DuckSprite();
if(_duck == null)
_duck = BitmapFactory.decodeStream(_res.openRawResource(R.drawable.duck));
_anDuck.Initialize(_duck, 100, 100, 35,28, true);
_anDuck.setXPos((int)x);
_anDuck.setYPos((int)y);
synchronized(_mSpritesArray){
_mSpritesArray.add(_anDuck);
}
break;
}
}

public void setRunning(boolean _flag) {
_isRunning = _flag;
}

public void setSurfaceSize(int width, int height) {
synchronized (_mSurfaceHolder) {
}
}

}

private AnimationThread thread;

public DuckView(Context context, AttributeSet attrs) {
super(context, attrs);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
thread = new AnimationThread(holder, context, new Handler() {
});

setFocusable(true);
}

@Override
public boolean onTouchEvent(MotionEvent event){
thread.doTouch(event);
return super.onTouchEvent(event);
}

public AnimationThread getThread() {
return thread;
}

public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
thread.setSurfaceSize(width, height);
}

public void surfaceCreated(SurfaceHolder holder) {
thread.setRunning(true);
thread.start();
}

public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
thread.setRunning(false);
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
}

[/xml]

Step :8 Run your application It will look like this on touch even.
Most of function, varible names are self explanitory . If still you are getting any problem to understand it
write me in our forum section.
2

Tags: , , ,