viernes, 19 de junio de 2009

Mejoramos el movimiento

Todas estas semanas atrás hemos estado programando el juego utilizando las funcionalidades de los Tiles que nos brinda PALib. Esto está muy bien para juegos tipo Tetris, de tablero, etc. Pero para el New Super Mario Bros, o para los Pokemon no es totalmente válido.

El programar con tiles permite dibujar la pantalla con 'azulejos' de 8x8 pixeles, por lo que el movimiento del fondo (necesario en este tipo de juegos) ha de ser de 8 en 8 pixeles y eso no puede ser. Necesitamos unas transiciones más suaves.

PALib permite crear tiles y mover el fondo como de si una imagen se tratara. Así que hemos realizado los siguientes cambios en nuestra librería y en el editor de mapas.

Con respecto a la nueva librería hemos creado nuevas funciones para tratar los fondos. Estas funciones estarán en ScreenManager:


/**
* Asigna una imagen de fondo
*
* @param background Cada pantalla de la consola permite cuatro niveles de
* fondos. Los valores posibles son: BACKGROUND_ZERO, BACKGROUND_ONE,
* BACKGROUND_TWO, BACKGROUND_THREE (de mayor a menor prioridad)
*/
void SetBackground(unsigned int background, int *info, void * pal, const unsigned char *tiles, u32 tiles_size, const unsigned short *mapa);

/**
* Devuelve la coordenada X única a todos los fondos.
*/
int GetBackgroundsX();

/**
* Devuelve la coordenada Y única a todos los fondos.
*/
int GetBackgroundsY();

/**
* Asigna la coordenada X única a todos los fondos.
* Se utiliza para mover todos los fondos a la vez
*
* @param y coordenada x
*/
void SetBackgroundsX(int x);

/**
* Asigna la coordenada Y única a todos los fondos.
* Se utiliza para mover todos los fondos a la vez
*
* @param y coordenada Y
*/
void SetBackgroundsY(int y);

/**
* Asigna las coordenadas X, Y única a todos los fondos.
* Se utiliza para mover todos los fondos a la vez
*
* @param y coordenada x
* @param y coordenada Y
*/
void SetBackgroundsXY(int x, int y);

/**
* Desplaza a la izquierda todos los fondos una cantidad dada
* Se utiliza para mover todos los fondos a la vez
*
* @param offset desplazamiento
* @return la nueva coordenada x
*/
int MoveBackgroundsLeft(int offset);

/**
* Desplaza a la derecha todos los fondos una cantidad dada
* Se utiliza para mover todos los fondos a la vez
*
* @param offset desplazamiento
* @return la nueva coordenada x
*/
int MoveBackgroundsRight(int offset);

/**
* Desplaza arriba todos los fondos una cantidad dada
* Se utiliza para mover todos los fondos a la vez
*
* @param offset desplazamiento
* @return la nueva coordenada y
*/
int MoveBackgroundsUp(int offset);

/**
* Desplaza abajo todos los fondos una cantidad dada
* Se utiliza para mover todos los fondos a la vez
*
* @param offset desplazamiento
* @return la nueva coordenada y
*/
int MoveBackgroundsBottom(int offset);


De esta forma podemos asignar una serie de imágenes a los distintos fondos y moverlos sin problema los pixeles que se desean. En nuestro caso los fondos se moverán de izquierda a derecha.

Las funciones utilizadas hasta hoy, CreateTileSet, y la clase TileSet se dejarán para los proyectos que lo necesiten.

En cuanto al programa de edición de mapas se han cambiado los ficheros de salida. Ahora genera un png con el dibujo que se ha editado. Este dibujo debe pasar por PAGfx para generar los ficheros de salida. A continuación publicamos las dos imágenes de salida del programa de edición:


Fondo cero


Fondo uno

El código en NSMB.cpp quedará así:


topScreen->SetBackground(BACKGROUND_ZERO, FONDO_CERO);
topScreen->SetBackground(BACKGROUND_ONE, FONDO_UNO);
topScreen->SetBackground(BACKGROUND_THREE, FONDO_TRES);
topScreen->SetCollisionMap8x8((void *)newImage_0_Map, newImage_0_Info[1] / 8, newImage_0_Info[2] / 8);


Esta semana no voy a publicar código. Son demasiados cambios de un solo golpe y no puedo mantener bien las versiones. Además de que el código estará lleno de errores.

Ahora mi objetivo es dejar el salto fino y coger las monedas.

Espero tener para la semana que viene cosas nuevas que ofrecer, aunque el verano me va a quitar tiempo.

Saludos

viernes, 12 de junio de 2009

Los sonidos

A partir del post de como programar los sonidos en la Nintendo DS, con el código de David que publicamos hace ya un tiempo, vamos a implementar los sonidos de nuestro juego.

