viernes, 11 de diciembre de 2009

Cogiendo las monedas

Por fin, Mario puede coger sus monedas y ya empieza esto a parecerse más al New Super Mario Bross de la Nintendo DS.

Está quedando chulo, parece algo:



Se ha tenido que cambiar alguna cosilla de las librerías, pero nada demasiado raro.

Para coger las monedas lo primero es saber donde están y cuanto abultan. Es por esto que se ha tenido que introducir las variables width y height dentro de la clase Sprite. De paso hemos aprovechado para limpiar un poco los constructores y dejarlo todo más fino.

Dentro de la clase Sprite se han modificado e introducido las siguientes funciones:

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

Sprite(unsigned int screen, unsigned int background, unsigned int shape, unsigned int size, void *palette, void *sprite, int x, int y, int width, int height, int hflip);

void SetWidth(int width);
void SetHeight(int height);
void SetWidthHeight(int width, int height);

int GetWidth();
int GetHeight();

bool InSprite(int x, int y);

Esta última función, InSprite mira que el punto x,y esté dentro del Sprite. En nuestro caso será dentro de la moneda y se ha codificado de la siguiente manera:

bool Sprite::InSprite(int x, int y) {
return (x >= m_x && x <= m_x + m_width && y >= m_y && y <= m_y + m_height);
}

No está fino del todo, pero ya lo iremos mejorando.
También hemos codificado el destructor de la clase: 

Sprite::~Sprite() {
PA_StopSpriteAnim(m_screen, m_index_sprite);
PA_DeleteSprite(m_screen, m_index_sprite);

}

De esta forma al coger la moneda destruimos el sprite. Ahora la clase ScreenManager. En las funciones para crear Sprites y sprites de fondo se ha introducido el width y el height:
Sprite *CreateSprite(unsigned int background, unsigned int shape, unsigned int sizes, void *palette, void *sprite, int x, int y, int width, int height, int hflip = 0);

Sprite *CreateBackgroundSprite(unsigned int background, unsigned int shape, unsigned int sizes, void *palette, void *sprite, int x, int y, int width, int height, int hflip = 0);
Y hemos introducido más funciones para trabajar con los Sprites de fondo:
int ScreenManager::GetBackgroundSpriteIndex(int x, int y) {
unsigned int i;
for (i = 0; i < m_backgroundSprites->size(); i++) {
Sprite *sprite = m_backgroundSprites->at(i);
if (sprite->InSprite(x, y)) return i;
}
return -1;
}

Sprite *ScreenManager::GetBackgroundSprite(unsigned int i) {
return m_backgroundSprites->at(i);
}

void ScreenManager::EraseBackgroundSprite(unsigned int i) {
Sprite *sprite = m_backgroundSprites->at(i);
delete sprite;
m_backgroundSprites->erase(m_backgroundSprites->begin() + i);
}
La primera obtiene el índice de un Sprite de fondo a partir de unas coordenadas. Devolverá el primer sprite de fondo que contenga esas coordenadas. La segunda devuelve el Sprite de fondo a partir de un índice. La tercera borra un Sprite de fondo a partir de un índice. Esta última destruye el Sprite. En cuanto a código PAlib hemos usado por primera vez, creo, la función que sirve para borrar un Sprite: PA_DeleteSprite(m_screen, m_index_sprite); Se le pasa la pantalla donde está el sprite asignado y el indice que se le asoció al crearlo (no confundir con el índice de los Sprites de fondo). Para adaptar todas estas nuevas funciones a nuestro propósito, que es coger monedas al pasar sobre ellas, he introducido las siguientes líneas al final de la función BeforeVBL de la clase NSMB.cpp:
int i = topScreen->GetBackgroundSpriteIndex(mario->GetX() + 8, mario->GetY() + 8);
if (i > -1) { //hemos pillado moneda
topScreen->EraseBackgroundSprite(i);
puntuacion_monedas++;
PA_OutputText(SCREEN_BOTTOM, 1, 1, "monedas = %d      ", puntuacion_monedas); // para debugear
}

El código lo podéis encontrar en esta dirección.

Esto es todo por ahora.

Saludos

1 comentario:

Unknown dijo...

compile tu codigo y me marca errores despues de darle el make y segui tu manual de ocmo instalarlo en ubuntu kisiera saber si lo hice bien