viernes, 24 de abril de 2009

Creación de mapas para el Juego

Después del paréntesis de la semana santa volvemos al proyecto en que estamos metidos, hacer el New Super Mario Bros para la Nintendo DS.

En esta entrada vamos a presentar un programa que sirve para hacer los mapas del juego. Es un poco cutre, pero el tiempo no da para más. Aquí os dejo un pantallazo del programa.



Su uso es muy sencillo:
  • Primero, se debe cargar el tileset con el que queremos dibujar el mapa (fichero/abrir tileset...),

  • Segundo, si queremos modificar un mapa ya hecho lo cargamos con la opción fichero/abrir mapa 16,

  • Tercero, seleccionamos el tile que queremos dibujar en la parte superior,

  • Cuarto, vamos 'clickando' por la pantalla para ir poniendo los cuadraditos y

  • Finalmente guardamos el mapa con la opción 'guardar 16'.

Si os fijáis, al cargar se carga con la opción de cargar mapa 16. Esto es que el programa trabaja con tiles de 16x16 pixeles, así que el mapa a cargar sera de 16.

La opción de 'grabar 16' graba el mapa con tiles de 16x16 pixeles (salida_16.txt).
La opción de 'grabar 8' graba con tiles de 8x8 pixeles (salida_8.txt).

El proyecto java lo encontrareis aquí.

No he explicado nada de java, no es tema de este blog, pero si alguien quiere saber algo, que lo diga. Por otra parte, ¡¡¡he comentado bastante el código!!!


Para ver el mapa dentro de nuestro juego, únicamente, tendremos que copiar el contenido del fichero a NSMB.cpp. Es el array denominado mapa8.

El último código lo encontraréis aquí.

Hay un cambio con respecto a la anterior versión y es que antes dibujábamos casillas de 16x16 y ahora de 8x8. Dejaremos la anterior funcionalidad en las librerías por si a algún otro proyecto le pueda interesar.

Ahora ya podemos ir a por el tema de las colisiones y, después, a por el tema de la gravedad.

Ya siento no poder avanzar más pero de donde no hay no se puede sacar, y no tengo nada de tiempo.

Nos vemos en los comentarios, saludos

viernes, 10 de abril de 2009

Doxygen :: Comentar el código

He estado hablando con David y estamos viendo la posibilidad de comentar el código de una forma más extensa que hasta ahora. O mejor dicho, hasta ahora no se comentaba casi nada en las fuentes.

Hemos estado mirando las distintas herramientas que hay en Internet para documentar un proyecto y parece que Doxygen es la que nos parece más potente y fácil de usar. Posee una opción para utilizar los comentarios JavaDoc por lo que el que conozca esta forma de comentar ya lo tiene todo hecho, y ese es más o menos mi caso.

El resultado es algo parecido a esto:


¡Ahora sólo queda comentar el código!

Saludos

viernes, 3 de abril de 2009

Sonidos en la Nintendo DS

Esta semana vamos a tocar un tema que hasta el momento no habíamos hecho nada, el sonido.

Para ilustrar el tema tenemos código que ha mandado David. David es un crack de la programación de la nintendo DS, además de ser quien aporta más comentarios al Blog.

El código es el siguiente:


#include &lh;PA9.h>

#include "intro.h"
#include "uno.h" // Include the sound (found in the data folder in .raw format)
#include "dos.h"
#include "tres.h"
#include "cuatro.h"

#include "constantes.h"

int main(void)
{
PA_Init(); // Initializes PA_Lib
PA_InitVBL(); // Initializes a standard VBL

PA_InitSound();

PA_InitText(SCREEN_TOP, BACKGROUND_ZERO); // Initialise the text system on the top screen
PA_InitText(SCREEN_BOTTOM, BACKGROUND_ZERO); // Initialise the text system on the top screen

PA_OutputSimpleText(SCREEN_TOP, 0, 1, "Prueba raw,pulsa Arriba para escuchar");
PA_OutputSimpleText(SCREEN_TOP, 0, 3, "--------------------------------");

PA_WaitForVBL();

s32 sonido = 1;
while (1)
{
if (Pad.Newpress.Up)
{
switch (sonido)
{
case 1:
PA_PlaySimpleSound(0, uno);
sonido ++;
break;
case 2:
PA_PlaySimpleSound(0, dos);
sonido ++;
break;
case 3:
PA_PlaySimpleSound(0, tres);
sonido ++;
break;
case 4:
PA_PlaySimpleSound(0, cuatro);
sonido = 1;
break;
default:
PA_PlaySimpleSound(0, intro);
break;
}
}

PA_OutputText(SCREEN_BOTTOM, 1, 3, "sonido %d ", sonido);

PA_WaitForVBL();
}

return 0;
}


