Video Tutoriales

Android Game Programming 4. Our First Sprites

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_ROWS = 4;

       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.