Como ya explicamos en aquel post, las librerías PALib leen los ficheros de audio en formato raw.

Para pasar de mp3 a raw lo he hecho con 'Switch Sound File Converter'. Para editar los ficheros hemos usado Audacity.

Los ficheros de sonido se dejan en la carpeta data de SuperMarioDS.

La Instrucción PA_InitSound la hemos puesto en el constructor de GameManager.cpp. Ahora en la instalación que tengo de PALib ha empezado a dar problemas y he tenido que cambiar el código, que ha quedad de esta forma:


GameManager::GameManager() {
PA_Init();
PA_InitVBL();

//PA_InitSound();
AS_Init(AS_MODE_SURROUND | AS_MODE_16CH );
AS_SetDefaultSettings(AS_PCM_8BIT, 11025, AS_SURROUND);


El código a cambiar en NSMB.cpp es el siguiente:


#include
#include "salto.h"

....

bool NSMB::HeldUp() {
if (!volando) { //Si no estamos volando podremos saltar
//PA_PlaySimpleSound(0, salto);
PA_PlaySimpleSound(salto);
tiempoSalto = TIEMPO_SALTO;
volando = true;
fuerzaSalto = FUERZA_SALTO_INICIAL;
}
return 1;
}

El error que aparecía al compilar era
'PA_InitSound' was not declared in this scope
, y ahí me he quedado, he cambiado PA_InitSound y PA_PlaySimpleSound(0, salto) por las otras instrucciones y ya funciona (¿?¿?¿?¿?).

Ahora habrá que ir poniendo sonidos a las distintas acciones...

Saludos

viernes, 5 de junio de 2009

La gravedad y el salto

Bueno, aquí no vamos a explicar lo que es la gravedad, pero si que es necesario ponerla en nuestro juego.

Vamos a programar la gravedad en nuestro juego.

El tema está en que al saltar, Mario no sube y después baja, no....si no que al saltar Mario sube, el bajar es cosa de la gravedad, no del salto. Por lo que habrá que programar primero el tema de la gravedad.

Lo primero será hacer un mapa con una zona elevada y poner ahí a nuestro héroe. Y que al salir de dicha zona la gravedad le haga caer y que lo haga hasta que ocurra una colisión.

he creado varias variables, una para saber que estamos cayendo, ya que en esos momentos no podemos saltar. Sólo se salta desde el suelo.
Otra es para el tema de la fuerza al caer, es decir, cada vez se cae más deprisa y el retardo del salto para que no caiga demasiado deprisa.


bool NSMB::BeforeVBL() {
if (tiempoSalto-- < 0) {
tiempoSalto = MOVIMIENTO_VELOCIDAD;
int y = koopa->GetY();
koopa->SetY(y + fuerzaSalto);
if (topScreen->IsCollision(koopa, mundo_plataformas_cero->GetX(), mundo_plataformas_cero->GetY())) {
koopa->SetY(y);
fuerzaSalto = 1;//inicializar
volando = false;
} else {
if (fuerzaSalto < MAXIMA_FUERZA_CAIDA) fuerzaSalto++;
volando = true;
}
}
return 1;
}


El código lo hemos colocado en la función BeforeVBL que se ejecuta en cada vuelta del bucle y antes del refresco de la pantalla. Esto se ha hecho así porque la gravedad actua continuamente.

Lo que realmente hace nuestro código es coger la coordenada 'Y' de nuestro héroe y sumarle la fuerza. La hemos llamado fuerzaSalto porque sirve igualmente para saltar que para caer, ya hemos dicho que saltar y caer es lo mismo.

Una vez sumados los valores vemos si hay colisión, si no es el caso aumentamos la fuerza, cada vez caemos más fuerte (hasta un límite 'MAXIMA_FUERZA_CAIDA'). Este algoritmo se ejecutará hasta llegar a un suelo.

Y ahora que pasa si fuerzaSalto es negativo. Pues que tenemos a nuestro héroe saltando. Por lo que necesitamos este código para comenzar a saltar:


bool NSMB::HeldUp() {
if (!volando) { //Si no estamos volando podremos saltar
tiempoSalto = TIEMPO_SALTO;
volando = true;
fuerzaSalto = FUERZA_SALTO_INICIAL;
}
return 1;
}


Y ya está, programando la gravedad nos ha salido gratis el salto. Así da gusto!

El juego tiene este aspecto ahora mismo:


Aún así queda un efecto feo al aterrizar. Ya lo trabajaremos más adelate.

Ahora sólo queda coger las monedas, meter los sonidos, los efectos de fondo, más plataformas,... esto no acaba nunca.

Saludos, nos vemos en los comentarios.