40. Varias animaciones distintas.

Si queremos que un personaje pueda tener distintas secuencias de movimiento, es decir, que no se vean los mismos fotogramas cuando se mueva en una dirección o en otra, podemos ampliar el esquema anterior para que no sea un único array de imágenes.

La primera aproximación podría ser pensar en un array de dos dimensiones, de modo que el primer índice sirva para saber qué secuencia estamos utilizando y el segundo índice sea para el fotograma actual dentro de esa secuencia:

protected Imagen[,] secuencia;

Pero esto tiene la limitación de que todas las secuencias tendrían que tener la misma cantidad de fotogramas. Una alternativa más versátil es utilizar un "array de arrays", para que las secuencias puedan ser de distinta longitud:

protected Imagen[][] secuencia;

Además, ahora nos interesará saber en qué dirección se mueve el personaje, para saber cuál debe ser la siguiente imagen a mostrar:

protected byte direccion; 

Para nombrar las direcciones, sería preferible usar "constantes" en vez de números, que ayuden a que el fuente sea más legible:

protected byte cantidadDirecciones = 4;
public const byte ABAJO = 0;
public const byte ARRIBA = 1;
public const byte DERECHA = 2;
public const byte IZQUIERDA = 3;

De modo que en el constructor reservaríamos espacio para ese array:

secuencia = new Imagen[cantidadDirecciones][];
 

Y "CargarSecuencia" debería tener en cuenta la dirección a la que corresponde esa serie de imágenes:

public void CargarSecuencia(byte direcc, string[] nombres)
{
  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]);
} 

En la mayoría de métodos no hay apenas cambios. Basta poner "secuencia[direccion]" donde antes ponía "secuencia". Por ejemplo, en SiguienteFotograma se comprobaría la longitud de la secuencia actual haciendo:

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

Y nos hará falta un método "CambiarDirección" que pase a tomar las imágenes de una secuencia distinta (y que volver a comenzar desde el fotograma 0, para evitar problemas si una secuencia es más larga que otra):

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

Un ejemplo de uso, desde el constructor de la clase Personaje, podría ser:

public Personaje()
    : base(32, 23)
{
    x = 400;
    y = 300;
    visible = true;
    incrX = 10;
    incrY = 10;
    CargarSecuencia(DERECHA,new string[] { "personajed1.png", "personajed2.png" });
    CargarSecuencia(IZQUIERDA, new string[] { "personajei1.png", "personajei2.png" });
    CambiarDireccion(DERECHA);
}

Y cambiaríamos de dirección cuando fuera necesario. Por ejemplo, al pulsar la tecla Izquierda podría ocurrir lo siguiente:

public void MoverIquierda()
{
    CambiarDireccion(IZQUIERDA);
    SiguienteFotograma();
    x -= incrX;
}

Ejercicio propuesto: Aplica estos cambios al juego, para que el personaje realmente intercambie entre dos fotogramas en cada sentido.