20 diciembre 2008

Remake (parcial) de Fruity Frank... 22 - Rediseñando usando clases (3 - Personajes animados)

Todavía queda una cosa por hacer para que el juego rediseñado usando clases tenga las mismas funcionalidades que la versión anterior: personajes animados.

Habíamos comentado que lo ideal sería que la clase "ElementoGráfico" nos permitiera tanto manejar elementos con una única imagen estática como elementos que tengan varias imágenes, que actuarían como distintos fotogramas para dar una sensación de movimiento más real. Incluso sería deseable que pidiéramos tener distintas secuencias de imágenes según el sentido en que se muestra el personaje (izquierda, derecha, arriba o abajo).

Tampoco es especialmente difícil. Vamos con ello...

  • Por una parte, ahora tendremos un array de imágenes dentro de la clase ElemGrafico. Nos interesará no declarar el array como "Imagen[,]", sino como "Imagen[][]", para permitir que haya distinto número de fotogramas en un sentido o en otro:


    // La secuencia de imagenes, si es animada
protected Imagen[][] secuencia;


  • Necesitaremos variables para saber en qué dirección nos encontramos, y en qué número de fotograma. Para que el fuente sea más legible, podemos crear variables (o incluso constantes) llamadas ARRIBA, ABAJO, etc.


    protected byte fotogramaActual;
protected byte direccion;
public const byte ABAJO = 0;
public const byte ARRIBA = 1;
public const byte DERECHA = 2;
public const byte IZQUIERDA = 3;


  • Ahora la rutina de Dibujar deberá mostrar una imagen estática o una imagen animada, según lo que hayamos cargado:


    public  void Dibujar()
{
if (contieneSecuencia)
secuencia[direccion][fotogramaActual].Dibujar(x, y);
else if (contieneImagen)
miImagen.Dibujar(x, y);
else
Hardware.ErrorFatal("Se ha intentado dibujar una imagen no cargada!");
}


  • Donde la variable "contieneSecuencia" se declara con valor "false" en el constructor, y recibe el valor "true" cuando cargamos.


    public  ElemGrafico()
{
contieneImagen = false;
contieneSecuencia = false;
direccion = ABAJO;
fotogramaActual = 0;
secuencia = new Imagen[4][];
}


  • Cuando cargamos, recibiremos un "array" de nombres de imágenes. Deberemos reservar espacio para todas ellas, y cargarlas una por una:


    public void CargarSecuencia(byte direcc, string[] nombres)
{
contieneImagen = true;
contieneSecuencia = true;
byte tamanyo = (byte) nombres.Length;
secuencia[direcc] = new Imagen[tamanyo];
for (byte i=0; i< nombres.Length; i++) {
secuencia[direcc][i] = new Imagen(nombres[i]);
}
}


  • Cuando cambiemos de dirección, deberemos volver al fotograma número 0, por si acaso en una dirección hubiera más fotogramas que en otra. Si la dirección que nos piden es en la que ya estamos, no debería hacer falta volver al fotograma 0:


    public  void CambiarDireccion(byte nuevaDir)
{
if (direccion != nuevaDir)
{
direccion = nuevaDir;
fotogramaActual = 0;
}
}


  • En el personaje, cambiará el constructor, que ahora no carga una imagen sino una secuencia:


    public  Personaje(Juego j)  // Constructor
{
miJuego = j;
...
CargarSecuencia( ARRIBA,
new string[] {"imagenes/personajea1.png",
"imagenes/personajea2.png"} );
CargarSecuencia( DERECHA,
new string[] {"imagenes/personajed1.png",
"imagenes/personajed2.png"} );
...
}


  • Además, debemos decidir cuando queremos que cambie la apariencia del personaje. Podría ser en cada fotograma del juego, y entonces incluiríamos "miPersonaje.SiguienteFotograma" dentro del método "SiguienteFotograma" de Juego, pero en el Fruity Frank original, el personaje sólo cambia de forma cuando se mueve, así que lo haremos dentro de "MoverDerecha" y los métodos similares:


    public  void MoverDerecha()
{
if (miJuego.GetNivelActual().EsPosibleMover( (short) (x+incrX), y) )
{
CambiarDireccion(DERECHA);
SiguienteFotograma();
x += incrX;
miJuego.GetMarcador().IncrPuntuacion(
miJuego.GetNivelActual().PuntosMover( x, y ));
}
}


  • Con eso ya hemos igualado casi todas las funcionalidades de la versión "no orientada a objetos", excepto el disparo. Pronto volveremos a incorporarlo, pero ahora será un disparo un poco más "real", en vez de moverse siempre hacia la derecha, haya obstáculos o no los haya.


Si quieres ver el fuente completo, todo el fuente del proyecto está en: code.google.com/p/fruityfrank