Para realizar este proyecto se han de seguir los siguientes pasos:

1. Copiar los ficheros de sonido .raw a la carpeta data
2. realizar los includes de los sonidos
3. constants.h se encuentra en la carpeta 'include'. Como ya nos enseñó David, en esa carpeta puedes dejar cosas comunes y el compilador va a buscarlas ahí por defecto. constants.h hace las veces de devnintendods.h en los proyectos mios.
4. PA_InitSound(); Esta función de PALib no la habíamos usado nunca hasta ahora. Inicializa el sistema de sonido de la consola.
5.PA_PlaySimpleSound(0, uno); Hace sonar el fichero de sonido uno, por el canal 0. Tenemos hasta 8 canales disponibles, lo que permite tener varios sonidos sonando a la vez. En este ejemplo sólo falta una música de fondo, como si fuera la melodía de un juego.

El programa mantiene una variable, sonido, que va pasando de 1 a 4 para que suenen los distintos ficheros.

Un código sencillo y elegante.

El proyecto lo dejo donde siempre.

Saludos y gracias David.

P.D. En estos momentos estoy sin tiempo, y con la proximidad de semana santa quizás no consiga llegar a mi cita semanal...

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

viernes, 20 de marzo de 2009

Nueva versión del Tetris

Hacemos un paréntesis en la programación del NSMB y vamos a presentar la última versión del Tetris.

Se ha creado un menú en la pantalla táctil, por lo que usaremos el stylus por primera vez en este blog. La imagen es la siguiente:



Posibilita la selección de tres tipos de juegos.

PALib controla cuando se pulsa en la pantalla táctil y devuelve las coordenadas (x, y) donde se ha pulsado.

if (Stylus.Held) {
    tipo_juego = obtener_tipo_juego(Stylus.X, Stylus.Y);

El Stylus.Held indica que se está pulsando en la pantalla y las coordenadas quedan en Stylus.X y en Stylus.Y. Ahora para saber si se ha pulsado un botón u otro se ha creado esta función:


u8 obtener_tipo_juego(s32 xStylus, s32 yStylus) {
if (pulsado_boton_con_stylus(xStylus, yStylus, 60, 37, 205, 79)) {
return JUEGO_MARATON;
} else if (pulsado_boton_con_stylus(xStylus, yStylus, 74, 83, 224, 125)) {
return JUEGO_EXPERTO;
} else if (pulsado_boton_con_stylus(xStylus, yStylus, 61, 133, 226, 170)) {
return JUEGO_SUPER_BLOQUES;
} else {
return 0;
}
}

bool pulsado_boton_con_stylus(s32 xStylus, s32 yStylus, s32 x1, s32 y1, s32 x2, s32 y2) {
return (xStylus > x1 && xStylus <> y1 && yStylus < y2);
}


Esta última función es la que uso en todos los proyectos. Sirve para saber si un punto (x, y) esta dentro de un rectángulo (x1, y1) - (x2, y2).
Los rectángulos los sacamos de la imagen, y aunque los botones estén un poco torcidos más o menos he trazado unos rectángulos y son esas coordenadas las que he usado:


El modo superbloques muestra fichas de distintas formas, posibilidad que nos da el haber creado las fichas como matrices de 4x4. Y tanto este modo como el experto van incrementando las velocidad a medida que se consigue aumentar la puntuación.

Veamos la función actualizar_puntuacion:


if (tipo_juego == JUEGO_EXPERTO || tipo_juego == JUEGO_SUPER_BLOQUES) {
if (nivel != puntos / 100) {
nivel = puntos / 100; velocidad -= nivel;
}
}

Cada cien puntos aumentamos la velocidad (o disminuimos el tiempo de espera).

Os dejo todo el código en el lugar habitual para que echéis un vistazo. Como siempre nos vemos en los comentarios.

Saludos

sábado, 14 de marzo de 2009

Clases básicas: TileSet

TileSet es una clase que nos permite trabajar con los tiles. Los tiles son esas pequeñas imágenes, de 8x8 pixeles, que sirven para dibujar en las pantallas de la nintendo DS.

Para explicarlo mejor, las pantalla de la DS tienen 256x192 pixeles. Dividido entre 8 nos da 32x24 casillas. Es decir, cada pantalla tienen 32x24 casillas, y en cada casilla se puede dibujar un tile.

PaLib nos permite trabajar con estos tiles de una forma muy sencilla, pero la clase TileSet nos permite aún una mayor abstracción. Sólo contiene, por ahora, tres funciones.

El constructor de la clase nos permite cargar en memoria la imagen con todos los tiles de nuestro juego.

La función SetTile16x16 nos permitirá dibujar en una ubicación dada un tile.

La función GetTile nos permite ver que tile hay en una ubicación dada. Esto nos servirá para el tema de colisiones.

Esta es la imagen que usamos, en este momento, en el proyecto:



Si os fijáis bien el primer rectángulo es rosa, eso significa que el 0 será un recuadro transparente.

Un ejemplo de uso:

#define PLATAFORMAS (void *)plataformas_Pal, (void *)plataformas_Tiles, SIZEOF_16BIT(plataformas_Tiles), (void *)plataformas_Map

#define COLUMNAS_16x16_PANTALLA 16
#define COLUMNAS_16x16_MAPA 48
#define FILAS_16x16 12
#define MAPA_PLATAFORMAS (void *)mapa, COLUMNAS_16x16_PANTALLA, FILAS_16x16, COLUMNAS_16x16_MAPA

int mapa[COLUMNAS_16x16_MAPA * FILAS_16x16] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 5, 2, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 12, 8, 11, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 8, 13, 12, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 12, 8, 11, 14, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 11, 12, 13, 14, 0, 0, 0, 0, 0, 0, 7, 9, 8, 10, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 12, 13, 8, 14, 0, 0, 0, 0, 0, 0, 7, 12, 10, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 13, 9, 10, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 12, 8, 12, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 8, 12, 13, 15, 4, 3, 3, 4, 2, 3, 4, 2, 5, 4, 4, 3, 5, 2, 3, 5, 4, 3, 3, 4, 2, 3, 4, 2, 5, 4, 2, 3, 5, 2, 3, 5, 4, 3, 3, 4, 2, 3, 4, 2, 5, 4, 6,
7, 11, 13, 12, 8, 10, 9, 11, 12, 11, 8, 12, 12, 13, 12, 8, 10, 9, 11, 12, 11, 8, 12, 9, 11, 12, 11, 8, 12, 9, 13, 12, 8, 10, 9, 11, 8, 12, 12, 13, 12, 10, 12, 11, 8, 12, 9, 14
};

