39. Un personaje animado.

Para que el movimiento de un personaje parezca más real, deberíamos tener distintas imágenes, una para cada "fotograma" de ese movimiento.

La forma más sencilla sería que cada "Elemento gráfico" no tuviera una única imagen, sino un "array" de imágenes:

protected Imagen[] secuencia;

Como no siempre estaremos mostrando el mismo fotograma de esa secuencia, deberemos llevar un contador para saber cuál es el fotograma actual:

protected byte fotogramaActual;

Además, ahora el método que se encarga de dibujar tendrá que saber si debe mostrar una imagen tomada de este array o no, para lo que nos interesará tener un "booleano" auxiliar:

protected bool contieneSecuencia = false;

De modo que "DibujarOculta" quedaría así:

public void DibujarOculta()
{
    if (!visible) return;
 
    if (contieneSecuencia)
        secuencia[fotogramaActual].DibujarOculta(x, y);
    else
        imagen.DibujarOculta(x, y);
}
 

Nos falta un constructor que no cargue una imagen, sino que prepare las cosas para cargar una secuencia: (o dentro de poco tiempo, varias):

public ElemGrafico(int nuevoAncho, int nuevoAlto)
{
    contieneSecuencia = true;
 
    visible = true;
    ancho = nuevoAncho;
    alto = nuevoAlto;
}

Y el método encargado de cargar las secuencias podría recibir un array de strings, que fueran los nombres de cada una de las imágenes que forman esa secuencia:

public void CargarSecuencia(string[] nombres)
{
    if (!contieneSecuencia)
        return;
 
    byte tamanyo = (byte)nombres.Length;
    secuencia = new Imagen[tamanyo];
    for (byte i = 0; i < nombres.Length; i++)
        secuencia[i] = new Imagen(nombres[i]);
}
 

Sólo nos falta el método encargado de pasar de una imagen a la siguiente dentro de esa secuencia. Lo podemos llamar "SiguienteFotograma":

public void SiguienteFotograma()
{
    if (!contieneSecuencia)
        return;
 
    if (fotogramaActual < secuencia.Length - 1)
        fotogramaActual++;
    else
        fotogramaActual = 0;
}


Con eso ya tenemos toda la infraestructura necesaria para que un "elemento gráfico" esté formado por una secuencia de imágenes. Ahora vamos a aplicarlo a la clase "Enemigo":

En primer lugar, el constructor se basará en el de ElemGrafico que no carga imagen, sino que prepara para cargar una secuencia. Además, cargará una secuencia formada por dos foogramas:

public Enemigo()
    : base(36, 42)
{
    incrX = 5;
    CargarSecuencia(new string[] { 
        "enemigo1.png", "enemigo2.png" });
}

Y el método "Mover", además de calcular la siguiente posición del movimiento, cambiará de un fotograma visible al siguiente:

public void Mover()
{
    SiguienteFotograma();
 
    if (x < 50)
        ...

Puedes descargar el juego completo, incluyendo fuentes, proyecto, imágenes y ejecutable, para ver los fuentes completos y probar el resultado.

Ejercicio propuesto: Aplica estos cambios al "Personaje", para que también intercambie al menos entre dos fotogramas.