Android Game Programming 4. Our First Sprite
A Sprite is a partially transparent 2D raster image that is usually placed over a background image. Sprites are used in video games. Normally there is more than one sprite in the screen at one time. They can represent AI (Artificial Intelligent) entities or the main character controlled by the player.
A Sprite has a (x,y) position and a (x,y) speed. It can contain its own animation and sounds. Next you can see the bitmaps for our sprite characters:
bad1.pgn | bad2.pgn | bad3.pgn | bad4.pgn | bad5.pgn | bad6.pgn |
good1.pgn | good2.pgn | good3.pgn | good4.pgn | good5.pgn | good6.pgn |
I made this characters using this Japan page. Try to make your owns, it's fun ;)
http://www.famitsu.com/freegame/tool/chibi/index2.html
if you have problem with Japanese maybe you prefer this link
http://www.famitsu.com/freegame/tool/chibi/index2.html translated
Now that we have the bitmaps let`s create our first Sprite class:
package com.edu4java.android.killthemall;
import android.graphics.Bitmap;
import android.graphics.Canvas;
public class Sprite {
private int x = 0;
private int xSpeed = 5;
private GameView gameView;
private Bitmap bmp;
public Sprite(GameView gameView,
Bitmap bmp) {
this.gameView=gameView;
this.bmp=bmp;
}
private void update() {
if (x > gameView.getWidth() - bmp.getWidth() - xSpeed) {
xSpeed = -5;
}
if (x + xSpeed< 0) {
xSpeed = 5;
}
x = x + xSpeed;
}
public void onDraw(Canvas canvas) {
update();
canvas.drawBitmap(bmp, x , 10, null);
}
}
As you can see, all the code about position and speed has been moved (including the borders control from the view) to our new Sprite class. I moved the sprite drawing to this class too and I made some little modifications in the speed.
Now we have everything referent to our sprite inside this class. In the constructor we ask for a reference to the view and to the bitmap bpm. The view and bpm are necessary to get their widths for the border coalition detection. Bpm is use to draw on the Canvas too.
We have to remove all this staff from the view and add a new Sprite instance and we end up with this:
package com.edu4java.android.killthemall;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView
{
private Bitmap bmp;
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private Sprite sprite;
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameLoopThread.setRunning(false);
while (retry) {
try {
gameLoopThread.join();
retry = false;
}
catch (InterruptedException e) {
}
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.bad1);
sprite = new Sprite(this,bmp);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
sprite.onDraw(canvas);
}
}
If everything is ok and you run this you get a screen like this:
Now we have to fix this to draw only one of the 12 characters. We need to draw a different character each time in order to get an animation. Each row is a different animation. To make it simple we are going to start with the second row that seems to walk from right to left.
package com.edu4java.android.killthemall;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
public class Sprite {
private static final int BMP_COLUMNS = 3;
private int x = 0;
private int y = 0;
private int xSpeed = 5;
private GameView gameView;
private Bitmap bmp;
private int currentFrame = 0;
private int width;
private int height;
public Sprite(GameView gameView,
Bitmap bmp) {
this.gameView = gameView;
this.bmp = bmp;
this.width = bmp.getWidth() / BMP_COLUMNS;
this.height = bmp.getHeight() / BMP_ROWS;
}
private void update() {
if (x > gameView.getWidth() - width - xSpeed) {
xSpeed = -5;
}
if (x + xSpeed < 0) {
xSpeed = 5;
}
x = x + xSpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
}
public void onDraw(Canvas canvas) {
update();
int srcX = currentFrame * width;
int srcY = 1 * height;
Rect
src = new Rect(srcX, srcY,
srcX + width, srcY + height);
Rect
dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
}
In the constructor we calculate our sprite width and height. In the update method we fix the border calculation and add a current frame value change. Current frame here can have only the values 0, 1 or 2. In the onDraw method we use the method canvas.drawBitmap(bmp, src, dst, null); src is a source rectangle inside the bitmap that is going to be written and dst is a destine rectangle in the canvas where we are going to write.
<< Game Loop and Animation | Sprites: Speed and Animation >> |