TileSet *newTileSet = new TileSet(SCREEN_TOP, BACKGROUND_TWO, PLATAFORMAS);
newTileSet->SetTile16x16(MAPA_PLATAFORMAS, 10, 10);

Es muy sencillo. Me gusta usar los defines, porque el código queda mucho más claro, desaparecen * y (void *) y queda todo más cómodo.

Saludos

viernes, 6 de marzo de 2009

Clases básicas - Sprite

En nuestro NSMB vamos a empezar a definir una serie de clases que se encargarán, cada una de ellas, de un apartado propio del juego.

NOTA:
Aquí vamos a explicar como se han construido estas clases y como funcionan. Si no te interesa o tu nivel de programación aún no ha llegado a esto, podrías saltarte la explicación y únicamente aprender a usarlas.



Incluso podemos diferenciar la lógica del juego del apartado gráfico (las propias librerías PALib) por lo que sería más fácil pasar el juego a otro sistema. Vamos a presentar en este post la clase Sprite (vimos una primera versión en el post anterior).

Esta clase será la encargada de cargar y mostrar los personajes o los objetos con los que interactuaremos en nuestros juegos. Podremos animar los Sprites, rotarlos, moverlos, etc.

En C++ las clases se componen de dos ficheros, el .h y el .cpp.
En el .h se almacena la definición de la clase, su nombre, las funciones públicas, las privadas y las variables miembro.
En el .cpp está el código, la implementación de la propia clase.

Sprite.h
#ifndef SPRITE_H
#define SPRITE_H

class Sprite {

private:
    static unsigned int index_sprites;
    static unsigned int index_sprites_pals;

protected:
    unsigned int m_index_sprite;
    unsigned int m_index_pal;
    unsigned int m_screen;
    unsigned int m_background;
    unsigned int m_size;

    unsigned int m_firstframe;
    unsigned int m_lastframe;
    unsigned int m_speed;

    int m_x;
    int m_y;

    Sprite(unsigned int screen, unsigned int background, unsigned int size, int x, int y);

public:
    Sprite(unsigned int screen, unsigned int background, unsigned int shape, unsigned int size, void *palette, void *sprite, int x, int y, int hflip = 0);
    ~Sprite();

