Los sprites de fondo o 'background sprite' se moverán con el fondo, por lo que habrá que hacer también funciones que muevan el fondo.
Se ha implementado casi todo dentro de ScreenManager. La función para crear un Sprite de fondo es 'CreateBackgroundSprite'. Tiene los mismos parámetros que 'CreateSprite', lo único que el Sprite queda en una lista de sprites de fondo. También se ha preparado 'CloneBackgroundSprite' que crea un sprite idéntico ahorrando espacio en memoria.
Antes de ver las funciones, conviene resaltar que se ha usado por primera vez una clase de C++ denominada Vector. Esta clase permite tener una especie de 'array' que se puede ir cargando de forma dinámica. En este caso se ha usado de esta forma:
//ScreenManager.h
std::vector*m_backgroundSprites;
Esta es la forma de crear un vector de clases de Sprite. Más delante se ve como recorrerlo, en 'MoveRightBackgroundSprites' y en 'MoveLeftBackgroundSprites'.
Las funciones nuevas son las siguientes:
Sprite *ScreenManager::CreateBackgroundSprite(unsigned int background, unsigned int shape, unsigned int sizes, void *palette, void *sprite, int x, int y) {
return CreateBackgroundSprite(background, shape, sizes, palette, sprite, x, y, 0);
}
Sprite *ScreenManager::CreateBackgroundSprite(unsigned int background, unsigned int shape, unsigned int sizes, void *palette, void *sprite, int x, int y, int hflip) {
Sprite *newSprite = new Sprite(m_screen, background, shape, sizes, palette, sprite, x, y, hflip);
if (!m_backgroundSprites) m_backgroundSprites = new std::vector();
m_backgroundSprites->push_back(newSprite);
return newSprite;
}
Sprite *ScreenManager::CloneBackgroundSprite(Sprite *sprite) {
return CloneBackgroundSprite(sprite, sprite->GetX(), sprite->GetY());
}
Sprite *ScreenManager::CloneBackgroundSprite(Sprite *sprite, int x, int y) {
Sprite *clone = sprite->Clone(x, y);
m_backgroundSprites->push_back(clone);
return clone;
}
Y, finalmente, las funciones encargadas de mover todos los sprites de fondo de un golpe son:
void ScreenManager::MoveRightBackgroundSprites(int offset) {
unsigned int i;
for(i = 0; i < m_backgroundSprites->size(); i++) {
Sprite *sprite = (Sprite *)m_backgroundSprites->at(i);
sprite->MoveRight(offset);
}
}
void ScreenManager::MoveLeftBackgroundSprites(int offset) {
unsigned int i;
for(i = 0; i < m_backgroundSprites->size(); i++) {
Sprite *sprite = (Sprite *)m_backgroundSprites->at(i);
sprite->MoveLeft(offset);
}
}
En este punto surgió un problema y es que cuando la x se hacía negativa o mayor de 256 aparecían los sprites por el otro lado. Este tema se ha corregido creando una función nueva que permite ocultar los sprites:
void Sprite::SetVisible(int visible) {
if (!visible) {
if (PA_GetSpriteMode(m_screen, m_index_sprite) != 1) {
PA_SetSpriteMode(m_screen, m_index_sprite, 1);
PA_EnableSpecialFx(m_screen, SFX_ALPHA, 0, SFX_BG0 | SFX_BG1 | SFX_BG2 | SFX_BG3 | SFX_BD);
PA_SetSFXAlpha(m_screen, 0, 0);
}
} else if (PA_GetSpriteMode(m_screen, m_index_sprite) != 0) {
PA_SetSpriteMode(m_screen, m_index_sprite, 0);
}
}
Esta función pone el sprite totalmente transparente (Esto no es cierto del todo, Existen dos modos y en uno de ellos serán todos los sprites transparentes). Se puede utilizar desde nuestros programas y además lo utilizan las funciones SetX, SetY y SetXY si las coordenadas están fuera de la pantalla:
void Sprite::SetX(int x) {
m_x = x;
PA_SetSpriteX(m_screen, m_index_sprite, m_x);
if (m_x < 0 || m_x > 256) SetVisible(0);
else SetVisible(1);
}
void Sprite::SetY(int y) {
m_y = y;
PA_SetSpriteY(m_screen, m_index_sprite, m_y);
if (m_y < 0 || m_y > 192) SetVisible(0);
else SetVisible(1);
}
void Sprite::SetXY(int x, int y) {
m_x = x;
m_y = y;
PA_SetSpriteXY(m_screen, m_index_sprite, m_x, m_y);
if (m_x < 0 || m_x > 256) SetVisible(0);
else SetVisible(1);
}
Las monedas las hemos creado en NSMB.cpp de la siguiente manera:
Sprite *coin = topScreen->CreateBackgroundSprite(BACKGROUND_TWO, COIN, 192, 80);
coin->SetAnim(0, 3, 4);
coin->StartAnim();
topScreen->CloneBackgroundSprite(coin, 224, 88);
topScreen->CloneBackgroundSprite(coin, 248, 96);
topScreen->CloneBackgroundSprite(coin, 548, 104);
La primera línea crea una moneda (un sprite de fondo).
La segunda define los frames para la animación.
La tercera pone a girar la moneda.
Y las otras tres crean tres monedas más.
Este es el aspecto del juego en estos momentos:
¡¡Ahora solo nos falta saltar para coger esas monedas!!
Tenemos que hacer el tema de la gravedad y lo de saltar.
El código correspondiente a esta última entrega lo podéis descargar desde aquí.
Nos vemos en los comentarios.
Saludos