viernes, 27 de marzo de 2009

NSMB.cpp

Hoy vamos a ver la clase NSMB.cpp que, al fin y al cabo, es lo único programado del juego hasta la fecha. El resto es una especie de librería que con el paso del tiempo podría servir para programar todo tipo de juegos para la Nintendo DS.

Lo primero, si vemos el código, es que apenas hay nada de PALib en el código. Sólo está el include y un par de constantes. Las clases han conseguido encapsular todo el código PALib.

Veamos el código del programa:


NSMB::NSMB() {
gameManager = new GameManager();
gameManager->SetKeypadManager(this);
topScreen = gameManager->GetTopScreenManager();
koopa = topScreen->CreateSprite(BACKGROUND_THREE, KOOPA, 16, 0, 1);
koopa->SetAnim(0, 15, 15);

tileSet = topScreen->CreateTileSet(BACKGROUND_TWO, PLATAFORMAS);
topScreen->PrintMap(MAPA_PLATAFORMAS, tileSet, x, y);
}


Parece poco código, veamos lo que hace:

gameManager = new GameManager();: Es la clase que crea el motor del juego. Podemos decir que engloba el HelloWorld de PaLib, es decir los init y el bucle principal.

gameManager->SetKeypadManager(this);: En esta línea le estamos diciendo que clase va a recibir la información de entrada del juego (el teclado y el sylus). 'this' significa que será la propia clase NSMB la que los recibirá.
Esto es una aproximación a lo que se suele llamar programación orientada a eventos. Es decir, cuando el usuario pulse un botón de la consola, NSMB recibirá una llamada a una de las funciones que tiene que implementar. Si, por ejemplo, se pulsa el botón de A se lanzará la función NewpressA.
Sería algo parecido a los callback, pero más orientado a objetos.

topScreen = gameManager->GetTopScreenManager();: Esto es una forma de tener una variable que apunte a la pantalla superior y no tener que ir todo el rato arrastrándo gameManager->GetTopScreenManager().

topScreen->CreateSprite(BACKGROUND_THREE, KOOPA, 16, 0, 1);: Ya tenemos un sprite hecho. Más fácil imposible. Los parámetros último son x, y y si lo queremos girar horizontalmente (1 = si).

koopa->SetAnim(0, 15, 15);: Y ahora lo animamos, entre los frames 0 a 15 y la velocidad es de 15.

tileSet = topScreen->CreateTileSet(BACKGROUND_TWO, PLATAFORMAS);: Creamos los tileset (serían los ladrillos de nuestro juego) para los fondos.

topScreen->PrintMap(MAPA_PLATAFORMAS, tileSet, x, y);: Y dibujamos el fondo de la pantalla superior.

Ya está...........

No parece muy complicado. Si no se tiene mucha experiencia en la programación con PALib puede resultar rara la definición de KOOPA. Pues nada, con echar un ojo a la entrada que se hizo en su día explicando los Sprites creo que será suficiente.

Por ahora estamos trabajando con Koopa como personaje. En cuanto saque tiempo prepararé los sprites de Mario.

El resto del código es:

void NSMB::Run() {
    gameManager->Run();
}
Se podía haber puesto en el constructor (NSMB::NSMB()) pero aquí parece que queda mejor.


bool NSMB::HeldLeft() {
if (movimiento != MOVIMIENTO_IZQUIERDA) {
koopa->Hflip(0);
movimiento = MOVIMIENTO_IZQUIERDA;
koopa->StartAnim();
} else {
koopa->RestartAnim();
}
velocidad--;
if (velocidad == 0){
velocidad = MOVIMIENTO_VELOCIDAD;
x--;
}
return 1;
}


Cuando el jugador pulse en el botón de flecha izquierda se ejecutará este código, que ahora mismo únicamente, anima a nuestra tortuga. Usa la variable 'movimiento' para hacerlo una animación más fluida, y girar a nuestro héroe cuando sea necesario. Falta el tema de las colisiones.
Con más detalle: si la tortuga estaba con otra orientación (if (movimiento != MOVIMIENTO_IZQUIERDA)) no hace falta girarlo (Hflip(0) = lo desgiramos - el sprite original mira a la izquierda) y empezamos la animación. Si ya estábamos mirando a la izquierda, únicamente, continuamos con la animación (RestartAnim). El resto del código es para ir poco a poco (lo intentaremos mejorar llamando a una función, que también la llamará HeldRight, que será la encargada de mover a nuestro héroe y mirar las colisiones).


bool NSMB::HeldRight() {
if (movimiento != MOVIMIENTO_DERECHA) {
koopa->Hflip(1);
movimiento = MOVIMIENTO_DERECHA;
koopa->StartAnim();
} else {
koopa->RestartAnim();
}
velocidad--;
if (velocidad == 0){
velocidad = MOVIMIENTO_VELOCIDAD;
x++;
}
return 1;
}

Igual que el anterior pero para ir a la derecha.


bool NSMB::NoKey() {
koopa->PauseAnim();
return 1;
}

Si no se ha pulsado ninguna tecla se ejecutará esta función. Nosotros la usaremos para parar la animación de nuestro héroe.


bool NSMB::BeforeVBL() {
topScreen->PrintMap(MAPA_PLATAFORMAS, tileSet, x, y);
return 1;
}

Esto se ejecutará siempre, una vez por cada vuelta del bucle, después de tratar el teclado (incluida la función de que no se ha pulsado ninguna tecla).

Y esto es todo, por ahora. La primera versión de GameManager ha sido publicada, esperemos que no sea la última.

Y ¿cómo usarlo? Es decir, ¿cómo llamar a NSMB?

Vemos el código de main.cpp:


#include "NSMB.h"

int main(int argc, char ** argv) {
NSMB *nsmb = new NSMB();
nsmb->Run();
return 0;
}

Uhmmm, no sé que se puede explicar. Se crea un objeto de tipo NSMB y ejecutamos un 'run'.

Nos vemos en los comentarios.

Saludos

1 comentario:

David Martínez Martínez dijo...

Hola Iñigo, ¡qué raro yo por aquí!

Dos cositas, primero que intentes comentar algo más el código, porque hasta que has hecho este tutorial, ¡no me enteraba de nada!

Luego quería comentarte un par de cosas. He visto un par de puntos, que tenemos que sabernos las cosas porque sí, cuando con una constante sería más sencillo y más entendible.

Las líneas que he visto son las siguientes:

koopa = topScreen->CreateSprite(BACKGROUND_THREE, KOOPA, 16, 0, 1);

- 16 y 0 son X e Y, vale, pero el 1 último, si quieres girado o no el Koopa... ¿Por qué no le pones mejor un SPRITE_GIRADO? En inglés, claro. Más cosas.

koopa->SetAnim(0, 15, 15);

- Lo lei hace 20 segundos, y tuve que volver a leer tu explicación porque ya no me acordaba de qué era. A esto le pondría KOOPA_ANDANDO_PRIMER_FRAME, KOOPA_ANDANDO_ULTIMO_FRAME y KOOPA_ANDANDO_VELOCIDAD. Por último, en los a la derecha y a la izquierda.

koopa->Hflip(0);
koopa->Hflip(1);

- Estos 0 y 1, los cambiaría por SPRITE_NO_GIRADO y SPRITE_GIRADO.

Se que estás malamente de tiempo siempre, así que si quieres se lo añado todo esto en un momento.

¡Saludos! ¿Mañana es viernes de nuevo? ¿No? Jo...

PD: se me olvidó decir, que tienes mi permiso permisivo permisorio para poner la super aplicación de super sonidos que te pasé :P