    unsigned int GetIndexSprite();
    unsigned int GetScreen();

    Sprite *Clone();
    Sprite *Clone(int x, int y);

    void SetAnim(unsigned int firstframe, unsigned int lastframe, unsigned int speed);
    void StartAnim(unsigned int firstframe, unsigned int lastframe, unsigned int speed);
    void StartAnim();
    void StopAnim();
    void RestartAnim();
    void PauseAnim();

    void Hflip(bool hflip);

    void SetX(int x);
    void SetY(int y);
    void SetXY(int x, int y);

    int GetX();
    int GetY();

    int MoveRight(int offset);
    int MoveLeft(int offset);
    int MoveUp(int offset);
    int MoveDown(int offset);
};

#endif


Las variables miembro son las que definen el estado de un objeto. En nuestro caso son las variables que tienen como prefijo una m_ :
m_index_sprite, m_index_pal, m_screen, m_background, m_firstframe, m_lastframe, m_speed, m_x, m_y.

Las variables miembro son las que almacenan el estado, es decir son las que diferencian un objeto de otro. Veamos cada una que hace:

m_index_sprite, m_index_pal quedan ocultas a la programación. Son valores necesarios para PALib. Si os fijaís existen unas variables (index_sprites, index_sprites_pals) que son estáticas, es decir son únicas para todos los objetos, y son las encargadas de crear los índices para cada Sprite y cada Paleta). (En el primer tutorial son los valores HEROE_PALLETE y HEROE_SPRITE, gracias a la POO nos olvidamos de ellas)

Como siempre es más difícil explicarlo que verlo o hacerlo.

El resto de variables miembro nos indican a que pantalla pertenece el Sprite y dentro de cada pantalla a que fondo, m_screen y m_background.

m_firstFrame y m_lastFrame, sirven para realizar la animación. m_speed nos indica la velocidad de la misma.

m_x y m_y almacenan las coordenadas del sprite.

El resto del fichero .h son las declaraciones de las funciones. Tenemos un constructor, con el último campo puesto = 0. Esto significa que se puede no usar y por defecto es cero. Es decir al crear el sprite lo podemos rotar horizontalmente si ponemos un 1 en ese campo, si no queremos rotarlo,no ponemos nada.

El resto son una serie de funciones que su nombre ya las explica.

Ahora veamos como usarlo:


#define COIN OBJ_SIZE_16X16, (void*)coin_Pal, (void*)coin_Sprite




Sprite coin_i(BACKGROUND_THREE, COIN, 96, 32);
coin_i.StartAnim(0, 3, 5);
Sprite coin_ii = coin_i.Clone(112, 16);
Sprite coin_iii = coin_ii.Clone();
coin_iii.MoveRight(16);
Sprite coin_iv = coin_i.Clone(144, 32);


No creo que necesite más explicación, si no, nos vemos en los comentarios.


En cuanto a la librería PALib, en esta clase utilizo por primera vez la función PA_SpriteAnimPause. Esta función permite parar una animación y continuarla posteriormente. Utiliza como parámetros el fondo donde está el sprite, así como su índice (para saber cual parar) y el último parámetro es un 1 para parar la animación y 0 para reanudarla. Ejemplo de uso:

void Sprite::RestartAnim() {
    PA_SpriteAnimPause(m_screen, m_index_sprite, 0);
}

void Sprite::PauseAnim() {
    PA_SpriteAnimPause(m_screen, m_index_sprite, 1);
}


De esta forma al pulsar poco a poco el teclado, la animación se hace continua y no parece que esté andando a la pata coja.


Otra función que se utiliza por primera vez en este tutorial es la de Clonar un Sprite, PA_CloneSprite. Como parámetros se le pasa la pantalla de la DS donde está cargado el Sprite, el índice de este para saber cual clonar y, por último, el índice del nuevo Sprite. Clonar Sprites nos ahorra espacio en memoria, ya que comparten toda la información gráfica. En nuestro caso va a ser muy util para las monedas que aparecen a lo largo de todo el juego.

Saludos

PD: Voy a dejar todo el proyecto, tal y como está ahora, en la siguiente dirección: http://sites.google.com/site/devnintendods/Home/nsmb. Lo que dejo ahí es todo lo que tengo hecho hasta ahora (SuperMarioDS_0.2). Es todo el montaje que estoy haciendo. Lo iré explicando en los siguientes Post. Sólo decir que main.cpp únicamente llama a NSMB.cpp que es el que lo hace todo.

Aún así, se pueden usar las clases de forma independiente en cualquier otro proyecto.

Enlaces patrocinados