Nuestros primeros Sprites. Video tutorial de Programación de juegos en Android.

Un sprite es una imagen rasterizada 2D, parcialmente transparente, que está normalmente situada encima de una imagen de fondo. Los sprites se utilizan en los video juegos. Suele haber más de un sprite en la pantalla al mismo tiempo.

Pueden representar o bien a entidades de inteligencia artificial o el personaje principal controlado por el usuario.

Un sprite tiene una posición (x,y) y una velocidad (x,y). Puede contener su propia animación y sonido.

A continuación se pueden ver los bitmaps de nuestros personajes (sprites):

bad1.pgn bad2.pgn bad3.pgn bad4.pgn bad5.pgn bad6.pgn
good1.pgn good2.pgn good3.pgn good4.pgn good5.pgn good6.pgn

He utilizado esta página web para hacer los personajes. Prueba a hacer los tuyos, es muy divertido! ;)

http://www.famitsu.com/freegame/tool/chibi/index2.html

Si tienes problemas con el japonés puedes preferir este link;

http://www.famitsu.com/freegame/tool/chibi/index2.html translated

Ahora que tenemos los bitmaps, vamos a crear nuestra primera clase Sprite:

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);

       }

}  

 

Como se ve, todo el código referente a la posición y a la velocidad se ha movido (incluyendo los bordes de la vista) a nuestra clase Sprite. También he movido el gráfico del sprite a esta clase y he hecho unas modificaciones en la velocidad.

 

Ahora tenemos todo lo referente a nuestro sprite, dentro de esta clase.

 

En el constructor pedimos que nos pasen como parámetro la vista (gameView) y el bitmap (bpm). La vista y el bitmpa son necesarios para obtener los anchos para la detección de la colisión con el borde. Bpm también se utiliza para dibujar en el canvas.

 

Si en la clase GameView eliminamos todo esto y añadimos una nueva instancia de Sprite obtendremos lo siguiente:

 

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);

       }

}

 

Si está todo ok y lo ejecutamos tendremos el siguiente resultado:

Ahora vamos a modificarlo para dibujar una sola de las 12 imágenes. Queremos dibujar un personaje diferente cada vez para obtener una animación. Cada fila es un dibujo diferente. Para hacerlo más simple vamos a empezar con la segunda fila en la que el personaje parece que anda desde la derecha a la izquierda.

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);

       }

}

 

En el constructor calculamos el ancho y la altura del sprite.

En el método update fijamos donde dibujo el sprite (x = x + xSpeed) y vamos cambiando la animación utilizada (currentFrame = ++currentFrame % BMP_COLUMNS). La variable currentFrame sólo puede tener los valores 0, 1 o 2.

En el método onDraw utilizamos el método canvas.drawBitmap(bmp, src, dst, null); src es el rectángulo fuente dentro del bitmap que va a ser dibujado dentro del rectángulo destino en el canvas (dst).

<< Game Loop y Animación Sprites velocidad y Animación >>