forked from jaildesigner-jailgames/coffee_crisis
5159 lines
154 KiB
C++
5159 lines
154 KiB
C++
#include "const.h"
|
|
#include "struct.h"
|
|
#include "gamedirector.h"
|
|
#include <iostream>
|
|
|
|
const Uint8 *keystates;
|
|
float mSin[360]; // Vector con los valores del seno para 360 grados
|
|
|
|
// Constructor
|
|
GameDirector::GameDirector(std::string path)
|
|
{
|
|
// Crea los objetos
|
|
mEventHandler = new SDL_Event();
|
|
|
|
mTexture[TEXTURE_MENU].texture = new LTexture();
|
|
mTexture[TEXTURE_FONT_WHITE].texture = new LTexture();
|
|
mTexture[TEXTURE_FONT_WHITE_X2].texture = new LTexture();
|
|
mTexture[TEXTURE_FONT_BLACK].texture = new LTexture();
|
|
mTexture[TEXTURE_FONT_BLACK_X2].texture = new LTexture();
|
|
mTexture[TEXTURE_FONT_NOKIA].texture = new LTexture();
|
|
|
|
mMenu.gameOver = new Menu();
|
|
mMenu.options = new Menu();
|
|
mMenu.pause = new Menu();
|
|
mMenu.title = new Menu();
|
|
|
|
mText.black = new Text();
|
|
mText.blackX2 = new Text();
|
|
mText.nokia = new Text();
|
|
mText.white = new Text();
|
|
mText.whiteX2 = new Text();
|
|
|
|
// Inicializa variables
|
|
setExecutablePath(path);
|
|
setFileList();
|
|
checkFileList();
|
|
|
|
// Inicializa SDL
|
|
initSDL();
|
|
|
|
// Inicializa JailAudio
|
|
initJailAudio();
|
|
|
|
// Carga recursos
|
|
loadMediaProg();
|
|
loadScoreFile();
|
|
loadConfigFile();
|
|
loadDemoFile();
|
|
|
|
// Inicializa el resto de variables
|
|
initProg();
|
|
}
|
|
|
|
GameDirector::~GameDirector()
|
|
{
|
|
quitProg();
|
|
|
|
// Destuye el manejador de eventos
|
|
delete mEventHandler;
|
|
|
|
// Libera el mando
|
|
if (mGameControllerFound)
|
|
{
|
|
SDL_JoystickClose(mGameController);
|
|
mGameController = NULL;
|
|
}
|
|
|
|
// Destruye los objetos
|
|
delete mTexture[TEXTURE_MENU].texture;
|
|
delete mTexture[TEXTURE_FONT_WHITE].texture;
|
|
delete mTexture[TEXTURE_FONT_WHITE_X2].texture;
|
|
delete mTexture[TEXTURE_FONT_BLACK].texture;
|
|
delete mTexture[TEXTURE_FONT_BLACK_X2].texture;
|
|
delete mTexture[TEXTURE_FONT_NOKIA].texture;
|
|
|
|
delete mMenu.gameOver;
|
|
delete mMenu.options;
|
|
delete mMenu.pause;
|
|
delete mMenu.title;
|
|
mMenu.active = nullptr;
|
|
|
|
delete mText.black;
|
|
delete mText.blackX2;
|
|
delete mText.nokia;
|
|
delete mText.white;
|
|
delete mText.whiteX2;
|
|
|
|
SDL_DestroyTexture(mBackbuffer);
|
|
SDL_DestroyRenderer(mRenderer);
|
|
SDL_DestroyWindow(mWindow);
|
|
mBackbuffer = nullptr;
|
|
mRenderer = nullptr;
|
|
mWindow = nullptr;
|
|
|
|
SDL_Quit();
|
|
}
|
|
|
|
// Inicia las variables necesarias para arrancar el programa
|
|
void GameDirector::initProg()
|
|
{
|
|
// Debug mode
|
|
mDebug.enabled = false;
|
|
mDebug.enemySet = 0;
|
|
mDebug.gradR = mDebug.gradG = mDebug.gradB = 0;
|
|
|
|
// Variables
|
|
mProg.quit = false;
|
|
mProg.ticks = 0;
|
|
mProg.ticksSpeed = 15;
|
|
mProg.section = PROG_SECTION_LOGO;
|
|
initSin();
|
|
initPaths();
|
|
initEnemyFormations();
|
|
initEnemyPools();
|
|
|
|
mOptions.displayCoffeeDrops = false;
|
|
|
|
mDemo.enabled = false;
|
|
mDemo.recording = false;
|
|
mDemo.counter = 0;
|
|
|
|
mMenu.keyPressed = false;
|
|
mMenu.active = mMenu.title;
|
|
|
|
// Teclado
|
|
mProg.keyboard.up = SDL_SCANCODE_UP;
|
|
mProg.keyboard.down = SDL_SCANCODE_DOWN;
|
|
mProg.keyboard.left = SDL_SCANCODE_LEFT;
|
|
mProg.keyboard.right = SDL_SCANCODE_RIGHT;
|
|
mProg.keyboard.accept = SDL_SCANCODE_RETURN;
|
|
mProg.keyboard.cancel = SDL_SCANCODE_ESCAPE;
|
|
mProg.keyboard.fire = SDL_SCANCODE_W;
|
|
mProg.keyboard.fireLeft = SDL_SCANCODE_Q;
|
|
mProg.keyboard.fireRight = SDL_SCANCODE_E;
|
|
mProg.keyboard.pause = SDL_SCANCODE_ESCAPE;
|
|
mProg.keyboard.escape = SDL_SCANCODE_ESCAPE;
|
|
|
|
// Buffer de teclado
|
|
mProg.keyboardBuffer.up = 0;
|
|
mProg.keyboardBuffer.down = 0;
|
|
mProg.keyboardBuffer.left = 0;
|
|
mProg.keyboardBuffer.right = 0;
|
|
mProg.keyboardBuffer.accept = 0;
|
|
mProg.keyboardBuffer.cancel = 0;
|
|
mProg.keyboardBuffer.fire = 0;
|
|
mProg.keyboardBuffer.fireLeft = 0;
|
|
mProg.keyboardBuffer.fireRight = 0;
|
|
mProg.keyboardBuffer.pause = 0;
|
|
mProg.keyboardBuffer.escape = 0;
|
|
|
|
// Inicializa los objetos de texto
|
|
mText.white->init(mTexture[TEXTURE_FONT_WHITE].texture, mRenderer, TEXT_FIXED, BLOCK);
|
|
mText.whiteX2->init(mTexture[TEXTURE_FONT_WHITE_X2].texture, mRenderer, TEXT_FIXED, BLOCK * 2);
|
|
mText.black->init(mTexture[TEXTURE_FONT_BLACK].texture, mRenderer, TEXT_FIXED, BLOCK);
|
|
mText.blackX2->init(mTexture[TEXTURE_FONT_BLACK_X2].texture, mRenderer, TEXT_FIXED, BLOCK * 2);
|
|
mText.nokia->init(mTexture[TEXTURE_FONT_NOKIA].texture, mRenderer, TEXT_VARIABLE, 10);
|
|
|
|
// Inicializa el objeto con el menu del titulo
|
|
mMenu.title->init("TITLE", 0, 15 * BLOCK, MENU_BACKGROUND_SOLID, mTexture[TEXTURE_MENU].texture, mRenderer, mText.white);
|
|
mMenu.title->addItem("PLAY");
|
|
mMenu.title->addItem("OPTIONS", 0, 5);
|
|
mMenu.title->addItem("QUIT");
|
|
mMenu.title->setDefaultActionWhenCancel(2);
|
|
mMenu.title->setBackgroundColor(0x30, 0x30, 0x40, 192);
|
|
mMenu.title->setSelectorColor(0xe5, 0x1c, 0x23, 255);
|
|
mMenu.title->setSelectorTextColor(0xFF, 0xF1, 0x76);
|
|
mMenu.title->centerMenu(SCREEN_CENTER_X);
|
|
mMenu.title->centerMenuElements();
|
|
|
|
// Inicializa el objeto con el menu de pausa
|
|
mMenu.pause->init("PAUSE", 0, 12 * BLOCK, MENU_BACKGROUND_SOLID, mTexture[TEXTURE_MENU].texture, mRenderer, mText.white);
|
|
mMenu.pause->addItem("CONTINUE");
|
|
mMenu.pause->addItem("EXIT TO TITLE");
|
|
mMenu.pause->setDefaultActionWhenCancel(0);
|
|
mMenu.pause->setBackgroundColor(0x29, 0x39, 0x41, 240);
|
|
mMenu.pause->setSelectorColor(0xFF, 0x7A, 0x00, 255);
|
|
mMenu.pause->setSelectorTextColor(0xFF, 0xFF, 0xFF);
|
|
mMenu.pause->centerMenu(SCREEN_CENTER_X);
|
|
mMenu.pause->centerMenuElements();
|
|
|
|
// Inicializa el objeto con el menu de la pantalla de game over
|
|
mMenu.gameOver->init("GAME OVER", 0, PLAY_AREA_CENTER_Y + BLOCK * 4, MENU_BACKGROUND_TRANSPARENT, mTexture[TEXTURE_MENU].texture, mRenderer, mText.white);
|
|
mMenu.gameOver->addItem("YES");
|
|
mMenu.gameOver->addItem("NO");
|
|
mMenu.gameOver->setDefaultActionWhenCancel(1);
|
|
mMenu.gameOver->setBackgroundColor(0, 0, 0, 255);
|
|
mMenu.gameOver->setSelectorColor(0x54, 0x6e, 0x7a, 255);
|
|
mMenu.gameOver->setSelectorColor(0x54, 0x6e, 0x7a, 0);
|
|
mMenu.gameOver->setSelectorTextColor(0xFF, 0xFF, 0xFF);
|
|
mMenu.gameOver->setSelectorTextColor(0xFF, 0xF1, 0x76);
|
|
mMenu.gameOver->setSelectorTextColor(0xFF, 0x7A, 0x00);
|
|
mMenu.gameOver->centerMenu(SCREEN_CENTER_X);
|
|
mMenu.gameOver->centerMenuElements();
|
|
|
|
// Inicializa el objeto con el menu de las opciones
|
|
mMenu.options->init("OPTIONS", 0, 15 * BLOCK, MENU_BACKGROUND_SOLID, mTexture[TEXTURE_MENU].texture, mRenderer, mText.white);
|
|
mMenu.options->addItem("FULLSCREEN");
|
|
mMenu.options->addItem("WINDOWS SIZE", 0, 5);
|
|
mMenu.options->addItem("[OK]");
|
|
mMenu.options->addItem("[CANCEL]");
|
|
mMenu.options->setDefaultActionWhenCancel(3);
|
|
mMenu.options->setBackgroundColor(0x30, 0x30, 0x40, 192);
|
|
mMenu.options->setSelectorColor(0xe5, 0x1c, 0x23, 255);
|
|
mMenu.options->setSelectorTextColor(0xFF, 0xF1, 0x76);
|
|
mMenu.options->centerMenu(SCREEN_CENTER_X);
|
|
mMenu.options->centerMenuElements();
|
|
|
|
// Actualiza los elementos del menu de opciones con los valores correspondientes
|
|
updateOptionsMenu();
|
|
}
|
|
|
|
// Carga los recursos necesarios para el programa
|
|
bool GameDirector::loadMediaProg()
|
|
{
|
|
bool success = true;
|
|
|
|
// Texturas
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_MENU].texture, mTexture[TEXTURE_MENU].file, mRenderer);
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_FONT_WHITE].texture, mTexture[TEXTURE_FONT_WHITE].file, mRenderer);
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_FONT_WHITE_X2].texture, mTexture[TEXTURE_FONT_WHITE_X2].file, mRenderer);
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_FONT_BLACK].texture, mTexture[TEXTURE_FONT_BLACK].file, mRenderer);
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_FONT_BLACK_X2].texture, mTexture[TEXTURE_FONT_BLACK_X2].file, mRenderer);
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_FONT_NOKIA].texture, mTexture[TEXTURE_FONT_NOKIA].file, mRenderer);
|
|
|
|
// Sonidos
|
|
mSound[SOUND_MENU_SELECT].sound = JA_LoadSound(mSound[SOUND_MENU_SELECT].file.c_str());
|
|
mSound[SOUND_MENU_CANCEL].sound = JA_LoadSound(mSound[SOUND_MENU_CANCEL].file.c_str());
|
|
mSound[SOUND_MENU_MOVE].sound = JA_LoadSound(mSound[SOUND_MENU_MOVE].file.c_str());
|
|
|
|
// Musicas
|
|
mMusic[MUSIC_TITLE].music = JA_LoadMusic(mMusic[MUSIC_TITLE].file.c_str());
|
|
|
|
return success;
|
|
}
|
|
|
|
// Libera las variables del programa
|
|
void GameDirector::quitProg()
|
|
{
|
|
// Guarda los ficheros
|
|
saveScoreFile();
|
|
saveConfigFile();
|
|
saveDemoFile();
|
|
|
|
// Texturas
|
|
mTexture[TEXTURE_MENU].texture->unload();
|
|
mTexture[TEXTURE_FONT_WHITE].texture->unload();
|
|
mTexture[TEXTURE_FONT_WHITE_X2].texture->unload();
|
|
mTexture[TEXTURE_FONT_BLACK].texture->unload();
|
|
mTexture[TEXTURE_FONT_BLACK_X2].texture->unload();
|
|
mTexture[TEXTURE_FONT_NOKIA].texture->unload();
|
|
|
|
// Sonidos
|
|
JA_DeleteSound(mSound[SOUND_MENU_SELECT].sound);
|
|
JA_DeleteSound(mSound[SOUND_MENU_CANCEL].sound);
|
|
JA_DeleteSound(mSound[SOUND_MENU_MOVE].sound);
|
|
|
|
// Musicas
|
|
JA_DeleteMusic(mMusic[MUSIC_TITLE].music);
|
|
}
|
|
|
|
// Inicializa JailAudio
|
|
void GameDirector::initJailAudio()
|
|
{
|
|
JA_Init(48000, AUDIO_S16, 2);
|
|
}
|
|
|
|
// Arranca SDL y crea la ventana
|
|
bool GameDirector::initSDL()
|
|
{
|
|
// Indicador de inicialización
|
|
bool success = true;
|
|
|
|
// Inicializa SDL
|
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_HAPTIC) < 0)
|
|
{
|
|
printf("SDL could not initialize!\nSDL Error: %s\n", SDL_GetError());
|
|
success = false;
|
|
}
|
|
else
|
|
{
|
|
// Establece el filtro de la textura a nearest
|
|
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"))
|
|
{
|
|
printf("Warning: Nearest texture filtering not enabled!\n");
|
|
}
|
|
|
|
// Comprueba si hay algun mando conectado
|
|
if (SDL_NumJoysticks() < 1)
|
|
{
|
|
printf("Warning: No joysticks connected!\n");
|
|
mGameControllerFound = false;
|
|
}
|
|
else
|
|
{
|
|
// Carga el mando
|
|
mGameController = SDL_JoystickOpen(0);
|
|
mGameControllerFound = true;
|
|
|
|
if (mGameController == NULL)
|
|
{
|
|
printf("Warning: Unable to open game controller!\nSDL Error: %s\n", SDL_GetError());
|
|
mGameControllerFound = false;
|
|
}
|
|
else
|
|
{
|
|
printf("%i joysticks were found.\n", SDL_NumJoysticks());
|
|
std::cout << SDL_JoystickNumButtons(mGameController) << " buttons\n";
|
|
|
|
// Obtiene el dispositivo de control háptico
|
|
mControllerHaptic = SDL_HapticOpenFromJoystick(mGameController);
|
|
if (mControllerHaptic == NULL)
|
|
{
|
|
printf("Warning: Controller does not support haptics!\nSDL Error: %s\n", SDL_GetError());
|
|
}
|
|
else
|
|
{
|
|
printf("Haptics detected\n");
|
|
|
|
// Inicializa la vibración
|
|
if (SDL_HapticRumbleInit(mControllerHaptic) < 0)
|
|
{
|
|
printf("Warning: Unable to initialize rumble!\nSDL Error: %s\n", SDL_GetError());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Crea la ventana
|
|
mWindow = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, VIEW_WIDTH, VIEW_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
|
|
if (mWindow == NULL)
|
|
{
|
|
printf("Window could not be created!\nSDL Error: %s\n", SDL_GetError());
|
|
success = false;
|
|
}
|
|
else
|
|
{
|
|
// Crea un renderizador para la ventana con vsync
|
|
mRenderer = SDL_CreateRenderer(mWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
|
if (mRenderer == NULL)
|
|
{
|
|
printf("Renderer could not be created!\nSDL Error: %s\n", SDL_GetError());
|
|
success = false;
|
|
}
|
|
else
|
|
{
|
|
// Inicializa el color de renderizado
|
|
SDL_SetRenderDrawColor(mRenderer, 0x00, 0x00, 0x00, 0xFF);
|
|
|
|
// Establece el tamaño del buffer de renderizado
|
|
SDL_RenderSetLogicalSize(mRenderer, SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
|
|
// Establece el modo de mezcla
|
|
SDL_SetRenderDrawBlendMode(mRenderer, SDL_BLENDMODE_BLEND);
|
|
}
|
|
|
|
// Crea un backbuffer para el renderizador
|
|
mBackbuffer = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
if (mBackbuffer == NULL)
|
|
{
|
|
printf("Backbuffer could not be created!\nSDL Error: %s\n", SDL_GetError());
|
|
success = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
printf("\n");
|
|
return success;
|
|
}
|
|
|
|
// Inicializa el vector con los valores del seno
|
|
void GameDirector::initSin()
|
|
{
|
|
// Vector con los valores del seno para 360 grados
|
|
for (int i = 0; i < 360; i++)
|
|
{
|
|
mSin[i] = sin((float)i * 3.14f / 180.0f);
|
|
}
|
|
}
|
|
|
|
// Inicializa las variables que contienen puntos de ruta para mover objetos
|
|
void GameDirector::initPaths()
|
|
{
|
|
// Letrero de STAGE #
|
|
int firstPart = STAGE_COUNTER / 4; // 50
|
|
int secondPart = firstPart * 3; // 150
|
|
int centerPoint = PLAY_AREA_CENTER_Y - (BLOCK * 2);
|
|
int distance = (PLAY_AREA_BOTTOM) - (PLAY_AREA_CENTER_Y - 16);
|
|
|
|
for (int i = 0; i < STAGE_COUNTER; i++)
|
|
{
|
|
if (i < firstPart)
|
|
mGame.stageBitmapPath[i] = (mSin[(int)((i * 1.8f) + 90)] * (distance) + centerPoint);
|
|
else if (i < secondPart)
|
|
mGame.stageBitmapPath[i] = (int)centerPoint;
|
|
else
|
|
mGame.stageBitmapPath[i] = (mSin[(int)(((i - 149) * 1.8f) + 90)] * (centerPoint + 17) - 17);
|
|
}
|
|
|
|
float start1 = PLAY_AREA_LEFT - 130;
|
|
float finish1 = PLAY_AREA_CENTER_X - 55;
|
|
|
|
float start2 = finish1;
|
|
float finish2 = PLAY_AREA_RIGHT + 20;
|
|
|
|
float distance1 = finish1 - start1;
|
|
float distance2 = finish2 - start2;
|
|
|
|
// Letrero de GetReady
|
|
for (int i = 0; i < STAGE_COUNTER; i++)
|
|
{
|
|
if (i < firstPart)
|
|
{
|
|
mGame.getReadyBitmapPath[i] = mSin[(int)(i * 1.8f)];
|
|
mGame.getReadyBitmapPath[i] *= distance1;
|
|
mGame.getReadyBitmapPath[i] -= 130;
|
|
}
|
|
else if (i < secondPart)
|
|
mGame.getReadyBitmapPath[i] = (int)finish1;
|
|
else
|
|
{
|
|
mGame.getReadyBitmapPath[i] = mSin[(int)((i - 150) * 1.8f)];
|
|
mGame.getReadyBitmapPath[i] *= distance2;
|
|
mGame.getReadyBitmapPath[i] += finish1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Inicializa las variables necesarias para la sección 'Logo'
|
|
void GameDirector::initLogo()
|
|
{
|
|
// Reserva memoria para los punteros
|
|
mTexture[TEXTURE_LOGO].texture = new LTexture();
|
|
mLogo.sprite = new Sprite();
|
|
|
|
// Carga los recursos
|
|
loadMediaLogo();
|
|
|
|
// Inicializa variables
|
|
mLogo.counter = 0;
|
|
mLogo.sprite->init(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, mTexture[TEXTURE_LOGO].texture, mRenderer);
|
|
}
|
|
|
|
// Carga los recursos necesarios para la sección 'Logo'
|
|
bool GameDirector::loadMediaLogo()
|
|
{
|
|
bool success = true;
|
|
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_LOGO].texture, mTexture[TEXTURE_LOGO].file, mRenderer);
|
|
|
|
return success;
|
|
}
|
|
|
|
// Libera las variables necesarias para la sección 'Logo'
|
|
void GameDirector::quitLogo()
|
|
{
|
|
// Texturas
|
|
mTexture[TEXTURE_LOGO].texture->unload();
|
|
|
|
// Libera la memoria de los punteros
|
|
delete mTexture[TEXTURE_LOGO].texture;
|
|
delete mLogo.sprite;
|
|
mTexture[TEXTURE_LOGO].texture = nullptr;
|
|
mLogo.sprite = nullptr;
|
|
}
|
|
|
|
// Inicializa las variables necesarias para la sección 'Intro'
|
|
void GameDirector::initIntro()
|
|
{
|
|
// Reserva memoria para los punteros
|
|
mTexture[TEXTURE_INTRO].texture = new LTexture();
|
|
|
|
for (Uint8 i = 0; i < INTRO_TOTAL_BITMAPS; i++)
|
|
mIntro.bitmap[i] = new SmartSprite();
|
|
|
|
for (Uint8 i = 0; i < INTRO_TOTAL_TEXTS; i++)
|
|
mIntro.text[i] = new Text2();
|
|
|
|
// Carga los recursos
|
|
loadMediaIntro();
|
|
|
|
// Inicializa el vector de eventos de la intro
|
|
for (Uint8 i = 0; i < INTRO_TOTAL_EVENTS; i++)
|
|
mIntro.events[i] = EVENT_WAITING;
|
|
|
|
// Inicializa los bitmaps de la intro
|
|
for (Uint8 i = 0; i < INTRO_TOTAL_BITMAPS; i++)
|
|
{
|
|
mIntro.bitmap[i]->init(mTexture[TEXTURE_INTRO].texture, mRenderer);
|
|
mIntro.bitmap[i]->setId(i);
|
|
mIntro.bitmap[i]->setIntroEvents(&mIntro.events[0]);
|
|
mIntro.bitmap[i]->setWidth(128);
|
|
mIntro.bitmap[i]->setHeight(96);
|
|
mIntro.bitmap[i]->setEnabled(false);
|
|
mIntro.bitmap[i]->setEnabledTimer(20);
|
|
mIntro.bitmap[i]->setDestX(SCREEN_CENTER_X - 64);
|
|
mIntro.bitmap[i]->setDestY(SCREEN_FIRST_QUARTER_Y - 24);
|
|
}
|
|
|
|
mIntro.bitmap[0]->setPosX(-128);
|
|
mIntro.bitmap[0]->setPosY(SCREEN_FIRST_QUARTER_Y - 24);
|
|
mIntro.bitmap[0]->setVelX(0.0f);
|
|
mIntro.bitmap[0]->setVelY(0.0f);
|
|
mIntro.bitmap[0]->setAccelX(0.6f);
|
|
mIntro.bitmap[0]->setAccelY(0.0f);
|
|
mIntro.bitmap[0]->setSpriteClip(0, 0, 128, 96);
|
|
|
|
mIntro.bitmap[1]->setPosX(SCREEN_WIDTH);
|
|
mIntro.bitmap[1]->setPosY(SCREEN_FIRST_QUARTER_Y - 24);
|
|
mIntro.bitmap[1]->setVelX(-1.0f);
|
|
mIntro.bitmap[1]->setVelY(0.0f);
|
|
mIntro.bitmap[1]->setAccelX(-0.3f);
|
|
mIntro.bitmap[1]->setAccelY(0.0f);
|
|
mIntro.bitmap[1]->setSpriteClip(128, 0, 128, 96);
|
|
|
|
mIntro.bitmap[2]->setPosX(SCREEN_CENTER_X - 64);
|
|
mIntro.bitmap[2]->setPosY(-96);
|
|
mIntro.bitmap[2]->setVelX(0.0f);
|
|
mIntro.bitmap[2]->setVelY(3.0f);
|
|
mIntro.bitmap[2]->setAccelX(0.1f);
|
|
mIntro.bitmap[2]->setAccelY(0.3f);
|
|
mIntro.bitmap[2]->setSpriteClip(0, 96, 128, 96);
|
|
|
|
mIntro.bitmap[2]->setEnabledTimer(250);
|
|
|
|
mIntro.bitmap[3]->setPosX(SCREEN_CENTER_X - 64);
|
|
mIntro.bitmap[3]->setPosY(SCREEN_HEIGHT);
|
|
mIntro.bitmap[3]->setVelX(0.0f);
|
|
mIntro.bitmap[3]->setVelY(-0.7f);
|
|
mIntro.bitmap[3]->setAccelX(0.0f);
|
|
mIntro.bitmap[3]->setAccelY(0.0f);
|
|
mIntro.bitmap[3]->setSpriteClip(128, 96, 128, 96);
|
|
|
|
mIntro.bitmap[4]->setPosX(SCREEN_CENTER_X - 64);
|
|
mIntro.bitmap[4]->setPosY(-96);
|
|
mIntro.bitmap[4]->setVelX(0.0f);
|
|
mIntro.bitmap[4]->setVelY(3.0f);
|
|
mIntro.bitmap[4]->setAccelX(0.1f);
|
|
mIntro.bitmap[4]->setAccelY(0.3f);
|
|
mIntro.bitmap[4]->setSpriteClip(0, 192, 128, 96);
|
|
|
|
mIntro.bitmap[5]->setPosX(SCREEN_WIDTH);
|
|
mIntro.bitmap[5]->setPosY(SCREEN_FIRST_QUARTER_Y - 24);
|
|
mIntro.bitmap[5]->setVelX(-0.7f);
|
|
mIntro.bitmap[5]->setVelY(0.0f);
|
|
mIntro.bitmap[5]->setAccelX(0.0f);
|
|
mIntro.bitmap[5]->setAccelY(0.0f);
|
|
mIntro.bitmap[5]->setSpriteClip(128, 192, 128, 96);
|
|
|
|
// Inicializa los textos de la intro
|
|
for (Uint8 i = 0; i < INTRO_TOTAL_TEXTS; i++)
|
|
{
|
|
mIntro.text[i]->init(mTexture[TEXTURE_FONT_NOKIA].texture, mRenderer, TEXT_VARIABLE, 10);
|
|
mIntro.text[i]->setId(6 + i);
|
|
mIntro.text[i]->setIntroEvents(&mIntro.events[0]);
|
|
mIntro.text[i]->setPosX(BLOCK * 0);
|
|
mIntro.text[i]->setPosY(SCREEN_HEIGHT - (BLOCK * 6));
|
|
mIntro.text[i]->setKerning(-1);
|
|
mIntro.text[i]->setEnabled(false);
|
|
mIntro.text[i]->setEnabledTimer(180);
|
|
}
|
|
|
|
mIntro.text[0]->setCaption("Un dia qualsevol de l'any 2000");
|
|
mIntro.text[0]->setWrittingSpeed(10);
|
|
|
|
mIntro.text[1]->setCaption("Tot esta tranquil a la UPV");
|
|
mIntro.text[1]->setWrittingSpeed(10);
|
|
|
|
mIntro.text[2]->setCaption("Fins que un desaprensiu...");
|
|
mIntro.text[2]->setWrittingSpeed(15);
|
|
|
|
mIntro.text[3]->setCaption("HEY! ME ANE A FERME UN CORTAET...");
|
|
mIntro.text[3]->setWrittingSpeed(10);
|
|
|
|
mIntro.text[4]->setCaption("UAAAAAAAAAAAAA!!!");
|
|
mIntro.text[4]->setWrittingSpeed(1);
|
|
|
|
mIntro.text[5]->setCaption("Espera un moment...");
|
|
mIntro.text[5]->setWrittingSpeed(20);
|
|
|
|
mIntro.text[6]->setCaption("Si resulta que no tinc solt!");
|
|
mIntro.text[6]->setWrittingSpeed(2);
|
|
|
|
mIntro.text[7]->setCaption("MERDA DE MAQUINA!");
|
|
mIntro.text[7]->setWrittingSpeed(3);
|
|
|
|
mIntro.text[8]->setCaption("Blop... blop... blop...");
|
|
mIntro.text[8]->setWrittingSpeed(20);
|
|
|
|
for (Uint8 i = 0; i < INTRO_TOTAL_TEXTS; i++)
|
|
{
|
|
mIntro.text[i]->center(SCREEN_CENTER_X);
|
|
}
|
|
}
|
|
|
|
// Carga los recursos necesarios para la sección 'Intro'
|
|
bool GameDirector::loadMediaIntro()
|
|
{
|
|
bool success = true;
|
|
|
|
// Texturas
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_INTRO].texture, mTexture[TEXTURE_INTRO].file, mRenderer);
|
|
|
|
// Musicas
|
|
mMusic[MUSIC_INTRO].music = JA_LoadMusic(mMusic[MUSIC_INTRO].file.c_str());
|
|
|
|
return success;
|
|
}
|
|
|
|
// Libera las variables necesarias para la sección 'Intro'
|
|
void GameDirector::quitIntro()
|
|
{
|
|
// Texturas
|
|
mTexture[TEXTURE_INTRO].texture->unload();
|
|
|
|
// Musicas
|
|
JA_DeleteMusic(mMusic[MUSIC_INTRO].music);
|
|
|
|
// Libera la memoria de los punteros
|
|
delete mTexture[TEXTURE_INTRO].texture;
|
|
mTexture[TEXTURE_INTRO].texture = nullptr;
|
|
|
|
for (Uint8 i = 0; i < INTRO_TOTAL_BITMAPS; i++)
|
|
{
|
|
delete mIntro.bitmap[i];
|
|
mIntro.bitmap[i] = nullptr;
|
|
}
|
|
for (Uint8 i = 0; i < INTRO_TOTAL_TEXTS; i++)
|
|
{
|
|
delete mIntro.text[i];
|
|
mIntro.text[i] = nullptr;
|
|
}
|
|
}
|
|
|
|
// Inicializa las variables necesarias para la sección 'Title'
|
|
void GameDirector::initTitle(Uint8 subsection)
|
|
{
|
|
// Reserva memoria para los punteros
|
|
mTexture[TEXTURE_TITLE].texture = new LTexture();
|
|
mTexture[TEXTURE_ITEMS].texture = new LTexture();
|
|
mTitle.coffeeBitmap = new SmartSprite();
|
|
mTitle.crisisBitmap = new SmartSprite();
|
|
mTitle.dustBitmapL = new AnimatedSprite();
|
|
mTitle.dustBitmapR = new AnimatedSprite();
|
|
mTitle.tile = new Sprite();
|
|
|
|
// Carga los recursos
|
|
loadMediaTitle();
|
|
|
|
// Inicializa variables
|
|
mTitle.section = subsection;
|
|
mTitle.counter = TITLE_COUNTER;
|
|
mTitle.backgroundCounter = 0;
|
|
mTitle.backgroundMode = rand() % 2;
|
|
mTitle.menuVisible = false;
|
|
mTitle.nextProgSection = PROG_SECTION_GAME;
|
|
mTitle.instructionsCounter = INSTRUCTIONS_COUNTER;
|
|
|
|
// Inicializa el bitmap de Coffee
|
|
mTitle.coffeeBitmap->init(mTexture[TEXTURE_TITLE].texture, mRenderer);
|
|
mTitle.coffeeBitmap->setId(0);
|
|
mTitle.coffeeBitmap->setIntroEvents(&mTitle.events[0]);
|
|
mTitle.coffeeBitmap->setPosX(45);
|
|
mTitle.coffeeBitmap->setPosY(11 - 200);
|
|
mTitle.coffeeBitmap->setWidth(167);
|
|
mTitle.coffeeBitmap->setHeight(46);
|
|
mTitle.coffeeBitmap->setVelX(0.0f);
|
|
mTitle.coffeeBitmap->setVelY(2.5f);
|
|
mTitle.coffeeBitmap->setAccelX(0.0f);
|
|
mTitle.coffeeBitmap->setAccelY(0.1f);
|
|
mTitle.coffeeBitmap->setSpriteClip(0, 0, 167, 46);
|
|
mTitle.coffeeBitmap->setEnabled(true);
|
|
mTitle.coffeeBitmap->setEnabledTimer(0);
|
|
mTitle.coffeeBitmap->setDestX(45);
|
|
mTitle.coffeeBitmap->setDestY(11);
|
|
|
|
// Inicializa el bitmap de Crisis
|
|
mTitle.crisisBitmap->init(mTexture[TEXTURE_TITLE].texture, mRenderer);
|
|
mTitle.crisisBitmap->setId(1);
|
|
mTitle.crisisBitmap->setIntroEvents(&mTitle.events[0]);
|
|
mTitle.crisisBitmap->setPosX(60);
|
|
mTitle.crisisBitmap->setPosY(57 + 200);
|
|
mTitle.crisisBitmap->setWidth(137);
|
|
mTitle.crisisBitmap->setHeight(46);
|
|
mTitle.crisisBitmap->setVelX(0.0f);
|
|
mTitle.crisisBitmap->setVelY(-2.5f);
|
|
mTitle.crisisBitmap->setAccelX(0.0f);
|
|
mTitle.crisisBitmap->setAccelY(-0.1f);
|
|
mTitle.crisisBitmap->setSpriteClip(0, 46, 137, 46);
|
|
mTitle.crisisBitmap->setEnabled(true);
|
|
mTitle.crisisBitmap->setEnabledTimer(0);
|
|
mTitle.crisisBitmap->setDestX(60);
|
|
mTitle.crisisBitmap->setDestY(57);
|
|
|
|
// Inicializa el bitmap de DustRight
|
|
mTitle.dustBitmapR->init(mTexture[TEXTURE_TITLE].texture, mRenderer);
|
|
mTitle.dustBitmapR->setPosX(218);
|
|
mTitle.dustBitmapR->setPosY(47);
|
|
mTitle.dustBitmapR->setWidth(16);
|
|
mTitle.dustBitmapR->setHeight(14);
|
|
mTitle.dustBitmapR->setCurrentFrame(0);
|
|
mTitle.dustBitmapR->setAnimationCounter(0);
|
|
mTitle.dustBitmapR->setAnimationNumFrames(0, 7);
|
|
mTitle.dustBitmapR->setAnimationSpeed(0, 8);
|
|
mTitle.dustBitmapR->setAnimationLoop(0, false);
|
|
mTitle.dustBitmapR->setAnimationFrames(0, 0, 160 + (mTitle.dustBitmapR->getWidth() * 0), 80, mTitle.dustBitmapR->getWidth(), mTitle.dustBitmapR->getHeight());
|
|
mTitle.dustBitmapR->setAnimationFrames(0, 1, 160 + (mTitle.dustBitmapR->getWidth() * 1), 80, mTitle.dustBitmapR->getWidth(), mTitle.dustBitmapR->getHeight());
|
|
mTitle.dustBitmapR->setAnimationFrames(0, 2, 160 + (mTitle.dustBitmapR->getWidth() * 2), 80, mTitle.dustBitmapR->getWidth(), mTitle.dustBitmapR->getHeight());
|
|
mTitle.dustBitmapR->setAnimationFrames(0, 3, 160 + (mTitle.dustBitmapR->getWidth() * 3), 80, mTitle.dustBitmapR->getWidth(), mTitle.dustBitmapR->getHeight());
|
|
mTitle.dustBitmapR->setAnimationFrames(0, 4, 160 + (mTitle.dustBitmapR->getWidth() * 4), 80, mTitle.dustBitmapR->getWidth(), mTitle.dustBitmapR->getHeight());
|
|
mTitle.dustBitmapR->setAnimationFrames(0, 5, 160 + (mTitle.dustBitmapR->getWidth() * 5), 80, mTitle.dustBitmapR->getWidth(), mTitle.dustBitmapR->getHeight());
|
|
mTitle.dustBitmapR->setAnimationFrames(0, 6, 160 + (mTitle.dustBitmapR->getWidth() * 6), 80, mTitle.dustBitmapR->getWidth(), mTitle.dustBitmapR->getHeight());
|
|
|
|
// Inicializa el bitmap de DustLeft
|
|
mTitle.dustBitmapL->init(mTexture[TEXTURE_TITLE].texture, mRenderer);
|
|
mTitle.dustBitmapL->setPosX(33);
|
|
mTitle.dustBitmapL->setPosY(47);
|
|
mTitle.dustBitmapL->setWidth(16);
|
|
mTitle.dustBitmapL->setHeight(14);
|
|
mTitle.dustBitmapL->setCurrentFrame(0);
|
|
mTitle.dustBitmapL->setAnimationCounter(0);
|
|
mTitle.dustBitmapL->setAnimationNumFrames(0, 7);
|
|
mTitle.dustBitmapL->setAnimationSpeed(0, 8);
|
|
mTitle.dustBitmapL->setAnimationLoop(0, false);
|
|
mTitle.dustBitmapL->setAnimationFrames(0, 0, 160 + (mTitle.dustBitmapL->getWidth() * 0), 66, mTitle.dustBitmapL->getWidth(), mTitle.dustBitmapL->getHeight());
|
|
mTitle.dustBitmapL->setAnimationFrames(0, 1, 160 + (mTitle.dustBitmapL->getWidth() * 1), 66, mTitle.dustBitmapL->getWidth(), mTitle.dustBitmapL->getHeight());
|
|
mTitle.dustBitmapL->setAnimationFrames(0, 2, 160 + (mTitle.dustBitmapL->getWidth() * 2), 66, mTitle.dustBitmapL->getWidth(), mTitle.dustBitmapL->getHeight());
|
|
mTitle.dustBitmapL->setAnimationFrames(0, 3, 160 + (mTitle.dustBitmapL->getWidth() * 3), 66, mTitle.dustBitmapL->getWidth(), mTitle.dustBitmapL->getHeight());
|
|
mTitle.dustBitmapL->setAnimationFrames(0, 4, 160 + (mTitle.dustBitmapL->getWidth() * 4), 66, mTitle.dustBitmapL->getWidth(), mTitle.dustBitmapL->getHeight());
|
|
mTitle.dustBitmapL->setAnimationFrames(0, 5, 160 + (mTitle.dustBitmapL->getWidth() * 5), 66, mTitle.dustBitmapL->getWidth(), mTitle.dustBitmapL->getHeight());
|
|
mTitle.dustBitmapL->setAnimationFrames(0, 6, 160 + (mTitle.dustBitmapL->getWidth() * 6), 66, mTitle.dustBitmapL->getWidth(), mTitle.dustBitmapL->getHeight());
|
|
|
|
// Inicializa el vector de eventos de la pantalla de titulo
|
|
for (Uint8 i = 0; i < TITLE_TOTAL_EVENTS; i++)
|
|
mTitle.events[i] = EVENT_WAITING;
|
|
}
|
|
|
|
// Carga los recursos necesarios para la sección 'Title'
|
|
bool GameDirector::loadMediaTitle()
|
|
{
|
|
// Indicador de éxito en la carga
|
|
bool success = true;
|
|
|
|
// Texturas
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_TITLE].texture, mTexture[TEXTURE_TITLE].file, mRenderer);
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_ITEMS].texture, mTexture[TEXTURE_ITEMS].file, mRenderer);
|
|
|
|
// Crea el mosaico de fondo del titulo
|
|
mTitleSurface = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH * 2, SCREEN_HEIGHT * 2);
|
|
if (mTitleSurface == NULL)
|
|
{
|
|
printf("TitleSurface could not be created!\nSDL Error: %s\n", SDL_GetError());
|
|
success = false;
|
|
}
|
|
else
|
|
{
|
|
SDL_SetRenderTarget(mRenderer, mTitleSurface);
|
|
SDL_SetRenderDrawColor(mRenderer, 0x43, 0x43, 0x4F, 0xFF);
|
|
SDL_RenderClear(mRenderer);
|
|
|
|
mTitle.tile->init(0, 0, 64, 64, mTexture[TEXTURE_TITLE].texture, mRenderer);
|
|
mTitle.tile->setSpriteClip(192, 0, 64, 64);
|
|
for (Uint8 i = 0; i < 8; i++)
|
|
for (Uint8 j = 0; j < 6; j++)
|
|
{
|
|
mTitle.tile->setPosX(i * 64);
|
|
mTitle.tile->setPosY(j * 64);
|
|
mTitle.tile->render();
|
|
}
|
|
|
|
mTitle.backgroundWindow.x = 0;
|
|
mTitle.backgroundWindow.y = 0;
|
|
mTitle.backgroundWindow.w = SCREEN_WIDTH;
|
|
mTitle.backgroundWindow.h = SCREEN_HEIGHT;
|
|
SDL_SetRenderTarget(mRenderer, nullptr);
|
|
}
|
|
|
|
// Crea una textura para dibujar las instrucciones
|
|
mInstructionsSurface = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
if (mInstructionsSurface == NULL)
|
|
{
|
|
printf("InstructionsSurface could not be created!\nSDL Error: %s\n", SDL_GetError());
|
|
success = false;
|
|
}
|
|
|
|
// Sonidos
|
|
mSound[SOUND_TITLE].sound = JA_LoadSound(mSound[SOUND_TITLE].file.c_str());
|
|
|
|
return success;
|
|
}
|
|
|
|
// Libera las variables necesarias para la sección 'Title'
|
|
void GameDirector::quitTitle()
|
|
{
|
|
// Texturas
|
|
mTexture[TEXTURE_TITLE].texture->unload();
|
|
mTexture[TEXTURE_ITEMS].texture->unload();
|
|
|
|
// Sonidos
|
|
JA_DeleteSound(mSound[SOUND_TITLE].sound);
|
|
|
|
// Libera la memoria de los punteros
|
|
delete mTexture[TEXTURE_TITLE].texture;
|
|
delete mTexture[TEXTURE_ITEMS].texture;
|
|
delete mTitle.coffeeBitmap;
|
|
delete mTitle.crisisBitmap;
|
|
delete mTitle.dustBitmapL;
|
|
delete mTitle.dustBitmapR;
|
|
delete mTitle.tile;
|
|
mTexture[TEXTURE_TITLE].texture = nullptr;
|
|
mTexture[TEXTURE_ITEMS].texture = nullptr;
|
|
mTitle.coffeeBitmap = nullptr;
|
|
mTitle.crisisBitmap = nullptr;
|
|
mTitle.dustBitmapL = nullptr;
|
|
mTitle.dustBitmapR = nullptr;
|
|
mTitle.tile = nullptr;
|
|
|
|
SDL_DestroyTexture(mTitleSurface);
|
|
SDL_DestroyTexture(mInstructionsSurface);
|
|
mTitleSurface = nullptr;
|
|
mInstructionsSurface = nullptr;
|
|
}
|
|
|
|
// Inicializa las variables necesarias para la sección 'Game'
|
|
void GameDirector::initGame()
|
|
{
|
|
// Reserva memoria para los punteros
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
mGame.balloon[i] = new Balloon();
|
|
for (Uint8 i = 0; i < MAX_BULLETS; i++)
|
|
mGame.bullet[i] = new Bullet();
|
|
for (Uint8 i = 0; i < MAX_ITEMS; i++)
|
|
mGame.item[i] = new Item();
|
|
for (Uint8 i = 0; i < MAX_SMART_SPRITES; i++)
|
|
mGame.smartSprite[i] = new SmartSprite();
|
|
mTexture[TEXTURE_PLAYER_LEGS].texture = new LTexture();
|
|
mTexture[TEXTURE_PLAYER_BODY].texture = new LTexture();
|
|
mTexture[TEXTURE_PLAYER_DEATH].texture = new LTexture();
|
|
mTexture[TEXTURE_BALLOON].texture = new LTexture();
|
|
mTexture[TEXTURE_BULLET].texture = new LTexture();
|
|
mTexture[TEXTURE_GAME_BG].texture = new LTexture();
|
|
mTexture[TEXTURE_GAME_TEXT].texture = new LTexture();
|
|
mTexture[TEXTURE_ITEMS].texture = new LTexture();
|
|
mGame.player = new Player();
|
|
mGame._1000Bitmap = new SmartSprite();
|
|
mGame._2500Bitmap = new SmartSprite();
|
|
mGame._5000Bitmap = new SmartSprite();
|
|
mGame.background = new Sprite();
|
|
mGame.clouds1a = new MovingSprite();
|
|
mGame.clouds1b = new MovingSprite();
|
|
mGame.clouds2a = new MovingSprite();
|
|
mGame.clouds2b = new MovingSprite();
|
|
mGame.getReadyBitmap = new Sprite();
|
|
mGame.gradient = new Sprite();
|
|
mGame.grass = new Sprite();
|
|
mGame.scoreBoard = new Sprite();
|
|
mGame.powerMeter = new Sprite();
|
|
|
|
// Carga los recursos
|
|
loadMediaGame();
|
|
|
|
// Inicializa variables
|
|
resetGame();
|
|
}
|
|
|
|
// Inicializa las variables especificas de la sección 'Game' para empezar una nueva partida
|
|
void GameDirector::resetGame()
|
|
{
|
|
// Inicializa las variables
|
|
mGame.section = GAME_SECTION_PLAY;
|
|
mGame.menaceCurrent = 0;
|
|
mGame.menaceThreshold = 0;
|
|
mGame.score = 0;
|
|
mGame.hiScoreAchieved = false;
|
|
mGame.currentStage = 0;
|
|
mGame.stageBitmapCounter = STAGE_COUNTER;
|
|
mGame.deathCounter = DEATH_COUNTER;
|
|
mGame.explosionTime = false;
|
|
mGame.remainingExplosions = REMAINING_EXPLOSIONS;
|
|
mGame.remainingExplosionsCounter = REMAINING_EXPLOSIONS_COUNTER;
|
|
mGame.timeStopped = false;
|
|
mGame.timeStoppedCounter = TIME_STOPPED_COUNTER;
|
|
mGame.counter = 0;
|
|
mGame.balloonsPopped = 0;
|
|
mGame.lastEnemyDeploy = 0;
|
|
mGame.enemyDeployCounter = 0;
|
|
mGame.enemySpeed = BALLOON_SPEED_1;
|
|
mGame.effect.flash = false;
|
|
mGame.effect.shake = false;
|
|
mGame.effect.shakeCounter = SHAKE_COUNTER;
|
|
initGameStages();
|
|
|
|
// Sprites
|
|
mGame.clouds1a->init(0, 0, 256, 52, -0.4f, 0.0f, 0.0f, 0.0f, mTexture[TEXTURE_GAME_BG].texture, mRenderer);
|
|
mGame.clouds1a->setSpriteClip(256, 0, 256, 52);
|
|
|
|
mGame.clouds1b->init(256, 0, 256, 52, -0.4f, 0.0f, 0.0f, 0.0f, mTexture[TEXTURE_GAME_BG].texture, mRenderer);
|
|
mGame.clouds1b->setSpriteClip(256, 0, 256, 52);
|
|
|
|
mGame.clouds2a->init(0, 52, 256, 32, -0.2f, 0.0f, 0.0f, 0.0f, mTexture[TEXTURE_GAME_BG].texture, mRenderer);
|
|
mGame.clouds2a->setSpriteClip(256, 52, 256, 32);
|
|
|
|
mGame.clouds2b->init(256, 52, 256, 32, -0.2f, 0.0f, 0.0f, 0.0f, mTexture[TEXTURE_GAME_BG].texture, mRenderer);
|
|
mGame.clouds2b->setSpriteClip(256, 52, 256, 32);
|
|
|
|
mGame.grass->init(0, 85, SCREEN_WIDTH, 6, mTexture[TEXTURE_GAME_BG].texture, mRenderer);
|
|
mGame.grass->setPosY(154);
|
|
|
|
mGame.scoreBoard->init(0, 160, SCREEN_WIDTH, 32, mTexture[TEXTURE_GAME_BG].texture, mRenderer);
|
|
mGame.scoreBoard->setSpriteClip(0, 160, 256, 32);
|
|
|
|
mGame.powerMeter->init(PLAY_AREA_CENTER_THIRD_QUARTER_X - 20, HISCORE_NUMBER_Y + 4, 40, 8, mTexture[TEXTURE_GAME_BG].texture, mRenderer);
|
|
mGame.powerMeter->setSpriteClip(256, 192 - 8, 40, 8);
|
|
|
|
// Objeto jugador
|
|
mGame.player->init(PLAY_AREA_CENTER_X - 11, PLAY_AREA_BOTTOM - 24, mTexture[TEXTURE_PLAYER_LEGS].texture, mTexture[TEXTURE_PLAYER_BODY].texture, mRenderer);
|
|
|
|
// Establece a cero todos los valores del vector de objetos globo
|
|
resetBalloons();
|
|
|
|
// Crea objetos globo y los centra en el area de juego
|
|
//mGame.balloon[0]->init(0, -BLOCK, POWER_BALL, BALLOON_VELX_POSITIVE, mGame.enemySpeed, 300, mTexture[TEXTURE_BALLOON].texture, mRenderer);
|
|
//mGame.balloon[0]->allignTo(PLAY_AREA_CENTER_X);
|
|
|
|
// Con los globos creados, calcula el nivel de amenaza
|
|
setMenace();
|
|
|
|
// Establece a cero todos los valores del vector de objetos bala
|
|
resetBullets();
|
|
|
|
// Establece a cero todos los valores del vector de objetos item
|
|
resetItems();
|
|
|
|
// Establece a cero todos los valores del vector de objetos SmafrtSprite
|
|
resetSmartSprites();
|
|
|
|
// Inicializa el bitmap de GetLeady!
|
|
mGame.getReadyBitmap->init(0, PLAY_AREA_CENTER_Y - 10, 109, 20, mTexture[TEXTURE_GAME_TEXT].texture, mRenderer);
|
|
mGame.getReadyBitmap->setSpriteClip(0, 0, 109, 20);
|
|
|
|
// Inicializa el bitmap de 1000 puntos
|
|
mGame._1000Bitmap->init(mTexture[TEXTURE_GAME_TEXT].texture, mRenderer);
|
|
mGame._1000Bitmap->setPosX(0);
|
|
mGame._1000Bitmap->setPosY(0);
|
|
mGame._1000Bitmap->setWidth(26);
|
|
mGame._1000Bitmap->setHeight(9);
|
|
mGame._1000Bitmap->setVelX(0.0f);
|
|
mGame._1000Bitmap->setVelY(-0.5f);
|
|
mGame._1000Bitmap->setAccelX(0.0f);
|
|
mGame._1000Bitmap->setAccelY(-0.1f);
|
|
mGame._1000Bitmap->setSpriteClip(0, 20, 26, 9);
|
|
mGame._1000Bitmap->setEnabled(false);
|
|
mGame._1000Bitmap->setEnabledTimer(0);
|
|
mGame._1000Bitmap->setDestX(0);
|
|
mGame._1000Bitmap->setDestY(0);
|
|
|
|
// Inicializa el bitmap de 2500 puntos
|
|
mGame._2500Bitmap->init(mTexture[TEXTURE_GAME_TEXT].texture, mRenderer);
|
|
mGame._2500Bitmap->setPosX(0);
|
|
mGame._2500Bitmap->setPosY(0);
|
|
mGame._2500Bitmap->setWidth(28);
|
|
mGame._2500Bitmap->setHeight(9);
|
|
mGame._2500Bitmap->setVelX(0.0f);
|
|
mGame._2500Bitmap->setVelY(-0.5f);
|
|
mGame._2500Bitmap->setAccelX(0.0f);
|
|
mGame._2500Bitmap->setAccelY(-0.1f);
|
|
mGame._2500Bitmap->setSpriteClip(26, 20, 28, 9);
|
|
mGame._2500Bitmap->setEnabled(false);
|
|
mGame._2500Bitmap->setEnabledTimer(0);
|
|
mGame._2500Bitmap->setDestX(0);
|
|
mGame._2500Bitmap->setDestY(0);
|
|
|
|
// Inicializa el bitmap de 5000 puntos
|
|
mGame._5000Bitmap->init(mTexture[TEXTURE_GAME_TEXT].texture, mRenderer);
|
|
mGame._5000Bitmap->setPosX(0);
|
|
mGame._5000Bitmap->setPosY(0);
|
|
mGame._5000Bitmap->setWidth(28);
|
|
mGame._5000Bitmap->setHeight(9);
|
|
mGame._5000Bitmap->setVelX(0.0f);
|
|
mGame._5000Bitmap->setVelY(-0.5f);
|
|
mGame._5000Bitmap->setAccelX(0.0f);
|
|
mGame._5000Bitmap->setAccelY(-0.1f);
|
|
mGame._5000Bitmap->setSpriteClip(54, 20, 28, 9);
|
|
mGame._5000Bitmap->setEnabled(false);
|
|
mGame._5000Bitmap->setEnabledTimer(0);
|
|
mGame._5000Bitmap->setDestX(0);
|
|
mGame._5000Bitmap->setDestY(0);
|
|
|
|
// Los fondos
|
|
mGame.background->init(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, mTexture[TEXTURE_GAME_BG].texture, mRenderer);
|
|
mGame.gradient->init(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, mTexture[TEXTURE_GAME_BG].texture, mRenderer);
|
|
mGame.gradientRect[0] = {0, 192, SCREEN_WIDTH, SCREEN_HEIGHT};
|
|
mGame.gradientRect[1] = {256, 192, SCREEN_WIDTH, SCREEN_HEIGHT};
|
|
mGame.gradientRect[2] = {0, 384, SCREEN_WIDTH, SCREEN_HEIGHT};
|
|
mGame.gradientRect[3] = {256, 384, SCREEN_WIDTH, SCREEN_HEIGHT};
|
|
}
|
|
|
|
// Carga los recursos necesarios para la sección 'Game'
|
|
bool GameDirector::loadMediaGame()
|
|
{
|
|
bool success = true;
|
|
|
|
// Texturas
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_PLAYER_LEGS].texture, mTexture[TEXTURE_PLAYER_LEGS].file, mRenderer);
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_PLAYER_BODY].texture, mTexture[TEXTURE_PLAYER_BODY].file, mRenderer);
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_PLAYER_DEATH].texture, mTexture[TEXTURE_PLAYER_DEATH].file, mRenderer);
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_BALLOON].texture, mTexture[TEXTURE_BALLOON].file, mRenderer);
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_BULLET].texture, mTexture[TEXTURE_BULLET].file, mRenderer);
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_GAME_BG].texture, mTexture[TEXTURE_GAME_BG].file, mRenderer);
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_GAME_TEXT].texture, mTexture[TEXTURE_GAME_TEXT].file, mRenderer);
|
|
success &= loadTextureFromFile(mTexture[TEXTURE_ITEMS].texture, mTexture[TEXTURE_ITEMS].file, mRenderer);
|
|
|
|
// Sonidos
|
|
mSound[SOUND_BALLOON].sound = JA_LoadSound(mSound[SOUND_BALLOON].file.c_str());
|
|
mSound[SOUND_BULLET].sound = JA_LoadSound(mSound[SOUND_BULLET].file.c_str());
|
|
mSound[SOUND_PLAYER_COLLISION].sound = JA_LoadSound(mSound[SOUND_PLAYER_COLLISION].file.c_str());
|
|
mSound[SOUND_HISCORE].sound = JA_LoadSound(mSound[SOUND_HISCORE].file.c_str());
|
|
mSound[SOUND_ITEM_DROP].sound = JA_LoadSound(mSound[SOUND_ITEM_DROP].file.c_str());
|
|
mSound[SOUND_ITEM_PICKUP].sound = JA_LoadSound(mSound[SOUND_ITEM_PICKUP].file.c_str());
|
|
mSound[SOUND_COFFEE_OUT].sound = JA_LoadSound(mSound[SOUND_COFFEE_OUT].file.c_str());
|
|
mSound[SOUND_STAGE_CHANGE].sound = JA_LoadSound(mSound[SOUND_STAGE_CHANGE].file.c_str());
|
|
mSound[SOUND_TITLE].sound = JA_LoadSound(mSound[SOUND_TITLE].file.c_str());
|
|
mSound[SOUND_BUBBLE1].sound = JA_LoadSound(mSound[SOUND_BUBBLE1].file.c_str());
|
|
mSound[SOUND_BUBBLE2].sound = JA_LoadSound(mSound[SOUND_BUBBLE2].file.c_str());
|
|
mSound[SOUND_BUBBLE3].sound = JA_LoadSound(mSound[SOUND_BUBBLE3].file.c_str());
|
|
mSound[SOUND_BUBBLE4].sound = JA_LoadSound(mSound[SOUND_BUBBLE4].file.c_str());
|
|
|
|
// Musicas
|
|
mMusic[MUSIC_PLAYING].music = JA_LoadMusic(mMusic[MUSIC_PLAYING].file.c_str());
|
|
|
|
return success;
|
|
}
|
|
|
|
// Libera las variables necesarias para la sección 'Game'
|
|
void GameDirector::quitGame()
|
|
{
|
|
// Texturas
|
|
mTexture[TEXTURE_PLAYER_LEGS].texture->unload();
|
|
mTexture[TEXTURE_PLAYER_BODY].texture->unload();
|
|
mTexture[TEXTURE_PLAYER_DEATH].texture->unload();
|
|
mTexture[TEXTURE_BALLOON].texture->unload();
|
|
mTexture[TEXTURE_BULLET].texture->unload();
|
|
mTexture[TEXTURE_GAME_BG].texture->unload();
|
|
mTexture[TEXTURE_GAME_TEXT].texture->unload();
|
|
mTexture[TEXTURE_ITEMS].texture->unload();
|
|
|
|
// Sonidos
|
|
JA_DeleteSound(mSound[SOUND_BALLOON].sound);
|
|
JA_DeleteSound(mSound[SOUND_BULLET].sound);
|
|
JA_DeleteSound(mSound[SOUND_PLAYER_COLLISION].sound);
|
|
JA_DeleteSound(mSound[SOUND_HISCORE].sound);
|
|
JA_DeleteSound(mSound[SOUND_ITEM_DROP].sound);
|
|
JA_DeleteSound(mSound[SOUND_ITEM_PICKUP].sound);
|
|
JA_DeleteSound(mSound[SOUND_COFFEE_OUT].sound);
|
|
JA_DeleteSound(mSound[SOUND_STAGE_CHANGE].sound);
|
|
JA_DeleteSound(mSound[SOUND_TITLE].sound);
|
|
JA_DeleteSound(mSound[SOUND_BUBBLE1].sound);
|
|
JA_DeleteSound(mSound[SOUND_BUBBLE2].sound);
|
|
JA_DeleteSound(mSound[SOUND_BUBBLE3].sound);
|
|
JA_DeleteSound(mSound[SOUND_BUBBLE4].sound);
|
|
|
|
// Musicas
|
|
JA_DeleteMusic(mMusic[MUSIC_PLAYING].music);
|
|
|
|
// Libera la memoria de los punteros
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
{
|
|
delete mGame.balloon[i];
|
|
mGame.balloon[i] = nullptr;
|
|
}
|
|
for (Uint8 i = 0; i < MAX_BULLETS; i++)
|
|
{
|
|
delete mGame.bullet[i];
|
|
mGame.bullet[i] = nullptr;
|
|
}
|
|
for (Uint8 i = 0; i < MAX_ITEMS; i++)
|
|
{
|
|
delete mGame.item[i];
|
|
mGame.item[i] = nullptr;
|
|
}
|
|
for (Uint8 i = 0; i < MAX_SMART_SPRITES; i++)
|
|
{
|
|
delete mGame.smartSprite[i];
|
|
mGame.smartSprite[i] = nullptr;
|
|
}
|
|
delete mTexture[TEXTURE_PLAYER_LEGS].texture;
|
|
delete mTexture[TEXTURE_PLAYER_BODY].texture;
|
|
delete mTexture[TEXTURE_PLAYER_DEATH].texture;
|
|
delete mTexture[TEXTURE_BALLOON].texture;
|
|
delete mTexture[TEXTURE_BULLET].texture;
|
|
delete mTexture[TEXTURE_GAME_BG].texture;
|
|
delete mTexture[TEXTURE_GAME_TEXT].texture;
|
|
delete mTexture[TEXTURE_ITEMS].texture;
|
|
delete mGame.player;
|
|
delete mGame._1000Bitmap;
|
|
delete mGame._2500Bitmap;
|
|
delete mGame._5000Bitmap;
|
|
delete mGame.background;
|
|
delete mGame.clouds1a;
|
|
delete mGame.clouds1b;
|
|
delete mGame.clouds2a;
|
|
delete mGame.clouds2b;
|
|
delete mGame.getReadyBitmap;
|
|
delete mGame.gradient;
|
|
delete mGame.grass;
|
|
delete mGame.scoreBoard;
|
|
delete mGame.powerMeter;
|
|
mTexture[TEXTURE_PLAYER_LEGS].texture = nullptr;
|
|
mTexture[TEXTURE_PLAYER_BODY].texture = nullptr;
|
|
mTexture[TEXTURE_PLAYER_DEATH].texture = nullptr;
|
|
mTexture[TEXTURE_BALLOON].texture = nullptr;
|
|
mTexture[TEXTURE_BULLET].texture = nullptr;
|
|
mTexture[TEXTURE_GAME_BG].texture = nullptr;
|
|
mTexture[TEXTURE_GAME_TEXT].texture = nullptr;
|
|
mTexture[TEXTURE_ITEMS].texture = nullptr;
|
|
mGame.player = nullptr;
|
|
mGame._1000Bitmap = nullptr;
|
|
mGame._2500Bitmap = nullptr;
|
|
mGame._5000Bitmap = nullptr;
|
|
mGame.background = nullptr;
|
|
mGame.clouds1a = nullptr;
|
|
mGame.clouds1b = nullptr;
|
|
mGame.clouds2a = nullptr;
|
|
mGame.clouds2b = nullptr;
|
|
mGame.getReadyBitmap = nullptr;
|
|
mGame.gradient = nullptr;
|
|
mGame.grass = nullptr;
|
|
mGame.scoreBoard = nullptr;
|
|
mGame.powerMeter = nullptr;
|
|
}
|
|
|
|
// Crea el indice de ficheros
|
|
void GameDirector::setFileList()
|
|
{
|
|
// Ficheros binarios
|
|
mBinFile[BINFILE_SCORE].file = mProg.executablePath + "/" + "../data/score.bin";
|
|
mBinFile[BINFILE_DEMO].file = mProg.executablePath + "/" + "../data/demo.bin";
|
|
mBinFile[BINFILE_CONFIG].file = mProg.executablePath + "/" + "../data/config.bin";
|
|
|
|
// Musicas
|
|
mMusic[MUSIC_INTRO].file = mProg.executablePath + "/" + "../media/music/intro.ogg";
|
|
mMusic[MUSIC_PLAYING].file = mProg.executablePath + "/" + "../media/music/playing.ogg";
|
|
mMusic[MUSIC_TITLE].file = mProg.executablePath + "/" + "../media/music/title.ogg";
|
|
|
|
// Sonidos
|
|
mSound[SOUND_BALLOON].file = mProg.executablePath + "/" + "../media/sound/balloon.wav";
|
|
mSound[SOUND_BUBBLE1].file = mProg.executablePath + "/" + "../media/sound/bubble1.wav";
|
|
mSound[SOUND_BUBBLE2].file = mProg.executablePath + "/" + "../media/sound/bubble2.wav";
|
|
mSound[SOUND_BUBBLE3].file = mProg.executablePath + "/" + "../media/sound/bubble3.wav";
|
|
mSound[SOUND_BUBBLE4].file = mProg.executablePath + "/" + "../media/sound/bubble4.wav";
|
|
mSound[SOUND_BULLET].file = mProg.executablePath + "/" + "../media/sound/bullet.wav";
|
|
mSound[SOUND_COFFEE_OUT].file = mProg.executablePath + "/" + "../media/sound/coffeeout.wav";
|
|
mSound[SOUND_HISCORE].file = mProg.executablePath + "/" + "../media/sound/hiscore.wav";
|
|
mSound[SOUND_ITEM_DROP].file = mProg.executablePath + "/" + "../media/sound/itemdrop.wav";
|
|
mSound[SOUND_ITEM_PICKUP].file = mProg.executablePath + "/" + "../media/sound/itempickup.wav";
|
|
mSound[SOUND_MENU_CANCEL].file = mProg.executablePath + "/" + "../media/sound/menu_cancel.wav";
|
|
mSound[SOUND_MENU_MOVE].file = mProg.executablePath + "/" + "../media/sound/menu_move.wav";
|
|
mSound[SOUND_MENU_SELECT].file = mProg.executablePath + "/" + "../media/sound/menu_select.wav";
|
|
mSound[SOUND_PLAYER_COLLISION].file = mProg.executablePath + "/" + "../media/sound/player_collision.wav";
|
|
mSound[SOUND_STAGE_CHANGE].file = mProg.executablePath + "/" + "../media/sound/stage_change.wav";
|
|
mSound[SOUND_TITLE].file = mProg.executablePath + "/" + "../media/sound/title.wav";
|
|
|
|
// Texturas
|
|
mTexture[TEXTURE_BALLOON].file = mProg.executablePath + "/" + "../media/gfx/balloon.png";
|
|
mTexture[TEXTURE_BULLET].file = mProg.executablePath + "/" + "../media/gfx/bullet.png";
|
|
mTexture[TEXTURE_FONT_BLACK_X2].file = mProg.executablePath + "/" + "../media/gfx/font_black_x2.png";
|
|
mTexture[TEXTURE_FONT_BLACK].file = mProg.executablePath + "/" + "../media/gfx/font_black.png";
|
|
mTexture[TEXTURE_FONT_NOKIA].file = mProg.executablePath + "/" + "../media/gfx/font_nokia.png";
|
|
mTexture[TEXTURE_FONT_WHITE_X2].file = mProg.executablePath + "/" + "../media/gfx/font_white_x2.png";
|
|
mTexture[TEXTURE_FONT_WHITE].file = mProg.executablePath + "/" + "../media/gfx/font_white.png";
|
|
mTexture[TEXTURE_GAME_BG].file = mProg.executablePath + "/" + "../media/gfx/game_bg.png";
|
|
mTexture[TEXTURE_GAME_TEXT].file = mProg.executablePath + "/" + "../media/gfx/game_text.png";
|
|
mTexture[TEXTURE_INTRO].file = mProg.executablePath + "/" + "../media/gfx/intro.png";
|
|
mTexture[TEXTURE_ITEMS].file = mProg.executablePath + "/" + "../media/gfx/items.png";
|
|
mTexture[TEXTURE_LOGO].file = mProg.executablePath + "/" + "../media/gfx/logo.png";
|
|
mTexture[TEXTURE_MENU].file = mProg.executablePath + "/" + "../media/gfx/menu.png";
|
|
mTexture[TEXTURE_PLAYER_BODY].file = mProg.executablePath + "/" + "../media/gfx/player_body.png";
|
|
mTexture[TEXTURE_PLAYER_DEATH].file = mProg.executablePath + "/" + "../media/gfx/player_death.png";
|
|
mTexture[TEXTURE_PLAYER_LEGS].file = mProg.executablePath + "/" + "../media/gfx/player_legs.png";
|
|
mTexture[TEXTURE_TITLE].file = mProg.executablePath + "/" + "../media/gfx/title.png";
|
|
}
|
|
|
|
// Comprueba que todos los ficheros existen
|
|
bool GameDirector::checkFileList()
|
|
{
|
|
bool success = true;
|
|
std::string p;
|
|
std::string filename;
|
|
SDL_RWops *file;
|
|
|
|
// Comprueba los ficheros de musica
|
|
printf("\n>> MUSIC FILES\n");
|
|
if (success)
|
|
for (Uint8 i = 0; i < TOTAL_MUSIC; i++)
|
|
{
|
|
p = mMusic[i].file.c_str();
|
|
filename = p.substr(p.find_last_of("\\/") + 1);
|
|
file = SDL_RWFromFile(p.c_str(), "r+b");
|
|
if (file != NULL)
|
|
{
|
|
printf("Checking file %-20s [OK]\n", filename.c_str());
|
|
}
|
|
else
|
|
{
|
|
printf("Checking file %-20s [ERROR]\n", filename.c_str());
|
|
success = false;
|
|
break;
|
|
}
|
|
SDL_RWclose(file);
|
|
}
|
|
|
|
// Comprueba los ficheros de sonidos
|
|
printf("\n>> SOUND FILES\n");
|
|
if (success)
|
|
for (Uint8 i = 0; i < TOTAL_SOUND; i++)
|
|
{
|
|
p = mSound[i].file.c_str();
|
|
filename = p.substr(p.find_last_of("\\/") + 1);
|
|
file = SDL_RWFromFile(p.c_str(), "r+b");
|
|
if (file != NULL)
|
|
{
|
|
printf("Checking file %-20s [OK]\n", filename.c_str());
|
|
}
|
|
else
|
|
{
|
|
printf("Checking file %-20s [ERROR]\n", filename.c_str());
|
|
success = false;
|
|
break;
|
|
}
|
|
SDL_RWclose(file);
|
|
}
|
|
|
|
// Comprueba los ficheros con texturas
|
|
printf("\n>> TEXTURE FILES\n");
|
|
if (success)
|
|
for (Uint8 i = 0; i < TOTAL_TEXTURE; i++)
|
|
{
|
|
p = mTexture[i].file.c_str();
|
|
filename = p.substr(p.find_last_of("\\/") + 1);
|
|
file = SDL_RWFromFile(p.c_str(), "r+b");
|
|
if (file != NULL)
|
|
{
|
|
printf("Checking file %-20s [OK]\n", filename.c_str());
|
|
}
|
|
else
|
|
{
|
|
printf("Checking file %-20s [ERROR]\n", filename.c_str());
|
|
success = false;
|
|
break;
|
|
}
|
|
SDL_RWclose(file);
|
|
}
|
|
|
|
// Resultado
|
|
if (success)
|
|
printf("\n** All files OK.\n\n");
|
|
else
|
|
printf("\n** A file is missing. Exiting.\n\n");
|
|
|
|
return success;
|
|
}
|
|
|
|
// Carga el fichero de puntos
|
|
bool GameDirector::loadScoreFile()
|
|
{
|
|
// Indicador de éxito en la carga
|
|
bool success = true;
|
|
std::string path = mProg.executablePath + "/";
|
|
std::string p = mBinFile[BINFILE_SCORE].file.c_str();
|
|
std::string filename = p.substr(p.find_last_of("\\/") + 1);
|
|
SDL_RWops *file = SDL_RWFromFile(p.c_str(), "r+b");
|
|
|
|
// El fichero no existe
|
|
if (file == NULL)
|
|
{
|
|
printf("Warning: Unable to open %s file\n", filename.c_str());
|
|
|
|
// Creamos el fichero para escritura
|
|
file = SDL_RWFromFile(p.c_str(), "w+b");
|
|
if (file != NULL)
|
|
{
|
|
printf("New file (%s) created!\n", filename.c_str());
|
|
|
|
// Inicializamos los datos
|
|
for (int i = 0; i < TOTAL_SCORE_DATA; ++i)
|
|
{
|
|
mGame.scoreDataFile[i] = 0;
|
|
SDL_RWwrite(file, &mGame.scoreDataFile[i], sizeof(Uint32), 1);
|
|
}
|
|
|
|
// Cerramos el fichero
|
|
SDL_RWclose(file);
|
|
}
|
|
else
|
|
{
|
|
printf("Error: Unable to create file %s\n", filename.c_str());
|
|
success = false;
|
|
}
|
|
}
|
|
// El fichero existe
|
|
else
|
|
{
|
|
// Cargamos los datos
|
|
printf("Reading file %s\n", filename.c_str());
|
|
for (int i = 0; i < TOTAL_SCORE_DATA; ++i)
|
|
SDL_RWread(file, &mGame.scoreDataFile[i], sizeof(Uint32), 1);
|
|
|
|
// Cierra el fichero
|
|
SDL_RWclose(file);
|
|
}
|
|
|
|
// Establece el valor de la máxima puntuación a partir del vector con los datos
|
|
if (mGame.scoreDataFile[0] == 0)
|
|
mGame.hiScore = 10000;
|
|
// Comprueba el checksum para ver si se ha modificado el fichero
|
|
else if (mGame.scoreDataFile[0] % 43 == mGame.scoreDataFile[1])
|
|
mGame.hiScore = mGame.scoreDataFile[0];
|
|
else
|
|
mGame.hiScore = 10000;
|
|
|
|
return success;
|
|
}
|
|
|
|
// Carga el fichero de configuración
|
|
bool GameDirector::loadConfigFile()
|
|
{
|
|
// Indicador de éxito en la carga
|
|
bool success = true;
|
|
std::string path = mProg.executablePath + "/";
|
|
std::string p = mBinFile[BINFILE_CONFIG].file.c_str();
|
|
std::string filename = p.substr(p.find_last_of("\\/") + 1);
|
|
SDL_RWops *file = SDL_RWFromFile(p.c_str(), "r+b");
|
|
|
|
// El fichero no existe
|
|
if (file == NULL)
|
|
{
|
|
printf("Warning: Unable to open %s file\n", filename.c_str());
|
|
|
|
// Creamos el fichero para escritura
|
|
file = SDL_RWFromFile(p.c_str(), "w+b");
|
|
if (file != NULL)
|
|
{
|
|
printf("New file (%s) created!\n", filename.c_str());
|
|
|
|
// Inicializamos los datos
|
|
mOptions.fullScreenMode = 0;
|
|
SDL_RWwrite(file, &mOptions.fullScreenMode, sizeof(mOptions.fullScreenMode), 1);
|
|
|
|
mOptions.windowSize = 3;
|
|
SDL_RWwrite(file, &mOptions.windowSize, sizeof(mOptions.windowSize), 1);
|
|
|
|
// Cerramos el fichero
|
|
SDL_RWclose(file);
|
|
}
|
|
else
|
|
{
|
|
printf("Error: Unable to create file %s\n", filename.c_str());
|
|
success = false;
|
|
}
|
|
}
|
|
// El fichero existe
|
|
else
|
|
{
|
|
// Cargamos los datos
|
|
printf("Reading file %s\n", filename.c_str());
|
|
SDL_RWread(file, &mOptions.fullScreenMode, sizeof(mOptions.fullScreenMode), 1);
|
|
SDL_SetWindowFullscreen(mWindow, mOptions.fullScreenMode);
|
|
SDL_RWread(file, &mOptions.windowSize, sizeof(mOptions.windowSize), 1);
|
|
SDL_SetWindowSize(mWindow, SCREEN_WIDTH * mOptions.windowSize, SCREEN_HEIGHT * mOptions.windowSize);
|
|
|
|
// Cierra el fichero
|
|
SDL_RWclose(file);
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
// Carga el fichero de datos para la demo
|
|
bool GameDirector::loadDemoFile()
|
|
{
|
|
// Indicador de éxito en la carga
|
|
bool success = true;
|
|
std::string path = mProg.executablePath + "/";
|
|
std::string p = mBinFile[BINFILE_DEMO].file.c_str();
|
|
std::string filename = p.substr(p.find_last_of("\\/") + 1);
|
|
SDL_RWops *file = SDL_RWFromFile(p.c_str(), "r+b");
|
|
|
|
// El fichero no existe
|
|
if (file == NULL)
|
|
{
|
|
printf("Warning: Unable to open %s file\n", filename.c_str());
|
|
|
|
// Creamos el fichero para escritura
|
|
file = SDL_RWFromFile(p.c_str(), "w+b");
|
|
if (file != NULL)
|
|
{
|
|
printf("New file (%s) created!\n", filename.c_str());
|
|
|
|
// Inicializamos los datos
|
|
for (int i = 0; i < TOTAL_DEMO_DATA; ++i)
|
|
{
|
|
mDemo.keys.left = 0;
|
|
mDemo.keys.right = 0;
|
|
mDemo.keys.noInput = 0;
|
|
mDemo.keys.fire = 0;
|
|
mDemo.keys.fireLeft = 0;
|
|
mDemo.keys.fireRight = 0;
|
|
mDemo.dataFile[i] = mDemo.keys;
|
|
SDL_RWwrite(file, &mDemo.dataFile[i], sizeof(demoKeys_t), 1);
|
|
}
|
|
|
|
// Cerramos el fichero
|
|
SDL_RWclose(file);
|
|
}
|
|
else
|
|
{
|
|
printf("Error: Unable to create file %s\n", filename.c_str());
|
|
success = false;
|
|
}
|
|
}
|
|
// El fichero existe
|
|
else
|
|
{
|
|
// Cargamos los datos
|
|
printf("Reading file %s\n", filename.c_str());
|
|
for (int i = 0; i < TOTAL_DEMO_DATA; ++i)
|
|
SDL_RWread(file, &mDemo.dataFile[i], sizeof(demoKeys_t), 1);
|
|
|
|
// Cierra el fichero
|
|
SDL_RWclose(file);
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
// Guarda el fichero de puntos
|
|
bool GameDirector::saveScoreFile()
|
|
{
|
|
bool success = true;
|
|
std::string path = mProg.executablePath + "/";
|
|
std::string p = mBinFile[BINFILE_SCORE].file;
|
|
std::string filename = p.substr(p.find_last_of("\\/") + 1);
|
|
SDL_RWops *file = SDL_RWFromFile(p.c_str(), "w+b");
|
|
if (file != NULL)
|
|
{
|
|
// Guardamos los datos
|
|
for (int i = 0; i < TOTAL_SCORE_DATA; ++i)
|
|
{
|
|
SDL_RWwrite(file, &mGame.scoreDataFile[i], sizeof(Uint32), 1);
|
|
}
|
|
|
|
printf("Writing file %s\n", filename.c_str());
|
|
|
|
// Cerramos el fichero
|
|
SDL_RWclose(file);
|
|
}
|
|
else
|
|
{
|
|
printf("Error: Unable to save %s file! %s\n", filename.c_str(), SDL_GetError());
|
|
}
|
|
return success;
|
|
}
|
|
|
|
// Guarda el fichero de configuración
|
|
bool GameDirector::saveConfigFile()
|
|
{
|
|
bool success = true;
|
|
std::string path = mProg.executablePath + "/";
|
|
std::string p = mBinFile[BINFILE_CONFIG].file;
|
|
std::string filename = p.substr(p.find_last_of("\\/") + 1);
|
|
SDL_RWops *file = SDL_RWFromFile(p.c_str(), "w+b");
|
|
if (file != NULL)
|
|
{
|
|
// Guarda los datos
|
|
SDL_RWwrite(file, &mOptions.fullScreenMode, sizeof(Uint32), 1);
|
|
SDL_RWwrite(file, &mOptions.windowSize, sizeof(Uint8), 1);
|
|
|
|
printf("Writing file %s\n", filename.c_str());
|
|
|
|
// Cierra el fichero
|
|
SDL_RWclose(file);
|
|
}
|
|
else
|
|
{
|
|
printf("Error: Unable to save %s file! %s\n", filename.c_str(), SDL_GetError());
|
|
}
|
|
return success;
|
|
}
|
|
|
|
// Guarda el fichero de datos para la demo
|
|
bool GameDirector::saveDemoFile()
|
|
{
|
|
bool success = true;
|
|
std::string path = mProg.executablePath + "/";
|
|
std::string p = mBinFile[BINFILE_DEMO].file;
|
|
std::string filename = p.substr(p.find_last_of("\\/") + 1);
|
|
if (mDemo.recording)
|
|
{
|
|
SDL_RWops *file = SDL_RWFromFile(p.c_str(), "w+b");
|
|
if (file != NULL)
|
|
{
|
|
// Guardamos los datos
|
|
for (int i = 0; i < TOTAL_DEMO_DATA; ++i)
|
|
{
|
|
SDL_RWwrite(file, &mDemo.dataFile[i], sizeof(demoKeys_t), 1);
|
|
}
|
|
|
|
printf("Writing file %s\n", filename.c_str());
|
|
|
|
// Cerramos el fichero
|
|
SDL_RWclose(file);
|
|
}
|
|
else
|
|
{
|
|
printf("Error: Unable to save %s file! %s\n", filename.c_str(), SDL_GetError());
|
|
}
|
|
}
|
|
return success;
|
|
}
|
|
|
|
// Carga un archivo de imagen en una textura
|
|
bool GameDirector::loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer)
|
|
{
|
|
bool success = true;
|
|
if (!texture->loadFromFile(path, renderer))
|
|
{
|
|
printf("Failed to load %s texture!\n", path.c_str());
|
|
success = false;
|
|
}
|
|
return success;
|
|
}
|
|
|
|
// Comprueba el valor de la variable 'quit'
|
|
bool GameDirector::exit()
|
|
{
|
|
return mProg.quit;
|
|
}
|
|
|
|
// Establece el valor de la variable
|
|
void GameDirector::setExecutablePath(std::string path)
|
|
{
|
|
mProg.executablePath = path.substr(0, path.find_last_of("\\/"));
|
|
}
|
|
|
|
// Inicializa las formaciones enemigas
|
|
void GameDirector::initEnemyFormations()
|
|
{
|
|
const int y4 = (PLAY_AREA_TOP - BLOCK);
|
|
const int x4_0 = PLAY_AREA_LEFT;
|
|
//const int x4_50 = PLAY_AREA_CENTER_X - (BALLOON_SIZE_4 / 2);
|
|
const int x4_100 = (PLAY_AREA_RIGHT)-BALLOON_SIZE_4;
|
|
|
|
const int y3 = (PLAY_AREA_TOP - BLOCK);
|
|
const int x3_0 = PLAY_AREA_LEFT;
|
|
//const int x3_50 = PLAY_AREA_CENTER_X - (BALLOON_SIZE_3 / 2);
|
|
const int x3_100 = (PLAY_AREA_RIGHT)-BALLOON_SIZE_3;
|
|
|
|
const int y2 = (PLAY_AREA_TOP - BLOCK);
|
|
const int x2_0 = PLAY_AREA_LEFT;
|
|
//const int x2_50 = PLAY_AREA_CENTER_X - (BALLOON_SIZE_2 / 2);
|
|
const int x2_100 = (PLAY_AREA_RIGHT)-BALLOON_SIZE_2;
|
|
|
|
const int y1 = (PLAY_AREA_TOP - BLOCK);
|
|
const int x1_0 = PLAY_AREA_LEFT;
|
|
const int x1_50 = PLAY_AREA_CENTER_X - (BALLOON_SIZE_1 / 2);
|
|
const int x1_100 = (PLAY_AREA_RIGHT)-BALLOON_SIZE_1;
|
|
|
|
const Uint16 creationTime = 300;
|
|
int incX = 0;
|
|
Uint8 incTime = 0;
|
|
Uint8 j = 0;
|
|
|
|
// #00 - Dos enemigos BALLOON4 uno a cada extremo
|
|
j = 0;
|
|
mEnemyFormation[j].numberOfEnemies = 2;
|
|
incX = x4_100;
|
|
incTime = 0;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x4_0 + (i * incX);
|
|
mEnemyFormation[j].init[i].y = y4;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE * (((i % 2) * 2) - 1);
|
|
mEnemyFormation[j].init[i].kind = BALLOON_4;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime + (incTime * i);
|
|
}
|
|
|
|
// #01 - Dos enemigos BALLOON4 uno a cada cuarto. Ambos van hacia el centro
|
|
j = 1;
|
|
mEnemyFormation[j].numberOfEnemies = 2;
|
|
incX = PLAY_AREA_CENTER_X;
|
|
incTime = 0;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = PLAY_AREA_CENTER_FIRST_QUARTER_X - (BALLOON_SIZE_4 / 2) + (i * incX);
|
|
mEnemyFormation[j].init[i].y = y4;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE * (((i % 2) * 2) - 1);
|
|
mEnemyFormation[j].init[i].kind = BALLOON_4;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime + (incTime * i);
|
|
}
|
|
|
|
// #02 - Cuatro enemigos BALLOON2 uno detras del otro. A la izquierda y hacia el centro
|
|
j = 2;
|
|
mEnemyFormation[j].numberOfEnemies = 4;
|
|
incX = BALLOON_SIZE_2 + 1;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x2_0 + (i * incX);
|
|
mEnemyFormation[j].init[i].y = y2;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_2;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #03 - Cuatro enemigos BALLOON2 uno detras del otro. A la derecha y hacia el centro
|
|
j = 3;
|
|
mEnemyFormation[j].numberOfEnemies = 4;
|
|
incX = BALLOON_SIZE_2 + 1;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x2_100 - (i * incX);
|
|
mEnemyFormation[j].init[i].y = y2;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_2;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #04 - Tres enemigos BALLOON3. 0, 25, 50. Hacia la derecha
|
|
j = 4;
|
|
mEnemyFormation[j].numberOfEnemies = 3;
|
|
incX = BALLOON_SIZE_3 * 2;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x3_0 + (i * incX);
|
|
mEnemyFormation[j].init[i].y = y3;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_3;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #05 - Tres enemigos BALLOON3. 50, 75, 100. Hacia la izquierda
|
|
j = 5;
|
|
mEnemyFormation[j].numberOfEnemies = 3;
|
|
incX = BALLOON_SIZE_3 * 2;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x3_100 - (i * incX);
|
|
mEnemyFormation[j].init[i].y = y3;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_3;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #06 - Tres enemigos BALLOON3. 0, 0, 0. Hacia la derecha
|
|
j = 6;
|
|
mEnemyFormation[j].numberOfEnemies = 3;
|
|
incX = BALLOON_SIZE_3 + 1;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x3_0 + (i * incX);
|
|
mEnemyFormation[j].init[i].y = y3;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_3;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #07 - Tres enemigos BALLOON3. 100, 100, 100. Hacia la izquierda
|
|
j = 7;
|
|
mEnemyFormation[j].numberOfEnemies = 3;
|
|
incX = BALLOON_SIZE_3 + 1;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x3_100 - (i * incX);
|
|
mEnemyFormation[j].init[i].y = y3;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_3;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #08 - Seis enemigos BALLOON1. 0, 0, 0, 0, 0, 0. Hacia la derecha
|
|
j = 8;
|
|
mEnemyFormation[j].numberOfEnemies = 6;
|
|
incX = BALLOON_SIZE_1 + 1;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x1_0 + (i * incX);
|
|
mEnemyFormation[j].init[i].y = 13;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_1;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #09 - Seis enemigos BALLOON1. 100, 100, 100, 100, 100, 100. Hacia la izquierda
|
|
j = 9;
|
|
mEnemyFormation[j].numberOfEnemies = 6;
|
|
incX = BALLOON_SIZE_1 + 1;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x1_100 - (i * incX);
|
|
mEnemyFormation[j].init[i].y = 13;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_1;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #10 - Tres enemigos BALLOON4 seguidos desde la izquierda
|
|
j = 10;
|
|
mEnemyFormation[j].numberOfEnemies = 3;
|
|
incX = BALLOON_SIZE_4 + 1;
|
|
incTime = 15;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x4_0 + (i * incX);
|
|
mEnemyFormation[j].init[i].y = y4;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_4;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #11 - Tres enemigos BALLOON4 seguidos desde la derecha
|
|
j = 11;
|
|
mEnemyFormation[j].numberOfEnemies = 3;
|
|
incX = BALLOON_SIZE_4 + 1;
|
|
incTime = 15;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x4_100 - (i * incX);
|
|
mEnemyFormation[j].init[i].y = y4;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_4;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #12 - Seis enemigos BALLOON2 uno detras del otro. A la izquierda y hacia el centro
|
|
j = 12;
|
|
mEnemyFormation[j].numberOfEnemies = 6;
|
|
incX = BALLOON_SIZE_2 + 1;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x2_0 + (i * incX);
|
|
mEnemyFormation[j].init[i].y = y2;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_2;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #13 - Seis enemigos BALLOON2 uno detras del otro. A la derecha y hacia el centro
|
|
j = 13;
|
|
mEnemyFormation[j].numberOfEnemies = 6;
|
|
incX = BALLOON_SIZE_2 + 1;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x2_100 - (i * incX);
|
|
mEnemyFormation[j].init[i].y = y2;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_2;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #14 - Cinco enemigos BALLOON3. Hacia la derecha. Separados
|
|
j = 14;
|
|
mEnemyFormation[j].numberOfEnemies = 5;
|
|
incX = BALLOON_SIZE_3 * 2;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x3_0 + (i * incX);
|
|
mEnemyFormation[j].init[i].y = y3;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_3;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #15 - Cinco enemigos BALLOON3. Hacia la izquierda. Separados
|
|
j = 15;
|
|
mEnemyFormation[j].numberOfEnemies = 5;
|
|
incX = BALLOON_SIZE_3 * 2;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x3_100 - (i * incX);
|
|
mEnemyFormation[j].init[i].y = y3;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_3;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #16 - Cinco enemigos BALLOON3. Hacia la derecha. Juntos
|
|
j = 16;
|
|
mEnemyFormation[j].numberOfEnemies = 5;
|
|
incX = BALLOON_SIZE_3 + 1;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x3_0 + (i * incX);
|
|
mEnemyFormation[j].init[i].y = y3;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_3;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #17 - Cinco enemigos BALLOON3. Hacia la izquierda. Juntos
|
|
j = 17;
|
|
mEnemyFormation[j].numberOfEnemies = 5;
|
|
incX = BALLOON_SIZE_3 + 1;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x3_100 - (i * incX);
|
|
mEnemyFormation[j].init[i].y = y3;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_3;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #18 - Doce enemigos BALLOON1. Hacia la derecha. Juntos
|
|
j = 18;
|
|
mEnemyFormation[j].numberOfEnemies = 12;
|
|
incX = BALLOON_SIZE_1 + 1;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x1_0 + (i * incX);
|
|
mEnemyFormation[j].init[i].y = y1;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_1;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #19 - Doce enemigos BALLOON1. Hacia la izquierda. Juntos
|
|
j = 19;
|
|
mEnemyFormation[j].numberOfEnemies = 12;
|
|
incX = BALLOON_SIZE_1 + 1;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x1_100 - (i * incX);
|
|
mEnemyFormation[j].init[i].y = y1;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_1;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
|
|
}
|
|
|
|
// #20 - Dos enemigos BALLOON4 seguidos desde la izquierda/derecha. Simetricos
|
|
j = 20;
|
|
mEnemyFormation[j].numberOfEnemies = 4;
|
|
incX = BALLOON_SIZE_4 + 1;
|
|
incTime = 0;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
Uint8 half = mEnemyFormation[j].numberOfEnemies / 2;
|
|
if (i < half)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x4_0 + (i * incX);
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
|
|
}
|
|
else
|
|
{
|
|
mEnemyFormation[j].init[i].x = x4_100 - ((i - half) * incX);
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
|
|
}
|
|
mEnemyFormation[j].init[i].y = y4;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_4;
|
|
mEnemyFormation[j].init[i].creationCounter = creationTime + (incTime * i);
|
|
}
|
|
|
|
// #21 - Diez enemigos BALLOON2 uno detras del otro. Izquierda/derecha. Simetricos
|
|
j = 21;
|
|
mEnemyFormation[j].numberOfEnemies = 10;
|
|
incX = BALLOON_SIZE_2 + 1;
|
|
incTime = 3;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
Uint8 half = mEnemyFormation[j].numberOfEnemies / 2;
|
|
if (i < half)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x2_0 + (i * incX);
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
|
|
mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * i);
|
|
}
|
|
else
|
|
{
|
|
mEnemyFormation[j].init[i].x = x2_100 - ((i - half) * incX);
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
|
|
mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * (i - half));
|
|
}
|
|
mEnemyFormation[j].init[i].y = y2;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_2;
|
|
}
|
|
|
|
// #22 - Diez enemigos BALLOON3. Hacia la derecha/izquierda. Separados. Simetricos
|
|
j = 22;
|
|
mEnemyFormation[j].numberOfEnemies = 10;
|
|
incX = BALLOON_SIZE_3 * 2;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
Uint8 half = mEnemyFormation[j].numberOfEnemies / 2;
|
|
if (i < half)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x3_0 + (i * incX);
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
|
|
mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * i);
|
|
}
|
|
else
|
|
{
|
|
mEnemyFormation[j].init[i].x = x3_100 - ((i - half) * incX);
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
|
|
mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * (i - half));
|
|
}
|
|
mEnemyFormation[j].init[i].y = y3;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_3;
|
|
}
|
|
|
|
// #23 - Diez enemigos BALLOON3. Hacia la derecha. Juntos. Simetricos
|
|
j = 23;
|
|
mEnemyFormation[j].numberOfEnemies = 10;
|
|
incX = BALLOON_SIZE_3 + 1;
|
|
incTime = 10;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
Uint8 half = mEnemyFormation[j].numberOfEnemies / 2;
|
|
if (i < half)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x3_0 + (i * incX);
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
|
|
mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * i);
|
|
}
|
|
else
|
|
{
|
|
mEnemyFormation[j].init[i].x = x3_100 - ((i - half) * incX);
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
|
|
mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * (i - half));
|
|
}
|
|
mEnemyFormation[j].init[i].y = y3;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_3;
|
|
}
|
|
|
|
// #24 - Treinta enemigos BALLOON1. Del centro hacia los extremos. Juntos. Simetricos
|
|
j = 24;
|
|
mEnemyFormation[j].numberOfEnemies = 30;
|
|
incX = 0;
|
|
incTime = 5;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
Uint8 half = mEnemyFormation[j].numberOfEnemies / 2;
|
|
if (i < half)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x1_50;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
|
|
mEnemyFormation[j].init[i].creationCounter = (creationTime) + (incTime * i);
|
|
}
|
|
else
|
|
{
|
|
mEnemyFormation[j].init[i].x = x1_50;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
|
|
mEnemyFormation[j].init[i].creationCounter = (creationTime) + (incTime * (i - half));
|
|
}
|
|
mEnemyFormation[j].init[i].y = y1;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_1;
|
|
}
|
|
|
|
// #25 - Treinta enemigos BALLOON1. Del centro hacia adentro. Juntos. Simetricos
|
|
j = 25;
|
|
mEnemyFormation[j].numberOfEnemies = 30;
|
|
incX = BALLOON_SIZE_1 + 1;
|
|
incTime = 5;
|
|
for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++)
|
|
{
|
|
Uint8 half = mEnemyFormation[j].numberOfEnemies / 2;
|
|
if (i < half)
|
|
{
|
|
mEnemyFormation[j].init[i].x = x1_50 + 20;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
|
|
mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * i);
|
|
}
|
|
else
|
|
{
|
|
mEnemyFormation[j].init[i].x = x1_50 - 20;
|
|
mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
|
|
mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * (i - half));
|
|
}
|
|
mEnemyFormation[j].init[i].y = y1;
|
|
mEnemyFormation[j].init[i].kind = BALLOON_1;
|
|
}
|
|
|
|
// Crea las mismas formaciones pero con hexagonos a partir de la posición 50 del vector
|
|
for (Uint8 k = 0; k < 50; k++)
|
|
{
|
|
mEnemyFormation[k + 50].numberOfEnemies = mEnemyFormation[k].numberOfEnemies;
|
|
for (Uint8 i = 0; i < mEnemyFormation[k + 50].numberOfEnemies; i++)
|
|
{
|
|
mEnemyFormation[k + 50].init[i].x = mEnemyFormation[k].init[i].x;
|
|
mEnemyFormation[k + 50].init[i].y = mEnemyFormation[k].init[i].y;
|
|
mEnemyFormation[k + 50].init[i].velX = mEnemyFormation[k].init[i].velX;
|
|
mEnemyFormation[k + 50].init[i].creationCounter = mEnemyFormation[k].init[i].creationCounter;
|
|
mEnemyFormation[k + 50].init[i].kind = mEnemyFormation[k].init[i].kind + 4;
|
|
}
|
|
}
|
|
|
|
// TEST
|
|
mEnemyFormation[99].numberOfEnemies = 4;
|
|
|
|
mEnemyFormation[99].init[0].x = 10;
|
|
mEnemyFormation[99].init[0].y = y1;
|
|
mEnemyFormation[99].init[0].velX = 0;
|
|
mEnemyFormation[99].init[0].kind = BALLOON_1;
|
|
mEnemyFormation[99].init[0].creationCounter = 200;
|
|
|
|
mEnemyFormation[99].init[1].x = 50;
|
|
mEnemyFormation[99].init[1].y = y1;
|
|
mEnemyFormation[99].init[1].velX = 0;
|
|
mEnemyFormation[99].init[1].kind = BALLOON_2;
|
|
mEnemyFormation[99].init[1].creationCounter = 200;
|
|
|
|
mEnemyFormation[99].init[2].x = 90;
|
|
mEnemyFormation[99].init[2].y = y1;
|
|
mEnemyFormation[99].init[2].velX = 0;
|
|
mEnemyFormation[99].init[2].kind = BALLOON_3;
|
|
mEnemyFormation[99].init[2].creationCounter = 200;
|
|
|
|
mEnemyFormation[99].init[3].x = 140;
|
|
mEnemyFormation[99].init[3].y = y1;
|
|
mEnemyFormation[99].init[3].velX = 0;
|
|
mEnemyFormation[99].init[3].kind = BALLOON_4;
|
|
mEnemyFormation[99].init[3].creationCounter = 200;
|
|
}
|
|
|
|
// Inicializa los conjuntos de formaciones
|
|
void GameDirector::initEnemyPools()
|
|
{
|
|
// EnemyPool #0
|
|
mEnemyPool[0].set[0] = &mEnemyFormation[0];
|
|
mEnemyPool[0].set[1] = &mEnemyFormation[1];
|
|
mEnemyPool[0].set[2] = &mEnemyFormation[2];
|
|
mEnemyPool[0].set[3] = &mEnemyFormation[3];
|
|
mEnemyPool[0].set[4] = &mEnemyFormation[4];
|
|
mEnemyPool[0].set[5] = &mEnemyFormation[5];
|
|
mEnemyPool[0].set[6] = &mEnemyFormation[6];
|
|
mEnemyPool[0].set[7] = &mEnemyFormation[7];
|
|
mEnemyPool[0].set[8] = &mEnemyFormation[8];
|
|
mEnemyPool[0].set[9] = &mEnemyFormation[9];
|
|
|
|
// EnemyPool #1
|
|
mEnemyPool[1].set[0] = &mEnemyFormation[10];
|
|
mEnemyPool[1].set[1] = &mEnemyFormation[11];
|
|
mEnemyPool[1].set[2] = &mEnemyFormation[12];
|
|
mEnemyPool[1].set[3] = &mEnemyFormation[13];
|
|
mEnemyPool[1].set[4] = &mEnemyFormation[14];
|
|
mEnemyPool[1].set[5] = &mEnemyFormation[15];
|
|
mEnemyPool[1].set[6] = &mEnemyFormation[16];
|
|
mEnemyPool[1].set[7] = &mEnemyFormation[17];
|
|
mEnemyPool[1].set[8] = &mEnemyFormation[18];
|
|
mEnemyPool[1].set[9] = &mEnemyFormation[19];
|
|
|
|
// EnemyPool #2
|
|
mEnemyPool[2].set[0] = &mEnemyFormation[0];
|
|
mEnemyPool[2].set[1] = &mEnemyFormation[1];
|
|
mEnemyPool[2].set[2] = &mEnemyFormation[2];
|
|
mEnemyPool[2].set[3] = &mEnemyFormation[3];
|
|
mEnemyPool[2].set[4] = &mEnemyFormation[4];
|
|
mEnemyPool[2].set[5] = &mEnemyFormation[55];
|
|
mEnemyPool[2].set[6] = &mEnemyFormation[56];
|
|
mEnemyPool[2].set[7] = &mEnemyFormation[57];
|
|
mEnemyPool[2].set[8] = &mEnemyFormation[58];
|
|
mEnemyPool[2].set[9] = &mEnemyFormation[59];
|
|
|
|
// EnemyPool #3
|
|
mEnemyPool[3].set[0] = &mEnemyFormation[50];
|
|
mEnemyPool[3].set[1] = &mEnemyFormation[51];
|
|
mEnemyPool[3].set[2] = &mEnemyFormation[52];
|
|
mEnemyPool[3].set[3] = &mEnemyFormation[53];
|
|
mEnemyPool[3].set[4] = &mEnemyFormation[54];
|
|
mEnemyPool[3].set[5] = &mEnemyFormation[5];
|
|
mEnemyPool[3].set[6] = &mEnemyFormation[6];
|
|
mEnemyPool[3].set[7] = &mEnemyFormation[7];
|
|
mEnemyPool[3].set[8] = &mEnemyFormation[8];
|
|
mEnemyPool[3].set[9] = &mEnemyFormation[9];
|
|
|
|
// EnemyPool #4
|
|
mEnemyPool[4].set[0] = &mEnemyFormation[60];
|
|
mEnemyPool[4].set[1] = &mEnemyFormation[61];
|
|
mEnemyPool[4].set[2] = &mEnemyFormation[62];
|
|
mEnemyPool[4].set[3] = &mEnemyFormation[63];
|
|
mEnemyPool[4].set[4] = &mEnemyFormation[64];
|
|
mEnemyPool[4].set[5] = &mEnemyFormation[65];
|
|
mEnemyPool[4].set[6] = &mEnemyFormation[66];
|
|
mEnemyPool[4].set[7] = &mEnemyFormation[67];
|
|
mEnemyPool[4].set[8] = &mEnemyFormation[68];
|
|
mEnemyPool[4].set[9] = &mEnemyFormation[69];
|
|
|
|
// EnemyPool #5
|
|
mEnemyPool[5].set[0] = &mEnemyFormation[10];
|
|
mEnemyPool[5].set[1] = &mEnemyFormation[61];
|
|
mEnemyPool[5].set[2] = &mEnemyFormation[12];
|
|
mEnemyPool[5].set[3] = &mEnemyFormation[63];
|
|
mEnemyPool[5].set[4] = &mEnemyFormation[14];
|
|
mEnemyPool[5].set[5] = &mEnemyFormation[65];
|
|
mEnemyPool[5].set[6] = &mEnemyFormation[16];
|
|
mEnemyPool[5].set[7] = &mEnemyFormation[67];
|
|
mEnemyPool[5].set[8] = &mEnemyFormation[18];
|
|
mEnemyPool[5].set[9] = &mEnemyFormation[69];
|
|
|
|
// EnemyPool #6
|
|
mEnemyPool[6].set[0] = &mEnemyFormation[60];
|
|
mEnemyPool[6].set[1] = &mEnemyFormation[11];
|
|
mEnemyPool[6].set[2] = &mEnemyFormation[62];
|
|
mEnemyPool[6].set[3] = &mEnemyFormation[13];
|
|
mEnemyPool[6].set[4] = &mEnemyFormation[64];
|
|
mEnemyPool[6].set[5] = &mEnemyFormation[15];
|
|
mEnemyPool[6].set[6] = &mEnemyFormation[66];
|
|
mEnemyPool[6].set[7] = &mEnemyFormation[17];
|
|
mEnemyPool[6].set[8] = &mEnemyFormation[68];
|
|
mEnemyPool[6].set[9] = &mEnemyFormation[19];
|
|
|
|
// EnemyPool #7
|
|
mEnemyPool[7].set[0] = &mEnemyFormation[20];
|
|
mEnemyPool[7].set[1] = &mEnemyFormation[21];
|
|
mEnemyPool[7].set[2] = &mEnemyFormation[22];
|
|
mEnemyPool[7].set[3] = &mEnemyFormation[23];
|
|
mEnemyPool[7].set[4] = &mEnemyFormation[24];
|
|
mEnemyPool[7].set[5] = &mEnemyFormation[65];
|
|
mEnemyPool[7].set[6] = &mEnemyFormation[66];
|
|
mEnemyPool[7].set[7] = &mEnemyFormation[67];
|
|
mEnemyPool[7].set[8] = &mEnemyFormation[68];
|
|
mEnemyPool[7].set[9] = &mEnemyFormation[69];
|
|
|
|
// EnemyPool #8
|
|
mEnemyPool[8].set[0] = &mEnemyFormation[70];
|
|
mEnemyPool[8].set[1] = &mEnemyFormation[71];
|
|
mEnemyPool[8].set[2] = &mEnemyFormation[72];
|
|
mEnemyPool[8].set[3] = &mEnemyFormation[73];
|
|
mEnemyPool[8].set[4] = &mEnemyFormation[74];
|
|
mEnemyPool[8].set[5] = &mEnemyFormation[15];
|
|
mEnemyPool[8].set[6] = &mEnemyFormation[16];
|
|
mEnemyPool[8].set[7] = &mEnemyFormation[17];
|
|
mEnemyPool[8].set[8] = &mEnemyFormation[18];
|
|
mEnemyPool[8].set[9] = &mEnemyFormation[19];
|
|
|
|
// EnemyPool #9
|
|
mEnemyPool[9].set[0] = &mEnemyFormation[20];
|
|
mEnemyPool[9].set[1] = &mEnemyFormation[21];
|
|
mEnemyPool[9].set[2] = &mEnemyFormation[22];
|
|
mEnemyPool[9].set[3] = &mEnemyFormation[23];
|
|
mEnemyPool[9].set[4] = &mEnemyFormation[24];
|
|
mEnemyPool[9].set[5] = &mEnemyFormation[70];
|
|
mEnemyPool[9].set[6] = &mEnemyFormation[71];
|
|
mEnemyPool[9].set[7] = &mEnemyFormation[72];
|
|
mEnemyPool[9].set[8] = &mEnemyFormation[73];
|
|
mEnemyPool[9].set[9] = &mEnemyFormation[74];
|
|
}
|
|
|
|
// Inicializa las fases del juego
|
|
void GameDirector::initGameStages()
|
|
{
|
|
// STAGE 1
|
|
mGame.stage[0].number = 1;
|
|
mGame.stage[0].currentPower = 0;
|
|
mGame.stage[0].powerToComplete = 200;
|
|
mGame.stage[0].minMenace = 7 + (4 * 1);
|
|
mGame.stage[0].maxMenace = 7 + (4 * 3);
|
|
mGame.stage[0].enemyPool = &mEnemyPool[0];
|
|
|
|
// STAGE 2
|
|
mGame.stage[1].number = 2;
|
|
mGame.stage[1].currentPower = 0;
|
|
mGame.stage[1].powerToComplete = 300;
|
|
mGame.stage[1].minMenace = 7 + (4 * 2);
|
|
mGame.stage[1].maxMenace = 7 + (4 * 4);
|
|
mGame.stage[1].enemyPool = &mEnemyPool[1];
|
|
|
|
// STAGE 3
|
|
mGame.stage[2].number = 3;
|
|
mGame.stage[2].currentPower = 0;
|
|
mGame.stage[2].powerToComplete = 600;
|
|
mGame.stage[2].minMenace = 7 + (4 * 3);
|
|
mGame.stage[2].maxMenace = 7 + (4 * 6);
|
|
mGame.stage[2].enemyPool = &mEnemyPool[2];
|
|
|
|
// STAGE 4
|
|
mGame.stage[3].number = 4;
|
|
mGame.stage[3].currentPower = 0;
|
|
mGame.stage[3].powerToComplete = 600;
|
|
mGame.stage[3].minMenace = 7 + (4 * 3);
|
|
mGame.stage[3].maxMenace = 7 + (4 * 7);
|
|
mGame.stage[3].enemyPool = &mEnemyPool[3];
|
|
|
|
// STAGE 5
|
|
mGame.stage[4].number = 5;
|
|
mGame.stage[4].currentPower = 0;
|
|
mGame.stage[4].powerToComplete = 600;
|
|
mGame.stage[4].minMenace = 7 + (4 * 4);
|
|
mGame.stage[4].maxMenace = 7 + (4 * 8);
|
|
mGame.stage[4].enemyPool = &mEnemyPool[4];
|
|
|
|
// STAGE 6
|
|
mGame.stage[5].number = 6;
|
|
mGame.stage[5].currentPower = 0;
|
|
mGame.stage[5].powerToComplete = 600;
|
|
mGame.stage[5].minMenace = 7 + (4 * 5);
|
|
mGame.stage[5].maxMenace = 7 + (4 * 10);
|
|
mGame.stage[5].enemyPool = &mEnemyPool[5];
|
|
|
|
// STAGE 7
|
|
mGame.stage[6].number = 7;
|
|
mGame.stage[6].currentPower = 0;
|
|
mGame.stage[6].powerToComplete = 650;
|
|
mGame.stage[6].minMenace = 7 + (4 * 6);
|
|
mGame.stage[6].maxMenace = 7 + (4 * 11);
|
|
mGame.stage[6].enemyPool = &mEnemyPool[6];
|
|
|
|
// STAGE 8
|
|
mGame.stage[7].number = 8;
|
|
mGame.stage[7].currentPower = 0;
|
|
mGame.stage[7].powerToComplete = 750;
|
|
mGame.stage[7].minMenace = 7 + (4 * 7);
|
|
mGame.stage[7].maxMenace = 7 + (4 * 12);
|
|
mGame.stage[7].enemyPool = &mEnemyPool[7];
|
|
|
|
// STAGE 9
|
|
mGame.stage[8].number = 9;
|
|
mGame.stage[8].currentPower = 0;
|
|
mGame.stage[8].powerToComplete = 850;
|
|
mGame.stage[8].minMenace = 7 + (4 * 8);
|
|
mGame.stage[8].maxMenace = 7 + (4 * 13);
|
|
mGame.stage[8].enemyPool = &mEnemyPool[8];
|
|
|
|
// STAGE 10
|
|
mGame.stage[9].number = 10;
|
|
mGame.stage[9].currentPower = 0;
|
|
mGame.stage[9].powerToComplete = 950;
|
|
mGame.stage[9].minMenace = 7 + (4 * 9);
|
|
mGame.stage[9].maxMenace = 7 + (4 * 15);
|
|
mGame.stage[9].enemyPool = &mEnemyPool[9];
|
|
}
|
|
|
|
// Crea una formación de enemigos
|
|
void GameDirector::deployEnemyFormation()
|
|
{
|
|
// Solo despliega una formación enemiga si ha pasado cierto tiempo desde la última
|
|
if (mGame.enemyDeployCounter == 0)
|
|
{
|
|
mGame.enemyDeployCounter = 255;
|
|
|
|
Uint8 set = (rand() % 10);
|
|
|
|
if (set == mGame.lastEnemyDeploy)
|
|
{
|
|
set++;
|
|
set %= 10;
|
|
}
|
|
mGame.lastEnemyDeploy = set;
|
|
|
|
if (mDebug.enabled)
|
|
set = mDebug.enemySet;
|
|
|
|
Uint8 numEnemies = mGame.stage[mGame.currentStage].enemyPool->set[set]->numberOfEnemies;
|
|
for (Uint8 i = 0; i < numEnemies; i++)
|
|
createNewBalloon(mGame.stage[mGame.currentStage].enemyPool->set[set]->init[i].x,
|
|
mGame.stage[mGame.currentStage].enemyPool->set[set]->init[i].y,
|
|
mGame.stage[mGame.currentStage].enemyPool->set[set]->init[i].kind,
|
|
mGame.stage[mGame.currentStage].enemyPool->set[set]->init[i].velX,
|
|
mGame.enemySpeed,
|
|
mGame.stage[mGame.currentStage].enemyPool->set[set]->init[i].creationCounter,
|
|
mTexture[TEXTURE_BALLOON].texture);
|
|
}
|
|
}
|
|
|
|
// Aumenta el poder de la fase
|
|
void GameDirector::increaseStageCurrentPower()
|
|
{
|
|
mGame.stage[mGame.currentStage].currentPower++;
|
|
}
|
|
|
|
// Establece el valor de la variable
|
|
void GameDirector::setScore(Uint32 score)
|
|
{
|
|
mGame.score = score;
|
|
}
|
|
|
|
// Establece el valor de la variable
|
|
void GameDirector::setHiScore(Uint32 score)
|
|
{
|
|
mGame.hiScore = score;
|
|
}
|
|
|
|
// Actualiza el valor de HiScore en caso necesario
|
|
void GameDirector::updateHiScore()
|
|
{
|
|
// La puntuación es mayor que la máxima puntuación
|
|
if (mGame.score > mGame.hiScore)
|
|
{
|
|
// Actualiza la máxima puntuación
|
|
mGame.hiScore = mGame.score;
|
|
|
|
// Almacena la máxima puntuación en el fichero junto con un checksum
|
|
mGame.scoreDataFile[0] = mGame.hiScore;
|
|
mGame.scoreDataFile[1] = mGame.hiScore % 43;
|
|
|
|
// Si superamos la máxima puntuación
|
|
if (mGame.hiScoreAchieved == false)
|
|
{
|
|
mGame.hiScoreAchieved = true;
|
|
JA_PlaySound(mSound[SOUND_HISCORE].sound);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Transforma un valor numérico en una cadena de 6 cifras
|
|
std::string GameDirector::updateScoreText(Uint32 num)
|
|
{
|
|
return (std::to_string(num));
|
|
|
|
if ((num >= 0) && (num <= 9))
|
|
{
|
|
return ("000000" + std::to_string(num));
|
|
}
|
|
|
|
if ((num >= 10) && (num <= 99))
|
|
{
|
|
return ("00000" + std::to_string(num));
|
|
}
|
|
|
|
if ((num >= 100) && (num <= 999))
|
|
{
|
|
return ("0000" + std::to_string(num));
|
|
}
|
|
|
|
if ((num >= 1000) && (num <= 9999))
|
|
{
|
|
return ("000" + std::to_string(num));
|
|
}
|
|
|
|
if ((num >= 010000) && (num <= 99999))
|
|
{
|
|
return ("00" + std::to_string(num));
|
|
}
|
|
|
|
if ((num >= 100000) && (num <= 999999))
|
|
{
|
|
return ("0" + std::to_string(num));
|
|
}
|
|
|
|
if ((num >= 1000000) && (num <= 9999999))
|
|
{
|
|
return (std::to_string(num));
|
|
}
|
|
|
|
return (std::to_string(num));
|
|
}
|
|
|
|
// Pinta el marcador en pantalla usando un objeto texto
|
|
void GameDirector::renderScoreBoard()
|
|
{
|
|
// Si el jugador esta muerto, no pintes el fondo del marcador, así que pase por encima cuando sale despedido
|
|
if (mGame.player->isAlive())
|
|
mGame.scoreBoard->render();
|
|
|
|
if (!mDemo.enabled)
|
|
{
|
|
// SCORE
|
|
mText.white->writeCentered(PLAY_AREA_CENTER_FIRST_QUARTER_X, SCORE_WORD_Y - 6, "SCORE", 0);
|
|
mText.white->writeCentered(PLAY_AREA_CENTER_FIRST_QUARTER_X, SCORE_NUMBER_Y - 6, updateScoreText(mGame.score), 0);
|
|
|
|
// HI-SCORE
|
|
mText.white->writeCentered(PLAY_AREA_CENTER_THIRD_QUARTER_X, HISCORE_WORD_Y - 6, "HI-SCORE", 0);
|
|
mText.white->writeCentered(PLAY_AREA_CENTER_THIRD_QUARTER_X, HISCORE_NUMBER_Y - 6, updateScoreText(mGame.hiScore), 0);
|
|
|
|
// MULT
|
|
mText.white->writeColored(MULTIPLIER_WORD_X, MULTIPLIER_WORD_Y - 6, "MULT", 0, 255, 0);
|
|
mText.whiteX2->writeShadowed(PLAY_AREA_CENTER_X - 16, SCORE_WORD_Y + 5, std::to_string(mGame.player->getScoreMultiplier()).substr(0, 1), 0, 192, 0);
|
|
mText.white->writeShadowed(PLAY_AREA_CENTER_X - 2, SCORE_WORD_Y + 12, ".", 0, 192, 0);
|
|
mText.white->writeShadowed(PLAY_AREA_CENTER_X + 4, SCORE_WORD_Y + 12, std::to_string(mGame.player->getScoreMultiplier()).substr(2, 1), 0, 192, 0);
|
|
|
|
// STAGE
|
|
mText.white->writeCentered(PLAY_AREA_CENTER_FIRST_QUARTER_X, SCORE_NUMBER_Y + 4, "STAGE " + std::to_string(mGame.stage[mGame.currentStage].number), 0);
|
|
|
|
// POWER
|
|
mGame.powerMeter->setSpriteClip(256, 184, 40, 8);
|
|
mGame.powerMeter->render();
|
|
float percent = (mGame.stage[mGame.currentStage].currentPower * 40.0f) / mGame.stage[mGame.currentStage].powerToComplete;
|
|
mGame.powerMeter->setSpriteClip(296, 184, (int)percent, 8);
|
|
mGame.powerMeter->render();
|
|
}
|
|
else
|
|
{
|
|
mText.nokia->writeCentered(SCREEN_FIRST_QUARTER_X, SCORE_WORD_Y - 3, "A game by", -1);
|
|
mText.nokia->writeCentered(SCREEN_FIRST_QUARTER_X, SCORE_NUMBER_Y, "JailDesigner", -1);
|
|
mText.nokia->writeCentered(SCREEN_THIRD_QUARTER_X, HISCORE_WORD_Y - 3, "Intro music by", -1);
|
|
mText.nokia->writeCentered(SCREEN_THIRD_QUARTER_X, HISCORE_NUMBER_Y, "JailDoctor", -1);
|
|
}
|
|
}
|
|
|
|
// Actualiza las variables del jugador
|
|
void GameDirector::updatePlayer()
|
|
{
|
|
mGame.player->update();
|
|
|
|
// Comprueba la colisión entre el jugador y los globos
|
|
if (checkPlayerBalloonCollision())
|
|
{
|
|
if (mGame.player->isAlive())
|
|
{
|
|
if (mDemo.enabled)
|
|
setProgSection(PROG_SECTION_TITLE, TITLE_SECTION_INSTRUCTIONS);
|
|
else
|
|
killPlayer();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Actualiza las variables de la fase
|
|
void GameDirector::updateStage()
|
|
{
|
|
if (mGame.stage[mGame.currentStage].currentPower >= mGame.stage[mGame.currentStage].powerToComplete)
|
|
{
|
|
// Cambio de fase
|
|
mGame.currentStage++;
|
|
JA_PlaySound(mSound[SOUND_STAGE_CHANGE].sound);
|
|
mGame.stageBitmapCounter = 0;
|
|
mGame.enemySpeed = BALLOON_SPEED_1;
|
|
setBalloonSpeed(mGame.enemySpeed);
|
|
mGame.effect.flash = true;
|
|
mGame.effect.shake = true;
|
|
}
|
|
|
|
if (mGame.stageBitmapCounter < STAGE_COUNTER)
|
|
{
|
|
mGame.stageBitmapCounter++;
|
|
}
|
|
}
|
|
|
|
// Actualiza el estado de muerte
|
|
void GameDirector::updateDeath()
|
|
{
|
|
if (!mGame.player->isAlive())
|
|
{
|
|
if (mGame.deathCounter > 0)
|
|
{
|
|
mGame.deathCounter--;
|
|
if ((mGame.deathCounter == 250) || (mGame.deathCounter == 200) || (mGame.deathCounter == 180) || (mGame.deathCounter == 120) || (mGame.deathCounter == 60))
|
|
{
|
|
Uint8 sound = rand() % 4;
|
|
switch (sound)
|
|
{
|
|
case 0:
|
|
JA_PlaySound(mSound[SOUND_BUBBLE1].sound, 0);
|
|
break;
|
|
case 1:
|
|
JA_PlaySound(mSound[SOUND_BUBBLE2].sound, 0);
|
|
break;
|
|
case 2:
|
|
JA_PlaySound(mSound[SOUND_BUBBLE3].sound, 0);
|
|
break;
|
|
case 3:
|
|
JA_PlaySound(mSound[SOUND_BUBBLE4].sound, 0);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Animación
|
|
if ((mGame.deathCounter / 5) % 2 == 0)
|
|
{
|
|
mGame.smartSprite[mGame.deathIndex]->setSpriteClip(0, 0, 24, 24);
|
|
}
|
|
else
|
|
{
|
|
mGame.smartSprite[mGame.deathIndex]->setSpriteClip(24, 0, 24, 24);
|
|
}
|
|
|
|
// Rebote en los laterales
|
|
if (mGame.smartSprite[mGame.deathIndex]->getVelX() > 0)
|
|
{
|
|
if (mGame.smartSprite[mGame.deathIndex]->getPosX() > (SCREEN_WIDTH - mGame.smartSprite[mGame.deathIndex]->getWidth()))
|
|
{
|
|
mGame.smartSprite[mGame.deathIndex]->setPosX(SCREEN_WIDTH - mGame.smartSprite[mGame.deathIndex]->getWidth());
|
|
mGame.smartSprite[mGame.deathIndex]->setVelX(mGame.smartSprite[mGame.deathIndex]->getVelX() * (-1));
|
|
mGame.smartSprite[mGame.deathIndex]->setDestX(mGame.smartSprite[mGame.deathIndex]->getDestX() * (-1));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (mGame.smartSprite[mGame.deathIndex]->getPosX() < 0)
|
|
{
|
|
mGame.smartSprite[mGame.deathIndex]->setPosX(0);
|
|
mGame.smartSprite[mGame.deathIndex]->setVelX(mGame.smartSprite[mGame.deathIndex]->getVelX() * (-1));
|
|
mGame.smartSprite[mGame.deathIndex]->setDestX(mGame.smartSprite[mGame.deathIndex]->getDestX() * (-1));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mGame.section = GAME_SECTION_GAMEOVER;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Renderiza el fade final cuando se acaba la partida
|
|
void GameDirector::renderDeathFade()
|
|
{
|
|
if (!mGame.player->isAlive() && (mGame.deathCounter < 150))
|
|
{
|
|
// 192 / 6 = 32, 6 cuadrados de 32 pixeles
|
|
SDL_Rect rect[12];
|
|
Uint8 h = (150 - mGame.deathCounter) / 3;
|
|
SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 255);
|
|
for (Uint8 i = 0; i < 12; i++)
|
|
{
|
|
rect[i].x = 0;
|
|
rect[i].y = i * 16;
|
|
rect[i].w = SCREEN_WIDTH;
|
|
if (i == 0)
|
|
rect[i].h = h;
|
|
else
|
|
rect[i].h = std::max(rect[i - 1].h - 3, 0);
|
|
SDL_RenderFillRect(mRenderer, &rect[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Actualiza los globos
|
|
void GameDirector::updateBalloons()
|
|
{
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
mGame.balloon[i]->update();
|
|
}
|
|
|
|
// Pinta en pantalla todos los globos activos
|
|
void GameDirector::renderBalloons()
|
|
{
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
{
|
|
mGame.balloon[i]->render();
|
|
if ((mDebug.enabled) && (mGame.balloon[i]->isPopping() == false))
|
|
mText.white->writeCentered(mGame.balloon[i]->getPosX() + (mGame.balloon[i]->getWidth() / 2), mGame.balloon[i]->getPosY() - 8, std::to_string(i), 0);
|
|
}
|
|
}
|
|
|
|
// Devuelve el primer indice no activo del vector de globos
|
|
Uint8 GameDirector::getBalloonFreeIndex()
|
|
{
|
|
Uint8 index = 0;
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
if (!mGame.balloon[i]->isEnabled())
|
|
{
|
|
index = i;
|
|
break;
|
|
}
|
|
return index;
|
|
}
|
|
|
|
// Crea un globo nuevo en el vector de globos
|
|
Uint8 GameDirector::createNewBalloon(float x, int y, Uint8 kind, float velx, float speed, Uint16 creationtimer, LTexture *texture)
|
|
{
|
|
Uint8 index = getBalloonFreeIndex();
|
|
mGame.balloon[index]->init(x, y, kind, velx, speed, creationtimer, texture, mRenderer);
|
|
return index;
|
|
}
|
|
|
|
// Crea una PowerBall
|
|
void GameDirector::createPowerBall()
|
|
{
|
|
const int y4 = (PLAY_AREA_TOP - BLOCK);
|
|
const int x4_0 = PLAY_AREA_LEFT;
|
|
const int x4_50 = PLAY_AREA_CENTER_X - (BALLOON_SIZE_4 / 2);
|
|
const int x4_100 = (PLAY_AREA_RIGHT)-BALLOON_SIZE_4;
|
|
const int x[3] = {x4_0, x4_50, x4_100};
|
|
int x4 = x[rand() % 3];
|
|
|
|
mGame.balloon[getBalloonFreeIndex()]->init(x4, y4, POWER_BALL, BALLOON_VELX_POSITIVE * (((rand() % 2) * 2) - 1), mGame.enemySpeed, 350, mTexture[TEXTURE_BALLOON].texture, mRenderer);
|
|
}
|
|
|
|
// Establece a cero todos los valores del vector de objetos globo
|
|
void GameDirector::resetBalloons()
|
|
{
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
{
|
|
mGame.balloon[i]->disable();
|
|
}
|
|
}
|
|
|
|
// Establece la velocidad de los globos
|
|
void GameDirector::setBalloonSpeed(float speed)
|
|
{
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
{
|
|
if (mGame.balloon[i]->isEnabled())
|
|
mGame.balloon[i]->setSpeed(speed);
|
|
}
|
|
}
|
|
|
|
// Incrementa la velocidad de los globos
|
|
void GameDirector::incBalloonSpeed()
|
|
{
|
|
if (mGame.enemySpeed == BALLOON_SPEED_1)
|
|
mGame.enemySpeed = BALLOON_SPEED_2;
|
|
else if (mGame.enemySpeed == BALLOON_SPEED_2)
|
|
mGame.enemySpeed = BALLOON_SPEED_3;
|
|
else if (mGame.enemySpeed == BALLOON_SPEED_3)
|
|
mGame.enemySpeed = BALLOON_SPEED_4;
|
|
else if (mGame.enemySpeed == BALLOON_SPEED_4)
|
|
mGame.enemySpeed = BALLOON_SPEED_5;
|
|
setBalloonSpeed(mGame.enemySpeed);
|
|
}
|
|
|
|
// Decrementa la velocidad de los globos
|
|
void GameDirector::decBalloonSpeed()
|
|
{
|
|
if (mGame.enemySpeed == BALLOON_SPEED_5)
|
|
mGame.enemySpeed = BALLOON_SPEED_4;
|
|
else if (mGame.enemySpeed == BALLOON_SPEED_4)
|
|
mGame.enemySpeed = BALLOON_SPEED_3;
|
|
else if (mGame.enemySpeed == BALLOON_SPEED_3)
|
|
mGame.enemySpeed = BALLOON_SPEED_2;
|
|
else if (mGame.enemySpeed == BALLOON_SPEED_2)
|
|
mGame.enemySpeed = BALLOON_SPEED_1;
|
|
setBalloonSpeed(mGame.enemySpeed);
|
|
}
|
|
|
|
// Actualiza la velocidad de los globos en funcion del poder acumulado de la fase
|
|
void GameDirector::updateBalloonSpeed()
|
|
{
|
|
float percent = (float)mGame.stage[mGame.currentStage].currentPower / (float)mGame.stage[mGame.currentStage].powerToComplete;
|
|
if (mGame.enemySpeed == BALLOON_SPEED_1)
|
|
{
|
|
if (percent > 0.2f)
|
|
incBalloonSpeed();
|
|
}
|
|
else if (mGame.enemySpeed == BALLOON_SPEED_2)
|
|
{
|
|
if (percent > 0.4f)
|
|
incBalloonSpeed();
|
|
}
|
|
else if (mGame.enemySpeed == BALLOON_SPEED_3)
|
|
{
|
|
if (percent > 0.6f)
|
|
incBalloonSpeed();
|
|
}
|
|
else if (mGame.enemySpeed == BALLOON_SPEED_4)
|
|
{
|
|
if (percent > 0.8f)
|
|
incBalloonSpeed();
|
|
}
|
|
}
|
|
|
|
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
|
|
void GameDirector::popBalloon(Uint8 index)
|
|
{
|
|
//if (mGame.balloon[index]->isActive())
|
|
{
|
|
// Otorga los puntos correspondientes al globo
|
|
mGame.player->addScore(Uint32(mGame.balloon[index]->getScore() * mGame.player->getScoreMultiplier()));
|
|
setScore(mGame.player->getScore());
|
|
updateHiScore();
|
|
|
|
// Aumenta el poder de la fase
|
|
increaseStageCurrentPower();
|
|
mGame.balloonsPopped++;
|
|
|
|
Uint8 kind = mGame.balloon[index]->getKind();
|
|
Uint8 freeIndex = 0;
|
|
switch (kind)
|
|
{
|
|
// Si es del tipo más pequeño, simplemente elimina el globo
|
|
case BALLOON_1:
|
|
mGame.balloon[index]->pop();
|
|
break;
|
|
|
|
case HEXAGON_1:
|
|
mGame.balloon[index]->pop();
|
|
break;
|
|
|
|
// Si es del tipo PowerBall, destruye todos los globos
|
|
case POWER_BALL:
|
|
destroyAllBalloons();
|
|
break;
|
|
|
|
// En cualquier otro caso, crea dos globos de un tipo inferior
|
|
default:
|
|
freeIndex = getBalloonFreeIndex();
|
|
mGame.balloon[freeIndex]->init(0, mGame.balloon[index]->getPosY(), mGame.balloon[index]->getKind() - 1, BALLOON_VELX_NEGATIVE, mGame.enemySpeed, 0, mTexture[TEXTURE_BALLOON].texture, mRenderer);
|
|
mGame.balloon[freeIndex]->allignTo(mGame.balloon[index]->getPosX() + (mGame.balloon[index]->getWidth() / 2));
|
|
if (mGame.balloon[freeIndex]->getClass() == BALLOON_CLASS)
|
|
mGame.balloon[freeIndex]->setVelY(-2.50f);
|
|
else if (mGame.balloon[freeIndex]->getClass() == HEXAGON_CLASS)
|
|
mGame.balloon[freeIndex]->setVelY(BALLOON_VELX_NEGATIVE);
|
|
|
|
freeIndex = getBalloonFreeIndex();
|
|
mGame.balloon[freeIndex]->init(0, mGame.balloon[index]->getPosY(), mGame.balloon[index]->getKind() - 1, BALLOON_VELX_POSITIVE, mGame.enemySpeed, 0, mTexture[TEXTURE_BALLOON].texture, mRenderer);
|
|
mGame.balloon[freeIndex]->allignTo(mGame.balloon[index]->getPosX() + (mGame.balloon[index]->getWidth() / 2));
|
|
if (mGame.balloon[freeIndex]->getClass() == BALLOON_CLASS)
|
|
mGame.balloon[freeIndex]->setVelY(-2.50f);
|
|
else if (mGame.balloon[freeIndex]->getClass() == HEXAGON_CLASS)
|
|
mGame.balloon[freeIndex]->setVelY(BALLOON_VELX_NEGATIVE);
|
|
|
|
// Elimina el globo
|
|
mGame.balloon[index]->pop();
|
|
break;
|
|
}
|
|
|
|
// Recalcula el nivel de amenaza
|
|
setMenace();
|
|
}
|
|
}
|
|
|
|
// Explosiona un globo. Lo destruye
|
|
void GameDirector::destroyBalloon(Uint8 index)
|
|
{
|
|
//if (mGame.balloon[index]->isActive())
|
|
{
|
|
// Otorga los puntos correspondientes al globo
|
|
mGame.player->addScore(Uint32(mGame.balloon[index]->getScore() * mGame.player->getScoreMultiplier()));
|
|
setScore(mGame.player->getScore());
|
|
updateHiScore();
|
|
|
|
// Aumenta el poder de la fase
|
|
increaseStageCurrentPower();
|
|
mGame.balloonsPopped++;
|
|
|
|
// Destruye el globo
|
|
mGame.balloon[index]->pop();
|
|
|
|
// Recalcula el nivel de amenaza
|
|
setMenace();
|
|
}
|
|
}
|
|
|
|
// Explosiona todos los globos
|
|
void GameDirector::popAllBalloons()
|
|
{
|
|
int candidate[MAX_BALLOONS];
|
|
Uint8 j = 0;
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
{
|
|
if ((mGame.balloon[i]->isEnabled()) && (!mGame.balloon[i]->isPopping()) && (!mGame.balloon[i]->isBeingCreated()))
|
|
candidate[j] = i;
|
|
else
|
|
candidate[j] = -1;
|
|
j++;
|
|
}
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
if (candidate[i] >= 0)
|
|
popBalloon(i);
|
|
JA_PlaySound(mSound[SOUND_BALLOON].sound);
|
|
}
|
|
|
|
// Destruye todos los globos
|
|
void GameDirector::destroyAllBalloons()
|
|
{
|
|
int candidate[MAX_BALLOONS];
|
|
Uint8 j = 0;
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
{
|
|
if ((mGame.balloon[i]->isEnabled()) && (!mGame.balloon[i]->isPopping()) && (!mGame.balloon[i]->isBeingCreated()))
|
|
candidate[j] = i;
|
|
else
|
|
candidate[j] = -1;
|
|
j++;
|
|
}
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
if (candidate[i] >= 0)
|
|
destroyBalloon(i);
|
|
JA_PlaySound(mSound[SOUND_BALLOON].sound);
|
|
mGame.effect.flash = true;
|
|
mGame.effect.shake = true;
|
|
}
|
|
|
|
// Detiene todos los globos
|
|
void GameDirector::stopAllBalloons(Uint16 time)
|
|
{
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
if (mGame.balloon[i]->isEnabled())
|
|
{
|
|
mGame.balloon[i]->setStop(true);
|
|
mGame.balloon[i]->setStoppedTimer(time);
|
|
}
|
|
}
|
|
|
|
// Pone en marcha todos los globos
|
|
void GameDirector::startAllBalloons()
|
|
{
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
if ((mGame.balloon[i]->isEnabled()) && (!mGame.balloon[i]->isBeingCreated()))
|
|
{
|
|
mGame.balloon[i]->setStop(false);
|
|
mGame.balloon[i]->setStoppedTimer(0);
|
|
}
|
|
}
|
|
|
|
// Obtiene el numero de globos activos
|
|
Uint8 GameDirector::countBalloons()
|
|
{
|
|
Uint8 num = 0;
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
if (mGame.balloon[i]->isEnabled())
|
|
if (!mGame.balloon[i]->isPopping())
|
|
num++;
|
|
return num;
|
|
}
|
|
|
|
// Comprueba la colisión entre el jugador y los globos activos
|
|
bool GameDirector::checkPlayerBalloonCollision()
|
|
|
|
{
|
|
bool result = false;
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
{
|
|
if ((mGame.balloon[i]->isEnabled()) && !(mGame.balloon[i]->isStopped()) && !(mGame.balloon[i]->isInvulnerable()))
|
|
if (checkCollision(mGame.player->getCollider(), mGame.balloon[i]->getCollider()))
|
|
{
|
|
result = true;
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// Comprueba la colisión entre el jugador y los items
|
|
void GameDirector::checkPlayerItemCollision()
|
|
{
|
|
if (mGame.player->isAlive())
|
|
for (Uint8 i = 0; i < MAX_ITEMS; i++)
|
|
{
|
|
if (mGame.item[i]->isEnabled())
|
|
{
|
|
if (checkCollision(mGame.player->getCollider(), mGame.item[i]->getCollider()))
|
|
{
|
|
switch (mGame.item[i]->getClass())
|
|
{
|
|
case ITEM_POINTS_1_DISK:
|
|
mGame.player->addScore(1000);
|
|
setScore(mGame.player->getScore());
|
|
updateHiScore();
|
|
createItemScoreSprite(mGame.item[i]->getPosX() + (mGame.item[i]->getWidth() / 2) - (mGame._1000Bitmap->getWidth() / 2), mGame.player->getPosY(), mGame._1000Bitmap);
|
|
JA_PlaySound(mSound[SOUND_ITEM_PICKUP].sound);
|
|
break;
|
|
case ITEM_POINTS_2_GAVINA:
|
|
mGame.player->addScore(2500);
|
|
setScore(mGame.player->getScore());
|
|
updateHiScore();
|
|
createItemScoreSprite(mGame.item[i]->getPosX() + (mGame.item[i]->getWidth() / 2) - (mGame._2500Bitmap->getWidth() / 2), mGame.player->getPosY(), mGame._2500Bitmap);
|
|
JA_PlaySound(mSound[SOUND_ITEM_PICKUP].sound);
|
|
break;
|
|
case ITEM_POINTS_3_PACMAR:
|
|
mGame.player->addScore(5000);
|
|
setScore(mGame.player->getScore());
|
|
updateHiScore();
|
|
createItemScoreSprite(mGame.item[i]->getPosX() + (mGame.item[i]->getWidth() / 2) - (mGame._5000Bitmap->getWidth() / 2), mGame.player->getPosY(), mGame._5000Bitmap);
|
|
JA_PlaySound(mSound[SOUND_ITEM_PICKUP].sound);
|
|
break;
|
|
case ITEM_CLOCK:
|
|
enableTimeStopItem();
|
|
JA_PlaySound(mSound[SOUND_ITEM_PICKUP].sound);
|
|
break;
|
|
case ITEM_TNT:
|
|
popAllBalloons();
|
|
setExplosionTime(true);
|
|
JA_PlaySound(mSound[SOUND_TITLE].sound);
|
|
break;
|
|
case ITEM_COFFEE:
|
|
mGame.player->giveExtraHit();
|
|
JA_PlaySound(mSound[SOUND_ITEM_PICKUP].sound);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
mGame.item[i]->erase();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Comprueba y procesa la colisión entre las balas y los globos
|
|
void GameDirector::checkBulletBalloonCollision()
|
|
{
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
for (Uint8 j = 0; j < MAX_BULLETS; j++)
|
|
if (mGame.balloon[i]->isEnabled() && (!mGame.balloon[i]->isInvulnerable()) && mGame.bullet[j]->isActive())
|
|
if (checkCollision(mGame.balloon[i]->getCollider(), mGame.bullet[j]->getCollider()))
|
|
{
|
|
mGame.player->incScoreMultiplier();
|
|
popBalloon(i);
|
|
if (!mDemo.enabled)
|
|
JA_PlaySound(mSound[SOUND_BALLOON].sound);
|
|
mGame.bullet[j]->erase();
|
|
setMenace();
|
|
Uint8 droppeditem = dropItem();
|
|
if ((droppeditem != NO_KIND) && !(mDemo.enabled) && !(mDemo.recording))
|
|
{
|
|
if (droppeditem == ITEM_POWER_BALL)
|
|
{
|
|
createPowerBall();
|
|
}
|
|
else
|
|
{
|
|
createItem(mGame.balloon[i]->getPosX(), mGame.balloon[i]->getPosY(), droppeditem);
|
|
JA_PlaySound(mSound[SOUND_ITEM_DROP].sound);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Mueve las balas activas
|
|
void GameDirector::moveBullets()
|
|
{
|
|
for (Uint8 i = 0; i < MAX_BULLETS; i++)
|
|
{
|
|
if (mGame.bullet[i]->isActive())
|
|
{
|
|
if (mGame.bullet[i]->move() == MSG_BULLET_OUT)
|
|
{
|
|
mGame.player->decScoreMultiplier();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Pinta las balas activas
|
|
void GameDirector::renderBullets()
|
|
{
|
|
for (Uint8 i = 0; i < MAX_BULLETS; i++)
|
|
{
|
|
if (mGame.bullet[i]->isActive())
|
|
{
|
|
mGame.bullet[i]->render();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Devuelve el primer indice no activo del vector de balas
|
|
Uint8 GameDirector::getBulletFreeIndex()
|
|
{
|
|
Uint8 index = 0;
|
|
|
|
for (int i = 0; i < MAX_BULLETS; i++)
|
|
{
|
|
if (mGame.bullet[i]->isActive() == false)
|
|
{
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
// Establece a cero todos los valores del vector de objetos bala
|
|
void GameDirector::resetBullets()
|
|
{
|
|
for (Uint8 i = 0; i < MAX_BULLETS; i++)
|
|
{
|
|
mGame.bullet[i]->erase();
|
|
}
|
|
}
|
|
|
|
// Crea un objeto bala
|
|
void GameDirector::createBullet(int x, int y, Uint8 kind)
|
|
{
|
|
mGame.bullet[getBulletFreeIndex()]->init(x, y, kind, mTexture[TEXTURE_BULLET].texture, mRenderer);
|
|
}
|
|
|
|
// Actualiza los items
|
|
void GameDirector::updateItems()
|
|
{
|
|
for (Uint8 i = 0; i < MAX_ITEMS; i++)
|
|
{
|
|
mGame.item[i]->update();
|
|
}
|
|
}
|
|
|
|
// Pinta los items activos
|
|
void GameDirector::renderItems()
|
|
{
|
|
for (Uint8 i = 0; i < MAX_ITEMS; i++)
|
|
{
|
|
mGame.item[i]->render();
|
|
}
|
|
}
|
|
|
|
// Devuelve el primer indice no activo del vector de items
|
|
Uint8 GameDirector::getItemFreeIndex()
|
|
{
|
|
Uint8 index = 0;
|
|
|
|
for (int i = 0; i < MAX_ITEMS; i++)
|
|
{
|
|
if (mGame.item[i]->getClass() == NO_KIND)
|
|
{
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
// Establece a cero todos los valores del vector de objetos item
|
|
void GameDirector::resetItems()
|
|
{
|
|
for (Uint8 i = 0; i < MAX_ITEMS; i++)
|
|
{
|
|
mGame.item[i]->erase();
|
|
}
|
|
}
|
|
|
|
// Devuelve un item en función del azar
|
|
Uint8 GameDirector::dropItem()
|
|
{
|
|
//return ITEM_COFFEE;
|
|
|
|
Uint8 luckyNumber = rand() % 99;
|
|
Uint8 item = rand() % 7;
|
|
switch (item)
|
|
{
|
|
case 0:
|
|
if (luckyNumber < 10)
|
|
return ITEM_POINTS_1_DISK;
|
|
break;
|
|
case 1:
|
|
if (luckyNumber < 6)
|
|
return ITEM_POINTS_2_GAVINA;
|
|
break;
|
|
case 2:
|
|
if (luckyNumber < 3)
|
|
return ITEM_POINTS_3_PACMAR;
|
|
break;
|
|
case 3:
|
|
if (luckyNumber < 5)
|
|
return ITEM_CLOCK;
|
|
break;
|
|
case 4:
|
|
if (luckyNumber < 5)
|
|
return NO_KIND;
|
|
break;
|
|
case 5:
|
|
if (luckyNumber < 5)
|
|
return ITEM_COFFEE;
|
|
break;
|
|
case 6:
|
|
if (luckyNumber < 5)
|
|
if (countBalloons() > 10)
|
|
return ITEM_POWER_BALL;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return NO_KIND;
|
|
}
|
|
|
|
// Crea un objeto item
|
|
void GameDirector::createItem(int x, int y, Uint8 kind)
|
|
{
|
|
mGame.item[getItemFreeIndex()]->init(kind, x, y, mTexture[TEXTURE_ITEMS].texture, mRenderer);
|
|
}
|
|
|
|
// Crea un objeto SmartSprite para mostrar la puntuación al coger un objeto
|
|
void GameDirector::createItemScoreSprite(int x, int y, SmartSprite *sprite)
|
|
{
|
|
Uint8 index = getSmartSpriteFreeIndex();
|
|
*mGame.smartSprite[index] = *sprite;
|
|
mGame.smartSprite[index]->setPosX(x);
|
|
mGame.smartSprite[index]->setPosY(y);
|
|
mGame.smartSprite[index]->setDestX(x);
|
|
mGame.smartSprite[index]->setDestY(y - 15);
|
|
mGame.smartSprite[index]->setEnabled(true);
|
|
mGame.smartSprite[index]->setEnabledTimer(100);
|
|
}
|
|
|
|
// Crea un objeto de bonus en función del azar
|
|
void GameDirector::dropBonus()
|
|
{
|
|
}
|
|
|
|
// Dibuja el efecto de flash
|
|
void GameDirector::renderFlashEffect()
|
|
{
|
|
if (mGame.effect.flash)
|
|
{
|
|
// Pantallazo blanco
|
|
SDL_SetRenderDrawColor(mRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
|
|
SDL_RenderClear(mRenderer);
|
|
|
|
mGame.effect.flash = false;
|
|
}
|
|
}
|
|
|
|
// Actualiza el efecto de agitar la pantalla
|
|
void GameDirector::updateShakeEffect()
|
|
{
|
|
if (mGame.effect.shake)
|
|
{
|
|
if (mGame.effect.shakeCounter > 0)
|
|
mGame.effect.shakeCounter--;
|
|
else
|
|
mGame.effect.shake = false;
|
|
}
|
|
}
|
|
|
|
// Crea un SmartSprite para arrojar el item café al recibir un impacto
|
|
void GameDirector::throwCoffee(int x, int y)
|
|
{
|
|
Uint8 index = getSmartSpriteFreeIndex();
|
|
mGame.smartSprite[index]->init(mTexture[TEXTURE_ITEMS].texture, mRenderer);
|
|
mGame.smartSprite[index]->setPosX(x - 8);
|
|
mGame.smartSprite[index]->setPosY(y - 8);
|
|
mGame.smartSprite[index]->setWidth(16);
|
|
mGame.smartSprite[index]->setHeight(16);
|
|
mGame.smartSprite[index]->setVelX(-1.0f + ((rand() % 5) * 0.5f));
|
|
mGame.smartSprite[index]->setVelY(-4.0f);
|
|
mGame.smartSprite[index]->setAccelX(0.0f);
|
|
mGame.smartSprite[index]->setAccelY(0.2f);
|
|
mGame.smartSprite[index]->setDestX(x + (mGame.smartSprite[index]->getVelX() * 50));
|
|
mGame.smartSprite[index]->setDestY(SCREEN_HEIGHT + 1);
|
|
mGame.smartSprite[index]->setEnabled(true);
|
|
mGame.smartSprite[index]->setEnabledTimer(1);
|
|
mGame.smartSprite[index]->setSpriteClip(80, 16, 16, 16);
|
|
}
|
|
|
|
// Crea un SmartSprite para arrojar el item café al recibir un impacto
|
|
void GameDirector::throwPlayer(int x, int y)
|
|
{
|
|
int sentit = ((rand() % 2) ? 1 : -1);
|
|
mGame.deathIndex = getSmartSpriteFreeIndex();
|
|
mGame.smartSprite[mGame.deathIndex]->init(mTexture[TEXTURE_PLAYER_DEATH].texture, mRenderer);
|
|
mGame.smartSprite[mGame.deathIndex]->setPosX(x);
|
|
mGame.smartSprite[mGame.deathIndex]->setPosY(y);
|
|
mGame.smartSprite[mGame.deathIndex]->setWidth(24);
|
|
mGame.smartSprite[mGame.deathIndex]->setHeight(24);
|
|
mGame.smartSprite[mGame.deathIndex]->setVelX(2.0f * sentit);
|
|
mGame.smartSprite[mGame.deathIndex]->setVelY(-5.0f);
|
|
mGame.smartSprite[mGame.deathIndex]->setAccelX(0.0f);
|
|
mGame.smartSprite[mGame.deathIndex]->setAccelY(0.2f);
|
|
mGame.smartSprite[mGame.deathIndex]->setDestX(SCREEN_WIDTH * sentit);
|
|
mGame.smartSprite[mGame.deathIndex]->setDestY(SCREEN_HEIGHT + 1);
|
|
mGame.smartSprite[mGame.deathIndex]->setEnabled(true);
|
|
mGame.smartSprite[mGame.deathIndex]->setEnabledTimer(1);
|
|
mGame.smartSprite[mGame.deathIndex]->setSpriteClip(0, 0, 24, 24);
|
|
}
|
|
|
|
// Actualiza los SmartSprites
|
|
void GameDirector::updateSmartSprites()
|
|
{
|
|
for (int i = 0; i < MAX_SMART_SPRITES; i++)
|
|
{
|
|
mGame.smartSprite[i]->update();
|
|
}
|
|
}
|
|
|
|
// Pinta los SmartSprites activos
|
|
void GameDirector::renderSmartSprites()
|
|
{
|
|
for (int i = 0; i < MAX_SMART_SPRITES; i++)
|
|
{
|
|
mGame.smartSprite[i]->render();
|
|
}
|
|
}
|
|
|
|
// Devuelve el primer indice no activo del vector de SmartSprites
|
|
Uint8 GameDirector::getSmartSpriteFreeIndex()
|
|
{
|
|
Uint8 index = 0;
|
|
|
|
for (int i = 0; i < MAX_SMART_SPRITES; i++)
|
|
{
|
|
if (mGame.smartSprite[i]->isEnabled() == false)
|
|
{
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
// Establece a cero todos los valores del vector de objetos SmafrtSprite
|
|
void GameDirector::resetSmartSprites()
|
|
{
|
|
for (Uint8 i = 0; i < MAX_SMART_SPRITES; i++)
|
|
{
|
|
mGame.smartSprite[i]->erase();
|
|
}
|
|
}
|
|
|
|
#ifndef UNUSED
|
|
// Deshabilita todas las gotas de café
|
|
void GameDirector::resetCoffeeDrops()
|
|
{
|
|
for (Uint8 i = 0; i < MAX_COFFEE_DROPS; i++)
|
|
{
|
|
mCoffeeDrop[i]->disable();
|
|
}
|
|
}
|
|
|
|
// Actualiza las gotas de cafe
|
|
void GameDirector::updateCoffeeDrops()
|
|
{
|
|
for (Uint8 i = 0; i < MAX_COFFEE_DROPS; i++)
|
|
{
|
|
mCoffeeDrop[i]->update();
|
|
}
|
|
}
|
|
|
|
// Dibuja las gotas de cafe
|
|
void GameDirector::renderCoffeeDrops()
|
|
{
|
|
for (Uint8 i = 0; i < MAX_COFFEE_DROPS; i++)
|
|
{
|
|
mCoffeeDrop[i]->render();
|
|
}
|
|
}
|
|
|
|
// Devuelve el primer indice libre del vector de CoffeeDrops
|
|
Uint8 GameDirector::getCoffeDropFreeIndex()
|
|
{
|
|
Uint8 index = 0;
|
|
|
|
for (Uint8 i = 0; i < MAX_COFFEE_DROPS; i++)
|
|
{
|
|
if (!(mCoffeeDrop[i]->isEnabled()))
|
|
{
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
return index;
|
|
}
|
|
|
|
// Crea un numero de gotas de cafe
|
|
void GameDirector::createCoffeDrops(Uint8 num, int x, int y)
|
|
{
|
|
for (Uint8 i = 0; i < num; i++)
|
|
{
|
|
mCoffeeDrop[getCoffeDropFreeIndex()]->init(mTexture[TEXTURE_GAME_BG].texture, mRenderer, x, y, ((rand() % 7) * 0.5f) - 1.5f, (rand() % 7) * (-0.5f) + 1.0f, PLAY_AREA_BOTTOM);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Acciones a realizar cuando el jugador muere
|
|
void GameDirector::killPlayer()
|
|
{
|
|
if (!mGame.player->isInvulnerable())
|
|
{
|
|
if (mGame.player->hasExtraHit())
|
|
{
|
|
mGame.player->removeExtraHit();
|
|
throwCoffee(mGame.player->getPosX() + (mGame.player->getWidth() / 2), mGame.player->getPosY() + (mGame.player->getHeight() / 2));
|
|
JA_PlaySound(mSound[SOUND_COFFEE_OUT].sound);
|
|
}
|
|
else
|
|
{
|
|
stopAllBalloons(10); // 5000
|
|
JA_StopMusic();
|
|
JA_PlaySound(mSound[SOUND_PLAYER_COLLISION].sound);
|
|
shakeScreen();
|
|
SDL_Delay(500); // 1000
|
|
JA_PlaySound(mSound[SOUND_COFFEE_OUT].sound);
|
|
throwPlayer(mGame.player->getPosX(), mGame.player->getPosY());
|
|
mGame.player->setAlive(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Obtiene el valor de la variable
|
|
Uint8 GameDirector::getSubsection()
|
|
{
|
|
return mProg.subsection;
|
|
}
|
|
|
|
// Calcula y establece el valor de amenaza en funcion de los globos activos
|
|
void GameDirector::setMenace()
|
|
{
|
|
mGame.menaceCurrent = 0;
|
|
for (Uint8 i = 0; i < MAX_BALLOONS; i++)
|
|
if (mGame.balloon[i]->isEnabled())
|
|
mGame.menaceCurrent += mGame.balloon[i]->getMenace();
|
|
}
|
|
|
|
// Obtiene el valor de la variable
|
|
Uint8 GameDirector::getMenace()
|
|
{
|
|
return mGame.menaceCurrent;
|
|
}
|
|
|
|
// Establece el valor de la variable
|
|
void GameDirector::setTimeStopped(bool value)
|
|
{
|
|
mGame.timeStopped = value;
|
|
}
|
|
|
|
// Obtiene el valor de la variable
|
|
bool GameDirector::isTimeStopped()
|
|
{
|
|
return mGame.timeStopped;
|
|
}
|
|
|
|
// Establece el valor de la variable
|
|
void GameDirector::setTimeStoppedCounter(Uint16 value)
|
|
{
|
|
mGame.timeStoppedCounter = value;
|
|
}
|
|
|
|
// Actualiza y comprueba el valor de la variable
|
|
void GameDirector::updateTimeStoppedCounter()
|
|
{
|
|
if (isTimeStopped())
|
|
{
|
|
if (mGame.timeStoppedCounter > 0)
|
|
{
|
|
mGame.timeStoppedCounter--;
|
|
stopAllBalloons(TIME_STOPPED_COUNTER);
|
|
}
|
|
else
|
|
{
|
|
disableTimeStopItem();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Establece el valor de la variable
|
|
void GameDirector::setExplosionTime(bool value)
|
|
{
|
|
mGame.explosionTime = value;
|
|
}
|
|
|
|
// Obtiene el valor de la variable
|
|
bool GameDirector::isExplosionTime()
|
|
{
|
|
return mGame.explosionTime;
|
|
}
|
|
|
|
// Establece el valor de la variable
|
|
void GameDirector::setRemainingExplosions(Uint8 value)
|
|
{
|
|
mGame.remainingExplosions = value;
|
|
}
|
|
|
|
// Actualiza y comprueba el valor de la variable
|
|
void GameDirector::updateRemainingExplosionsCounter()
|
|
{
|
|
if (isExplosionTime())
|
|
{
|
|
if (mGame.remainingExplosionsCounter > 0)
|
|
{
|
|
--mGame.remainingExplosionsCounter;
|
|
}
|
|
else if (mGame.remainingExplosions > 0)
|
|
{
|
|
popAllBalloons();
|
|
--mGame.remainingExplosions;
|
|
mGame.remainingExplosionsCounter = REMAINING_EXPLOSIONS_COUNTER;
|
|
}
|
|
else
|
|
{
|
|
mGame.explosionTime = false;
|
|
mGame.remainingExplosions = REMAINING_EXPLOSIONS;
|
|
mGame.remainingExplosionsCounter = REMAINING_EXPLOSIONS_COUNTER;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Actualiza la variable EnemyDeployCounter
|
|
void GameDirector::updateEnemyDeployCounter()
|
|
{
|
|
if (mGame.enemyDeployCounter > 0)
|
|
mGame.enemyDeployCounter--;
|
|
}
|
|
|
|
// Actualiza el campo de juego
|
|
void GameDirector::updatePlayField()
|
|
{
|
|
// Comprueba el teclado/mando
|
|
checkGameInput();
|
|
|
|
// Actualiza las variables del jugador
|
|
updatePlayer();
|
|
|
|
// Actualiza el fondo
|
|
updateBackground();
|
|
|
|
// Mueve los globos
|
|
updateBalloons();
|
|
|
|
// Mueve las balas
|
|
moveBullets();
|
|
|
|
// Actualiza los items
|
|
updateItems();
|
|
|
|
// Actualiza el valor de mGame.currentStage
|
|
updateStage();
|
|
|
|
// Actualiza el estado de muerte
|
|
updateDeath();
|
|
|
|
// Actualiza los SmartSprites
|
|
updateSmartSprites();
|
|
|
|
// Actualiza los contadores de estado y efectos
|
|
updateTimeStoppedCounter();
|
|
updateRemainingExplosionsCounter();
|
|
updateEnemyDeployCounter();
|
|
updateShakeEffect();
|
|
|
|
// Comprueba las colisiones entre globos y balas
|
|
checkBulletBalloonCollision();
|
|
|
|
// Comprueba las colisiones entre elk jugador y los items
|
|
checkPlayerItemCollision();
|
|
|
|
// Comprueba el nivel de amenaza
|
|
updateMenace();
|
|
|
|
// Actualiza la velocidad de los enemigos
|
|
updateBalloonSpeed();
|
|
}
|
|
|
|
// Actualiza el fondo
|
|
void GameDirector::updateBackground()
|
|
{
|
|
mGame.clouds1a->move();
|
|
mGame.clouds1b->move();
|
|
mGame.clouds2a->move();
|
|
mGame.clouds2b->move();
|
|
if (mGame.clouds1a->getPosX() < -mGame.clouds1a->getWidth())
|
|
mGame.clouds1a->setPosX(mGame.clouds1a->getWidth());
|
|
if (mGame.clouds1b->getPosX() < -mGame.clouds1b->getWidth())
|
|
mGame.clouds1b->setPosX(mGame.clouds1b->getWidth());
|
|
if (mGame.clouds2a->getPosX() < -mGame.clouds2a->getWidth())
|
|
mGame.clouds2a->setPosX(mGame.clouds2a->getWidth());
|
|
if (mGame.clouds2b->getPosX() < -mGame.clouds2b->getWidth())
|
|
mGame.clouds2b->setPosX(mGame.clouds2b->getWidth());
|
|
mGame.grass->setSpriteClip(256, 85 + (6 * (mGame.counter / 20 % 2)), SCREEN_WIDTH, 6);
|
|
if (mGame.effect.shake)
|
|
mGame.background->setPosX(((mGame.effect.shakeCounter % 2) * 2) - 1);
|
|
else
|
|
mGame.background->setPosX(0);
|
|
}
|
|
|
|
// Dibuja el fondo
|
|
void GameDirector::renderBackground()
|
|
{
|
|
float gradientNumber = std::min(((float)mGame.balloonsPopped / 900.0f), 3.0f);
|
|
float percent = gradientNumber - (int)gradientNumber;
|
|
int alpha = std::max((255 - (int)(255 * percent)), 0);
|
|
|
|
// Dibuja el gradiente 2
|
|
mGame.gradient->setSpriteClip(mGame.gradientRect[((int)gradientNumber + 1) % 4]);
|
|
mGame.gradient->render();
|
|
|
|
// Dibuja el gradiente 1 con una opacidad cada vez menor
|
|
mGame.gradient->setSpriteClip(mGame.gradientRect[(int)gradientNumber]);
|
|
mTexture[TEXTURE_GAME_BG].texture->setAlpha(alpha);
|
|
mGame.gradient->render();
|
|
mTexture[TEXTURE_GAME_BG].texture->setAlpha(255);
|
|
|
|
mGame.clouds1a->render();
|
|
mGame.clouds1b->render();
|
|
mGame.clouds2a->render();
|
|
mGame.clouds2b->render();
|
|
|
|
mGame.background->render();
|
|
|
|
mGame.grass->render();
|
|
}
|
|
|
|
// Dibuja el campo de juego
|
|
void GameDirector::renderPlayField()
|
|
{
|
|
renderBackground();
|
|
renderBalloons();
|
|
renderBullets();
|
|
renderItems();
|
|
renderSmartSprites();
|
|
mGame.player->render();
|
|
renderMessages();
|
|
renderDeathFade();
|
|
renderScoreBoard();
|
|
renderFlashEffect();
|
|
}
|
|
|
|
// Gestiona el nivel de amenaza
|
|
void GameDirector::old_updateMenace()
|
|
{
|
|
// Aumenta el nivel de amenaza en función de la puntuación
|
|
mGame.menaceThreshold = 7 + (4 * (mGame.score / 10000));
|
|
|
|
// Si el nivel de amenza es inferior al umbral
|
|
if (mGame.menaceCurrent < mGame.menaceThreshold)
|
|
{
|
|
Uint8 index = 0;
|
|
|
|
// Obtiene el centro del jugador en el eje X
|
|
int x = mGame.player->getPosX() + (mGame.player->getWidth() / 2);
|
|
|
|
// Crea un globo sobre el jugador en dirección hacia el centro
|
|
if (x < (PLAY_AREA_WIDTH / 2))
|
|
{
|
|
index = createNewBalloon(0, PLAY_AREA_TOP + BLOCK - 37, BALLOON_4, BALLOON_VELX_POSITIVE, mGame.enemySpeed, 400, mTexture[TEXTURE_BALLOON].texture);
|
|
}
|
|
else
|
|
{
|
|
index = createNewBalloon(0, PLAY_AREA_TOP + BLOCK - 37, BALLOON_4, BALLOON_VELX_NEGATIVE, mGame.enemySpeed, 400, mTexture[TEXTURE_BALLOON].texture);
|
|
}
|
|
mGame.balloon[index]->allignTo(x);
|
|
|
|
// Recalcula el nivel de amenaza con el nuevo globo
|
|
setMenace();
|
|
}
|
|
}
|
|
|
|
// Gestiona el nivel de amenaza
|
|
void GameDirector::updateMenace()
|
|
{
|
|
float percent = mGame.stage[mGame.currentStage].currentPower / mGame.stage[mGame.currentStage].powerToComplete;
|
|
Uint8 difference = mGame.stage[mGame.currentStage].maxMenace - mGame.stage[mGame.currentStage].minMenace;
|
|
|
|
// Aumenta el nivel de amenaza en función de la puntuación
|
|
mGame.menaceThreshold = mGame.stage[mGame.currentStage].minMenace + (difference * percent);
|
|
|
|
// Si el nivel de amenza es inferior al umbral
|
|
if (mGame.menaceCurrent < mGame.menaceThreshold)
|
|
{
|
|
// Crea una formación de enemigos
|
|
deployEnemyFormation();
|
|
|
|
// Recalcula el nivel de amenaza con el nuevo globo
|
|
setMenace();
|
|
}
|
|
}
|
|
|
|
// Gestiona las entradas desde el mando de juego
|
|
bool GameDirector::checkGameController(Uint8 state)
|
|
{
|
|
// No hay mando. Siempre devuelve falso salvo NO_INPUT que siempre es cierto
|
|
if (!mGameControllerFound)
|
|
{
|
|
if (state == NO_INPUT)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
bool success = false;
|
|
|
|
switch (state)
|
|
{
|
|
case NO_INPUT:
|
|
success = !checkGameController(INPUT_UP) && !checkGameController(INPUT_DOWN) && !checkGameController(INPUT_LEFT) && !checkGameController(INPUT_RIGHT) &&
|
|
!checkGameController(INPUT_ACCEPT) && !checkGameController(INPUT_CANCEL) && !checkGameController(INPUT_PAUSE) &&
|
|
!checkGameController(INPUT_FIRE_UP) && !checkGameController(INPUT_FIRE_LEFT) && !checkGameController(INPUT_FIRE_RIGHT);
|
|
break;
|
|
case INPUT_UP:
|
|
success = (SDL_JoystickGetAxis(mGameController, 1) < -JOYSTICK_DEAD_ZONE) || (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_DPAD_UP));
|
|
break;
|
|
case INPUT_DOWN:
|
|
success = (SDL_JoystickGetAxis(mGameController, 1) > JOYSTICK_DEAD_ZONE) || (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_DPAD_DOWN));
|
|
break;
|
|
case INPUT_LEFT:
|
|
success = (SDL_JoystickGetAxis(mGameController, 0) < -JOYSTICK_DEAD_ZONE) || (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_DPAD_LEFT));
|
|
break;
|
|
case INPUT_RIGHT:
|
|
success = (SDL_JoystickGetAxis(mGameController, 0) > JOYSTICK_DEAD_ZONE) || (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_DPAD_RIGHT));
|
|
break;
|
|
case INPUT_ACCEPT:
|
|
success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_B));
|
|
break;
|
|
case INPUT_CANCEL:
|
|
success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_A));
|
|
break;
|
|
case INPUT_PAUSE:
|
|
success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_START));
|
|
break;
|
|
case INPUT_FIRE_UP:
|
|
success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_Y));
|
|
break;
|
|
case INPUT_FIRE_LEFT:
|
|
success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_X));
|
|
break;
|
|
case INPUT_FIRE_RIGHT:
|
|
success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_B));
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return success;
|
|
}
|
|
|
|
// Gestiona la entrada durante el juego
|
|
void GameDirector::checkGameInput()
|
|
{
|
|
// Obtiene el estado de las teclas pulsadas del teclado
|
|
keystates = SDL_GetKeyboardState(NULL);
|
|
|
|
mDemo.keys.left = 0;
|
|
mDemo.keys.right = 0;
|
|
mDemo.keys.noInput = 0;
|
|
mDemo.keys.fire = 0;
|
|
mDemo.keys.fireLeft = 0;
|
|
mDemo.keys.fireRight = 0;
|
|
|
|
// Modo Demo activo
|
|
if (mDemo.enabled)
|
|
{
|
|
if (mDemo.dataFile[mDemo.counter].left == 1)
|
|
mGame.player->setInput(INPUT_LEFT);
|
|
if (mDemo.dataFile[mDemo.counter].right == 1)
|
|
mGame.player->setInput(INPUT_RIGHT);
|
|
if (mDemo.dataFile[mDemo.counter].noInput == 1)
|
|
mGame.player->setInput(NO_INPUT);
|
|
if (mDemo.dataFile[mDemo.counter].fire == 1)
|
|
if (mGame.player->canFire())
|
|
{
|
|
mGame.player->setInput(INPUT_FIRE_UP);
|
|
createBullet(mGame.player->getPosX() + (mGame.player->getWidth() / 2) - 4, mGame.player->getPosY() + (mGame.player->getHeight() / 2), BULLET_UP);
|
|
mGame.player->setFireCooldown(10);
|
|
}
|
|
if (mDemo.dataFile[mDemo.counter].fireLeft == 1)
|
|
if (mGame.player->canFire())
|
|
{
|
|
mGame.player->setInput(INPUT_FIRE_LEFT);
|
|
createBullet(mGame.player->getPosX() + (mGame.player->getWidth() / 2) - 4, mGame.player->getPosY() + (mGame.player->getHeight() / 2), BULLET_UP);
|
|
mGame.player->setFireCooldown(10);
|
|
}
|
|
if (mDemo.dataFile[mDemo.counter].fireRight == 1)
|
|
if (mGame.player->canFire())
|
|
{
|
|
mGame.player->setInput(INPUT_FIRE_RIGHT);
|
|
createBullet(mGame.player->getPosX() + (mGame.player->getWidth() / 2) - 4, mGame.player->getPosY() + (mGame.player->getHeight() / 2), BULLET_UP);
|
|
mGame.player->setFireCooldown(10);
|
|
}
|
|
|
|
// Comprobamos la tecla o el botón de pausa/menu
|
|
if ((keystates[mProg.keyboard.accept] != 0) || (keystates[mProg.keyboard.cancel] != 0) || (checkGameController(INPUT_PAUSE)) || (checkGameController(INPUT_ACCEPT)) || (checkGameController(INPUT_CANCEL)))
|
|
{
|
|
setProgSection(PROG_SECTION_TITLE);
|
|
}
|
|
|
|
if (mDemo.counter < TOTAL_DEMO_DATA)
|
|
mDemo.counter++;
|
|
else
|
|
setProgSection(PROG_SECTION_TITLE, TITLE_SECTION_INSTRUCTIONS);
|
|
}
|
|
// Modo Demo no activo
|
|
else if (mGame.player->isAlive())
|
|
{
|
|
// Tecla izquierda o el mando hacia la izquierda
|
|
if ((keystates[mProg.keyboard.left] != 0) || (checkGameController(INPUT_LEFT)))
|
|
{
|
|
mGame.player->setInput(INPUT_LEFT);
|
|
mDemo.keys.left = 1;
|
|
}
|
|
else
|
|
{
|
|
// Tecla derecha o el mando hacia la derecha
|
|
if ((keystates[mProg.keyboard.right] != 0) || (checkGameController(INPUT_RIGHT)))
|
|
{
|
|
mGame.player->setInput(INPUT_RIGHT);
|
|
mDemo.keys.right = 1;
|
|
}
|
|
else
|
|
{
|
|
// Ninguna de las dos direcciones pulsadas
|
|
mGame.player->setInput(NO_INPUT);
|
|
mDemo.keys.noInput = 1;
|
|
}
|
|
}
|
|
// Comprueba la tecla o el botón de disparo central
|
|
if ((keystates[mProg.keyboard.fire] != 0) || (checkGameController(INPUT_FIRE_UP)))
|
|
{
|
|
if (mGame.player->canFire())
|
|
{
|
|
mGame.player->setInput(INPUT_FIRE_UP);
|
|
createBullet(mGame.player->getPosX() + (mGame.player->getWidth() / 2) - 4, mGame.player->getPosY() + (mGame.player->getHeight() / 2), BULLET_UP);
|
|
mGame.player->setFireCooldown(10);
|
|
|
|
// Reproduce el sonido de disparo
|
|
JA_PlaySound(mSound[SOUND_BULLET].sound);
|
|
|
|
mDemo.keys.fire = 1;
|
|
}
|
|
}
|
|
|
|
// Comprueba la tecla o el botón de disparo izquierdo
|
|
if ((keystates[mProg.keyboard.fireLeft] != 0) || (checkGameController(INPUT_FIRE_LEFT)))
|
|
{
|
|
if (mGame.player->canFire())
|
|
{
|
|
mGame.player->setInput(INPUT_FIRE_LEFT);
|
|
createBullet(mGame.player->getPosX() + (mGame.player->getWidth() / 2) - 4, mGame.player->getPosY() + (mGame.player->getHeight() / 2), BULLET_LEFT);
|
|
mGame.player->setFireCooldown(10);
|
|
|
|
// Reproduce el sonido de disparo
|
|
JA_PlaySound(mSound[SOUND_BULLET].sound);
|
|
|
|
mDemo.keys.fireLeft = 1;
|
|
}
|
|
}
|
|
|
|
// Comprueba la tecla o el botón de disparo derecho
|
|
if ((keystates[mProg.keyboard.fireRight] != 0) || (checkGameController(INPUT_FIRE_RIGHT)))
|
|
{
|
|
if (mGame.player->canFire())
|
|
{
|
|
mGame.player->setInput(INPUT_FIRE_RIGHT);
|
|
createBullet(mGame.player->getPosX() + (mGame.player->getWidth() / 2) - 4, mGame.player->getPosY() + (mGame.player->getHeight() / 2), BULLET_RIGHT);
|
|
mGame.player->setFireCooldown(10);
|
|
|
|
// Reproduce el sonido de disparo
|
|
JA_PlaySound(mSound[SOUND_BULLET].sound);
|
|
|
|
mDemo.keys.fireRight = 1;
|
|
}
|
|
}
|
|
|
|
// Para la pausa actuaremos cuando se suelte la tecla de pausa
|
|
// Comprueba la tecla o el botón de pausa/menu y su buffer
|
|
if (((keystates[mProg.keyboard.pause] != 0) || (checkGameController(INPUT_PAUSE))) && (mProg.keyboardBuffer.pause == 0)) //|| ((mGameControllerFound) && (SDL_JoystickGetButton(mGameController, BUTTON_START))))
|
|
{
|
|
// Se acaba de pulsar la tecla. Lo anotamos en su buffer
|
|
mProg.keyboardBuffer.pause = 1;
|
|
}
|
|
else
|
|
{
|
|
// Aqui sigue la tecla pulsada, mantenemos el buffer activo
|
|
if (((keystates[mProg.keyboard.pause] != 0) || (checkGameController(INPUT_PAUSE))) && (mProg.keyboardBuffer.pause != 0))
|
|
{
|
|
mProg.keyboardBuffer.pause = 1;
|
|
}
|
|
else
|
|
{
|
|
// Se ha soltado la tecla, procedemos a ejecutar la accion
|
|
if (((keystates[mProg.keyboard.pause] == 0) || (!checkGameController(INPUT_PAUSE))) && (mProg.keyboardBuffer.pause != 0))
|
|
{
|
|
mGame.section = GAME_SECTION_PAUSE;
|
|
|
|
if (JA_GetMusicState() == JA_MUSIC_PLAYING)
|
|
{
|
|
JA_PauseMusic();
|
|
}
|
|
|
|
mProg.keyboardBuffer.pause = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mDemo.counter < TOTAL_DEMO_DATA)
|
|
{
|
|
if (mDemo.recording)
|
|
{
|
|
mDemo.dataFile[mDemo.counter] = mDemo.keys;
|
|
}
|
|
mDemo.counter++;
|
|
}
|
|
else if (mDemo.recording)
|
|
{
|
|
mProg.quit = true;
|
|
;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Gestiona la entrada de teclado y mando durante el menu
|
|
void GameDirector::checkMenuInput(Menu *menu)
|
|
{
|
|
// Obtiene el estado de las teclas pulsadas del teclado
|
|
keystates = SDL_GetKeyboardState(NULL);
|
|
|
|
if (!mMenu.keyPressed)
|
|
{
|
|
// Tecla arriba o el mando hacia arriba
|
|
if ((keystates[mProg.keyboard.up] != 0) || (checkGameController(INPUT_UP)))
|
|
{
|
|
if (menu->checkInput(INPUT_UP))
|
|
{
|
|
mMenu.keyPressed = true;
|
|
JA_PlaySound(mSound[SOUND_MENU_MOVE].sound);
|
|
}
|
|
}
|
|
|
|
// Tecla abajo o el mando hacia abajo
|
|
if ((keystates[mProg.keyboard.down] != 0) || (checkGameController(INPUT_DOWN)))
|
|
{
|
|
if (menu->checkInput(INPUT_DOWN))
|
|
{
|
|
mMenu.keyPressed = true;
|
|
JA_PlaySound(mSound[SOUND_MENU_MOVE].sound);
|
|
}
|
|
}
|
|
|
|
// Tecla o el botón de aceptar
|
|
if ((keystates[mProg.keyboard.accept] != 0) || (checkGameController(INPUT_ACCEPT)))
|
|
{
|
|
menu->checkInput(INPUT_ACCEPT);
|
|
mMenu.keyPressed = true;
|
|
}
|
|
|
|
// Tecla o el botón de cancelar
|
|
if ((keystates[mProg.keyboard.cancel] != 0) || (checkGameController(INPUT_CANCEL)))
|
|
{
|
|
menu->checkInput(INPUT_CANCEL);
|
|
mMenu.keyPressed = true;
|
|
}
|
|
}
|
|
|
|
// Ningún botón, libera la variable
|
|
if ((keystates[mProg.keyboard.up] == 0) && (keystates[mProg.keyboard.down] == 0) && (keystates[mProg.keyboard.accept] == 0) &&
|
|
(keystates[mProg.keyboard.cancel] == 0) && (checkGameController(NO_INPUT)))
|
|
{
|
|
mMenu.keyPressed = false;
|
|
}
|
|
}
|
|
|
|
// Obtiene el valor de la variable
|
|
Uint8 GameDirector::getProgSection()
|
|
{
|
|
return mProg.section;
|
|
}
|
|
|
|
// Establece el valor de la variable
|
|
void GameDirector::setProgSection(Uint8 section, Uint8 subsection)
|
|
{
|
|
mProg.section = section;
|
|
mProg.subsection = subsection;
|
|
}
|
|
|
|
// Pinta una transición en pantalla
|
|
void GameDirector::renderFade(Uint8 index)
|
|
{
|
|
SDL_Rect rect1;
|
|
SDL_Rect rect2;
|
|
Uint8 R, G, B;
|
|
|
|
// Copia el backbuffer al renderer
|
|
SDL_SetRenderTarget(mRenderer, NULL);
|
|
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
|
|
SDL_RenderPresent(mRenderer);
|
|
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
|
|
SDL_RenderPresent(mRenderer);
|
|
|
|
switch (index)
|
|
{
|
|
case 0:
|
|
rect1 = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
|
|
R = 0x27;
|
|
G = 0x27;
|
|
B = 0x36;
|
|
|
|
for (int i = 0; i < 256; i += 4)
|
|
{
|
|
// Dibujamos sobre el renderizador
|
|
SDL_SetRenderTarget(mRenderer, NULL);
|
|
|
|
// Copia el backbuffer con la imagen que había al renderizador
|
|
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
|
|
|
|
SDL_SetRenderDrawColor(mRenderer, R, G, B, i);
|
|
SDL_RenderFillRect(mRenderer, &rect1);
|
|
|
|
// Vuelca el renderizador en pantalla
|
|
SDL_RenderPresent(mRenderer);
|
|
}
|
|
|
|
// Deja todos los bufferes del mismo color
|
|
SDL_SetRenderTarget(mRenderer, mBackbuffer);
|
|
SDL_SetRenderDrawColor(mRenderer, R, G, B, 255);
|
|
SDL_RenderClear(mRenderer);
|
|
|
|
SDL_SetRenderTarget(mRenderer, NULL);
|
|
SDL_SetRenderDrawColor(mRenderer, R, G, B, 255);
|
|
SDL_RenderClear(mRenderer);
|
|
break;
|
|
|
|
case 1:
|
|
rect1 = {0, 0, SCREEN_WIDTH, 0};
|
|
rect2 = {0, 0, SCREEN_WIDTH, 0};
|
|
R = 0x27;
|
|
G = 0x27;
|
|
B = 0x36;
|
|
|
|
SDL_SetRenderDrawColor(mRenderer, R, G, B, 64);
|
|
|
|
for (Uint16 i = 0; i < (SCREEN_HEIGHT / 2); i += 4)
|
|
{
|
|
// Dibujamos sobre el backbuffer
|
|
SDL_SetRenderTarget(mRenderer, mBackbuffer);
|
|
|
|
rect1.h = rect2.h = i;
|
|
rect2.y = SCREEN_HEIGHT - (i);
|
|
|
|
SDL_RenderFillRect(mRenderer, &rect1);
|
|
SDL_RenderFillRect(mRenderer, &rect2);
|
|
|
|
// Volvemos a usar el renderizador de forma normal
|
|
SDL_SetRenderTarget(mRenderer, NULL);
|
|
|
|
// Copiamos el backbuffer al renderizador
|
|
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
|
|
|
|
// Volcamos el renderizador en pantalla
|
|
SDL_RenderPresent(mRenderer);
|
|
}
|
|
|
|
rect1 = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
|
|
|
|
for (Uint8 i = 0; i < 32; i++)
|
|
{
|
|
// Dibujamos sobre el backbuffer
|
|
SDL_SetRenderTarget(mRenderer, mBackbuffer);
|
|
SDL_RenderFillRect(mRenderer, &rect1);
|
|
|
|
// Volvemos a usar el renderizador de forma normal
|
|
SDL_SetRenderTarget(mRenderer, NULL);
|
|
|
|
// Copiamos el backbuffer al renderizador
|
|
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
|
|
|
|
// Volcamos el renderizador en pantalla
|
|
SDL_RenderPresent(mRenderer);
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
rect1 = {0, 0, 32, 32};
|
|
|
|
for (Uint16 i = 0; i < 50; i++)
|
|
{
|
|
// Crea un color al azar
|
|
R = 255 * (rand() % 2);
|
|
G = 255 * (rand() % 2);
|
|
B = 255 * (rand() % 2);
|
|
SDL_SetRenderDrawColor(mRenderer, R, G, B, 64);
|
|
|
|
// Dibujamos sobre el backbuffer
|
|
SDL_SetRenderTarget(mRenderer, mBackbuffer);
|
|
|
|
rect1.x = rand() % (SCREEN_WIDTH - rect1.w);
|
|
rect1.y = rand() % (SCREEN_HEIGHT - rect1.h);
|
|
SDL_RenderFillRect(mRenderer, &rect1);
|
|
|
|
// Volvemos a usar el renderizador de forma normal
|
|
SDL_SetRenderTarget(mRenderer, NULL);
|
|
|
|
// Copiamos el backbuffer al renderizador
|
|
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
|
|
|
|
// Volcamos el renderizador en pantalla
|
|
SDL_RenderPresent(mRenderer);
|
|
SDL_Delay(100);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Pinta diferentes mensajes en la pantalla
|
|
void GameDirector::renderMessages()
|
|
{
|
|
// GetReady
|
|
if (mGame.counter < STAGE_COUNTER)
|
|
{
|
|
mGame.getReadyBitmap->setPosX((int)mGame.getReadyBitmapPath[mGame.counter]);
|
|
mGame.getReadyBitmap->render();
|
|
}
|
|
|
|
// Time Stopped
|
|
if (mGame.timeStopped)
|
|
{
|
|
if ((mGame.timeStoppedCounter > 100) || (mGame.timeStoppedCounter % 10 > 4))
|
|
{
|
|
mText.black->writeCentered(PLAY_AREA_CENTER_X + 1, PLAY_AREA_FIRST_QUARTER_Y + 1, "Time Stopped: " + std::to_string(mGame.timeStoppedCounter / 10));
|
|
mText.white->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_FIRST_QUARTER_Y, "Time Stopped: " + std::to_string(mGame.timeStoppedCounter / 10));
|
|
}
|
|
}
|
|
|
|
// D E M O
|
|
if (mDemo.enabled)
|
|
{
|
|
if (mDemo.counter % 30 > 14)
|
|
{
|
|
mText.black->writeCentered(PLAY_AREA_CENTER_X + 1, PLAY_AREA_FIRST_QUARTER_Y + 1, "D E M O");
|
|
mText.white->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_FIRST_QUARTER_Y, "D E M O");
|
|
}
|
|
}
|
|
|
|
// STAGE NUMBER
|
|
if (mGame.stageBitmapCounter < STAGE_COUNTER)
|
|
{
|
|
mText.blackX2->writeCentered(PLAY_AREA_CENTER_X + 2, mGame.stageBitmapPath[mGame.stageBitmapCounter] + 2, "STAGE " + std::to_string(mGame.stage[mGame.currentStage].number));
|
|
mText.whiteX2->writeCentered(PLAY_AREA_CENTER_X, mGame.stageBitmapPath[mGame.stageBitmapCounter], "STAGE " + std::to_string(mGame.stage[mGame.currentStage].number));
|
|
}
|
|
}
|
|
|
|
// Habilita el efecto del item de detener el tiempo
|
|
void GameDirector::enableTimeStopItem()
|
|
{
|
|
stopAllBalloons(TIME_STOPPED_COUNTER);
|
|
setTimeStopped(true);
|
|
setTimeStoppedCounter(TIME_STOPPED_COUNTER);
|
|
if (JA_GetMusicState() == JA_MUSIC_PLAYING)
|
|
{
|
|
JA_PauseMusic();
|
|
}
|
|
}
|
|
|
|
// Deshabilita el efecto del item de detener el tiempo
|
|
void GameDirector::disableTimeStopItem()
|
|
{
|
|
mGame.timeStopped = false;
|
|
mGame.timeStoppedCounter = TIME_STOPPED_COUNTER;
|
|
startAllBalloons();
|
|
if (JA_GetMusicState() == JA_MUSIC_PAUSED)
|
|
{
|
|
JA_ResumeMusic();
|
|
}
|
|
}
|
|
|
|
// Cambia el valor de la variable de modo de pantalla completa
|
|
void GameDirector::changeFullScreenMode()
|
|
{
|
|
switch (mOptions.fullScreenMode)
|
|
{
|
|
case 0:
|
|
mOptions.fullScreenMode = SDL_WINDOW_FULLSCREEN;
|
|
break;
|
|
case SDL_WINDOW_FULLSCREEN:
|
|
mOptions.fullScreenMode = SDL_WINDOW_FULLSCREEN_DESKTOP;
|
|
break;
|
|
case SDL_WINDOW_FULLSCREEN_DESKTOP:
|
|
mOptions.fullScreenMode = 0;
|
|
break;
|
|
|
|
default:
|
|
mOptions.fullScreenMode = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Actualiza los elementos del menu de opciones
|
|
void GameDirector::updateOptionsMenu()
|
|
{
|
|
switch (mOptions.fullScreenMode)
|
|
{
|
|
case 0:
|
|
mMenu.options->setItemCaption(0, "WINDOWED");
|
|
break;
|
|
case SDL_WINDOW_FULLSCREEN:
|
|
mMenu.options->setItemCaption(0, "FULLSCREEN");
|
|
break;
|
|
case SDL_WINDOW_FULLSCREEN_DESKTOP:
|
|
mMenu.options->setItemCaption(0, "FAKE FULLSCREEN");
|
|
break;
|
|
|
|
default:
|
|
mMenu.options->setItemCaption(0, "WINDOWED");
|
|
break;
|
|
}
|
|
mMenu.options->setItemCaption(1, "WINDOWS SIZE " + std::to_string(mOptions.windowSize));
|
|
mMenu.options->centerMenu(SCREEN_CENTER_X);
|
|
mMenu.options->centerMenuElements();
|
|
}
|
|
|
|
// Agita la pantalla
|
|
void GameDirector::shakeScreen()
|
|
{
|
|
int v[] = {-1, 1, -1, 1, -1, 1, -1, 0};
|
|
for (Uint8 n = 0; n < 8; n++)
|
|
{
|
|
// Limpia la pantalla
|
|
SDL_SetRenderDrawColor(mRenderer, 0x00, 0x00, 0x00, 0xFF);
|
|
SDL_RenderClear(mRenderer);
|
|
|
|
// Dibuja los objetos
|
|
mGame.background->setPosX(0);
|
|
mGame.background->setWidth(1);
|
|
mGame.background->setSpriteClip(0, 0, 1, 192);
|
|
renderBackground();
|
|
|
|
mGame.background->setPosX(255);
|
|
mGame.background->setSpriteClip(255, 0, 1, 192);
|
|
mGame.background->render();
|
|
|
|
mGame.background->setPosX(v[n]);
|
|
mGame.background->setWidth(256);
|
|
mGame.background->setSpriteClip(0, 0, 256, 192);
|
|
mGame.background->render();
|
|
|
|
mGame.grass->render();
|
|
renderBalloons();
|
|
renderBullets();
|
|
renderItems();
|
|
mGame.player->render();
|
|
renderScoreBoard();
|
|
|
|
// Actualiza la pantalla
|
|
SDL_RenderPresent(mRenderer);
|
|
SDL_Delay(50);
|
|
}
|
|
}
|
|
|
|
// Agita la pantalla
|
|
void GameDirector::shakeScreen2()
|
|
{
|
|
int v[] = {-1, 1, -1, 1, -1, 1, -1, 0};
|
|
for (Uint8 n = 0; n < 8; n++)
|
|
{
|
|
// Limpia la pantalla
|
|
SDL_SetRenderDrawColor(mRenderer, 0x00, 0x00, 0x00, 0xFF);
|
|
SDL_RenderClear(mRenderer);
|
|
|
|
// Dibuja los objetos
|
|
mGame.background->setPosX(0);
|
|
mGame.background->setWidth(1);
|
|
mGame.background->setSpriteClip(0, 0, 1, 192);
|
|
renderBackground();
|
|
|
|
mGame.background->setPosX(255);
|
|
mGame.background->setSpriteClip(255, 0, 1, 192);
|
|
mGame.background->render();
|
|
|
|
mGame.background->setPosX(v[n]);
|
|
mGame.background->setWidth(256);
|
|
mGame.background->setSpriteClip(0, 0, 256, 192);
|
|
mGame.background->render();
|
|
|
|
mGame.grass->render();
|
|
renderBalloons();
|
|
renderBullets();
|
|
renderItems();
|
|
mGame.player->render();
|
|
renderScoreBoard();
|
|
|
|
// Actualiza la pantalla
|
|
SDL_RenderPresent(mRenderer);
|
|
SDL_Delay(50);
|
|
}
|
|
}
|
|
|
|
// Bucle para el logo del juego
|
|
void GameDirector::runLogo()
|
|
{
|
|
initLogo();
|
|
|
|
while ((mProg.section == PROG_SECTION_LOGO) && (!exit()))
|
|
{
|
|
// Comprueba los eventos que hay en la cola
|
|
while (SDL_PollEvent(mEventHandler) != 0)
|
|
{
|
|
// Evento de salida de la aplicación
|
|
if (mEventHandler->type == SDL_QUIT)
|
|
{
|
|
mProg.quit = true;
|
|
break;
|
|
}
|
|
|
|
// Cualquier tecla pulsada
|
|
if ((mEventHandler->type == SDL_KEYDOWN) || (mEventHandler->type == SDL_JOYBUTTONDOWN))
|
|
{
|
|
setProgSection(PROG_SECTION_TITLE);
|
|
}
|
|
}
|
|
|
|
// Cambia el destino donde se pinta todo
|
|
SDL_SetRenderTarget(mRenderer, mBackbuffer);
|
|
|
|
// Limpia el destino
|
|
SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 255);
|
|
SDL_RenderClear(mRenderer);
|
|
|
|
// Dibuja los objetos
|
|
mLogo.sprite->render();
|
|
|
|
// Dibuja el fade
|
|
if (mLogo.counter >= 200)
|
|
{
|
|
SDL_Rect rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
|
|
Uint16 alpha = mLogo.counter - 200;
|
|
if (alpha < 256)
|
|
{
|
|
SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, alpha);
|
|
}
|
|
else
|
|
{
|
|
SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 255); // alpha - 0 trans, 255 opaco
|
|
}
|
|
SDL_RenderFillRect(mRenderer, &rect);
|
|
}
|
|
|
|
// Vuelve a usar el renderizador como destino
|
|
SDL_SetRenderTarget(mRenderer, NULL);
|
|
|
|
// Copia el backbufer al renderizador
|
|
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
|
|
|
|
// Actualiza la pantalla
|
|
SDL_RenderPresent(mRenderer);
|
|
|
|
// Comprueba si ha terminado el logo
|
|
if (SDL_GetTicks() - mProg.ticks > mProg.ticksSpeed)
|
|
{
|
|
// Actualiza el contador de ticks
|
|
mProg.ticks = SDL_GetTicks();
|
|
|
|
if (mLogo.counter == 0)
|
|
{
|
|
if (JA_GetMusicState() == JA_MUSIC_PLAYING)
|
|
{
|
|
JA_StopMusic();
|
|
}
|
|
}
|
|
|
|
if (mLogo.counter == 500) // minimo 200 + 255
|
|
{
|
|
mLogo.counter = 0;
|
|
setProgSection(PROG_SECTION_INTRO);
|
|
}
|
|
else
|
|
{
|
|
mLogo.counter++;
|
|
}
|
|
}
|
|
}
|
|
|
|
quitLogo();
|
|
}
|
|
|
|
// Bucle para la intro del juego
|
|
void GameDirector::runIntro()
|
|
{
|
|
initIntro();
|
|
|
|
// Si la música no está sonando
|
|
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
|
|
{
|
|
// Reproduce la música
|
|
JA_PlayMusic(mMusic[MUSIC_INTRO].music, false);
|
|
}
|
|
|
|
while ((mProg.section == PROG_SECTION_INTRO) && (!exit()))
|
|
{
|
|
if (SDL_GetTicks() - mProg.ticks > mProg.ticksSpeed)
|
|
{
|
|
// Actualiza el contador de ticks
|
|
mProg.ticks = SDL_GetTicks();
|
|
|
|
// Comprueba los eventos que hay en la cola
|
|
while (SDL_PollEvent(mEventHandler) != 0)
|
|
{
|
|
// Evento de salida de la aplicación
|
|
if (mEventHandler->type == SDL_QUIT)
|
|
{
|
|
mProg.quit = true;
|
|
break;
|
|
}
|
|
|
|
if ((mEventHandler->type == SDL_KEYDOWN) || (mEventHandler->type == SDL_JOYBUTTONDOWN))
|
|
{
|
|
JA_StopMusic();
|
|
setProgSection(PROG_SECTION_TITLE);
|
|
}
|
|
}
|
|
|
|
// Actualiza los objetos
|
|
for (Uint8 i = 0; i < INTRO_TOTAL_BITMAPS; i++)
|
|
{
|
|
mIntro.bitmap[i]->update();
|
|
}
|
|
for (Uint8 i = 0; i < INTRO_TOTAL_TEXTS; i++)
|
|
{
|
|
mIntro.text[i]->update();
|
|
}
|
|
|
|
// Guión de eventos
|
|
// Primera imagen - UPV
|
|
if (mIntro.events[BITMAP0] == EVENT_WAITING)
|
|
{
|
|
mIntro.bitmap[0]->setEnabled(true);
|
|
mIntro.events[BITMAP0] = EVENT_RUNNING;
|
|
}
|
|
|
|
// Primer texto de la primera imagen
|
|
if ((mIntro.events[BITMAP0] == EVENT_COMPLETED) && (mIntro.events[TEXT0] == EVENT_WAITING))
|
|
{
|
|
mIntro.text[0]->setEnabled(true);
|
|
mIntro.events[TEXT0] = EVENT_RUNNING;
|
|
}
|
|
|
|
// Segundo texto de la primera imagen
|
|
if ((mIntro.events[TEXT0] == EVENT_COMPLETED) && (mIntro.events[TEXT1] == EVENT_WAITING))
|
|
{
|
|
mIntro.text[0]->setEnabled(false);
|
|
mIntro.text[1]->setEnabled(true);
|
|
mIntro.events[TEXT1] = EVENT_RUNNING;
|
|
}
|
|
|
|
// Tercer texto de la primera imagen
|
|
if ((mIntro.events[TEXT1] == EVENT_COMPLETED) && (mIntro.events[TEXT2] == EVENT_WAITING))
|
|
{
|
|
mIntro.text[1]->setEnabled(false);
|
|
mIntro.text[2]->setEnabled(true);
|
|
mIntro.events[TEXT2] = EVENT_RUNNING;
|
|
}
|
|
|
|
// Segunda imagen - Máquina
|
|
if ((mIntro.events[TEXT2] == EVENT_COMPLETED) && (mIntro.events[BITMAP1] == EVENT_WAITING))
|
|
{
|
|
mIntro.bitmap[0]->setEnabled(false);
|
|
mIntro.text[2]->setEnabled(false);
|
|
mIntro.bitmap[1]->setEnabled(true);
|
|
mIntro.events[BITMAP1] = EVENT_RUNNING;
|
|
}
|
|
|
|
// Primer texto de la segunda imagen
|
|
if ((mIntro.events[BITMAP1] == EVENT_COMPLETED) && (mIntro.events[TEXT3] == EVENT_WAITING))
|
|
{
|
|
mIntro.text[3]->setEnabled(true);
|
|
mIntro.events[TEXT3] = EVENT_RUNNING;
|
|
}
|
|
|
|
// Tercera imagen junto con primer texto - GRITO
|
|
if ((mIntro.events[TEXT3] == EVENT_COMPLETED) && (mIntro.events[BITMAP2] == EVENT_WAITING) && (mIntro.events[TEXT4] == EVENT_WAITING))
|
|
{
|
|
mIntro.bitmap[1]->setEnabled(false);
|
|
mIntro.text[3]->setEnabled(false);
|
|
mIntro.bitmap[2]->setEnabled(true);
|
|
mIntro.text[4]->setEnabled(true);
|
|
mIntro.events[BITMAP2] = EVENT_RUNNING;
|
|
mIntro.events[TEXT4] = EVENT_RUNNING;
|
|
}
|
|
|
|
// Cuarta imagen junto con primer texto - Reflexión
|
|
if ((mIntro.events[TEXT4] == EVENT_COMPLETED) && (mIntro.events[BITMAP3] == EVENT_WAITING) && (mIntro.events[TEXT5] == EVENT_WAITING))
|
|
{
|
|
mIntro.bitmap[2]->setEnabled(false);
|
|
mIntro.text[4]->setEnabled(false);
|
|
mIntro.bitmap[3]->setEnabled(true);
|
|
mIntro.text[5]->setEnabled(true);
|
|
mIntro.events[BITMAP3] = EVENT_RUNNING;
|
|
mIntro.events[TEXT5] = EVENT_RUNNING;
|
|
}
|
|
|
|
// Segundo texto de la cuarta imagen
|
|
if ((mIntro.events[TEXT5] == EVENT_COMPLETED) && (mIntro.events[TEXT6] == EVENT_WAITING))
|
|
{
|
|
mIntro.text[5]->setEnabled(false);
|
|
mIntro.text[6]->setEnabled(true);
|
|
mIntro.events[TEXT6] = EVENT_RUNNING;
|
|
}
|
|
|
|
// Quinta imagen - Patada
|
|
if ((mIntro.events[TEXT6] == EVENT_COMPLETED) && (mIntro.events[BITMAP4] == EVENT_WAITING))
|
|
{
|
|
mIntro.bitmap[3]->setEnabled(false);
|
|
mIntro.text[6]->setEnabled(false);
|
|
mIntro.bitmap[4]->setEnabled(true);
|
|
mIntro.events[BITMAP4] = EVENT_RUNNING;
|
|
}
|
|
|
|
// Primer texto de la quinta imagen
|
|
if ((mIntro.events[BITMAP4] == EVENT_COMPLETED) && (mIntro.events[TEXT7] == EVENT_WAITING))
|
|
{
|
|
mIntro.text[7]->setEnabled(true);
|
|
mIntro.events[TEXT7] = EVENT_RUNNING;
|
|
}
|
|
|
|
// Sexta imagen junto con texto - Globos de café
|
|
if ((mIntro.events[TEXT7] == EVENT_COMPLETED) && (mIntro.events[BITMAP5] == EVENT_WAITING) && (mIntro.events[TEXT8] == EVENT_WAITING))
|
|
{
|
|
mIntro.bitmap[4]->setEnabled(false);
|
|
mIntro.text[7]->setEnabled(false);
|
|
mIntro.bitmap[5]->setEnabled(true);
|
|
mIntro.text[8]->setEnabled(true);
|
|
mIntro.events[BITMAP5] = EVENT_RUNNING;
|
|
mIntro.events[TEXT8] = EVENT_RUNNING;
|
|
}
|
|
|
|
// Acaba el último texto
|
|
if (mIntro.events[TEXT8] == EVENT_COMPLETED)
|
|
{
|
|
mIntro.text[8]->setEnabled(false);
|
|
JA_StopMusic();
|
|
setProgSection(PROG_SECTION_TITLE);
|
|
}
|
|
}
|
|
|
|
// Limpia la pantalla
|
|
SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 0xFF);
|
|
SDL_RenderClear(mRenderer);
|
|
|
|
// Dibuja los objetos
|
|
for (Uint8 i = 0; i < INTRO_TOTAL_BITMAPS; i++)
|
|
mIntro.bitmap[i]->render();
|
|
for (Uint8 i = 0; i < INTRO_TOTAL_TEXTS; i++)
|
|
mIntro.text[i]->render();
|
|
|
|
// Actualiza la pantalla
|
|
SDL_RenderPresent(mRenderer);
|
|
}
|
|
|
|
quitIntro();
|
|
}
|
|
|
|
// Bucle para el titulo del juego
|
|
void GameDirector::runTitle(Uint8 subsection)
|
|
{
|
|
Uint8 R = 0x27;
|
|
Uint8 G = 0x27;
|
|
Uint8 B = 0x36;
|
|
|
|
initTitle(subsection);
|
|
|
|
while ((mProg.section == PROG_SECTION_TITLE) && (!exit()))
|
|
{
|
|
// Sección 1 - Titulo desplazandose
|
|
if (mTitle.section == TITLE_SECTION_1)
|
|
{
|
|
// Comprueba los eventos que hay en la cola
|
|
while (SDL_PollEvent(mEventHandler) != 0)
|
|
{
|
|
// Evento de salida de la aplicación
|
|
if (mEventHandler->type == SDL_QUIT)
|
|
{
|
|
mProg.quit = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Calcula la lógica de los objetos
|
|
if (SDL_GetTicks() - mProg.ticks > mProg.ticksSpeed)
|
|
{
|
|
// Actualiza el contador de ticks
|
|
mProg.ticks = SDL_GetTicks();
|
|
|
|
// Actualiza los objetos
|
|
mTitle.coffeeBitmap->update();
|
|
mTitle.crisisBitmap->update();
|
|
}
|
|
|
|
// Limpia la pantalla
|
|
SDL_SetRenderDrawColor(mRenderer, R, G, B, 255);
|
|
SDL_RenderClear(mRenderer);
|
|
|
|
// Dibuja los objetos
|
|
mTitle.coffeeBitmap->render();
|
|
mTitle.crisisBitmap->render();
|
|
|
|
// Actualiza la pantalla
|
|
SDL_RenderPresent(mRenderer);
|
|
|
|
// Si los objetos han llegado a su destino, cambiamos de Sección
|
|
if ((mTitle.events[0] == EVENT_COMPLETED) && (mTitle.events[0] == EVENT_COMPLETED))
|
|
{
|
|
mTitle.section = TITLE_SECTION_2;
|
|
|
|
// Pantallazo blanco
|
|
SDL_SetRenderDrawColor(mRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
|
|
SDL_RenderClear(mRenderer);
|
|
SDL_RenderPresent(mRenderer);
|
|
}
|
|
}
|
|
|
|
// Sección 2 - Titulo vibrando
|
|
if (mTitle.section == TITLE_SECTION_2)
|
|
{
|
|
// Comprueba los eventos que hay en la cola
|
|
while (SDL_PollEvent(mEventHandler) != 0)
|
|
{
|
|
// Evento de salida de la aplicación
|
|
if (mEventHandler->type == SDL_QUIT)
|
|
{
|
|
mProg.quit = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Reproduce el efecto sonoro
|
|
JA_PlaySound(mSound[SOUND_TITLE].sound);
|
|
|
|
// Agita la pantalla
|
|
int v[] = {-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 0};
|
|
int a = mTitle.coffeeBitmap->getPosX();
|
|
int b = mTitle.crisisBitmap->getPosX();
|
|
for (Uint8 n = 0; n < 11 * 3; n++)
|
|
{
|
|
// Limpia la pantalla
|
|
SDL_SetRenderDrawColor(mRenderer, R, G, B, 255);
|
|
SDL_RenderClear(mRenderer);
|
|
|
|
// Dibuja los objetos
|
|
mTitle.coffeeBitmap->setPosX(a + v[n / 3]);
|
|
mTitle.crisisBitmap->setPosX(b + v[n / 3]);
|
|
mTitle.coffeeBitmap->render();
|
|
mTitle.crisisBitmap->render();
|
|
mTitle.dustBitmapR->animate(0);
|
|
mTitle.dustBitmapL->animate(0);
|
|
mTitle.dustBitmapR->render();
|
|
mTitle.dustBitmapL->render();
|
|
|
|
// Actualiza la pantalla
|
|
SDL_RenderPresent(mRenderer);
|
|
}
|
|
|
|
mTitle.section = 2;
|
|
}
|
|
|
|
// Sección 3 - La pantalla de titulo con el menú y la música
|
|
if (mTitle.section == TITLE_SECTION_3)
|
|
{
|
|
if (mTitle.counter > 0)
|
|
{
|
|
// Comprueba los eventos que hay en la cola
|
|
while (SDL_PollEvent(mEventHandler) != 0)
|
|
{
|
|
// Evento de salida de la aplicación
|
|
if (mEventHandler->type == SDL_QUIT)
|
|
{
|
|
mProg.quit = true;
|
|
break;
|
|
}
|
|
|
|
if ((mEventHandler->type == SDL_KEYUP) || (mEventHandler->type == SDL_JOYBUTTONUP))
|
|
{
|
|
mTitle.menuVisible = true;
|
|
mTitle.counter = TITLE_COUNTER;
|
|
}
|
|
}
|
|
// Si la música no está sonando
|
|
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
|
|
{
|
|
// Reproduce la música
|
|
JA_PlayMusic(mMusic[MUSIC_TITLE].music, true);
|
|
}
|
|
|
|
// Calcula la lógica de los objetos
|
|
if (SDL_GetTicks() - mProg.ticks > mProg.ticksSpeed)
|
|
{
|
|
// Actualiza el contador de ticks
|
|
mProg.ticks = SDL_GetTicks();
|
|
|
|
// Actualiza la lógica del menu
|
|
mMenu.active->update();
|
|
}
|
|
|
|
// Cambia el destino donde se pinta todo
|
|
SDL_SetRenderTarget(mRenderer, mBackbuffer);
|
|
|
|
// Limpia la pantalla
|
|
SDL_SetRenderDrawColor(mRenderer, R, G, B, 255);
|
|
SDL_RenderClear(mRenderer);
|
|
|
|
// Pinta el tileado de fondo
|
|
switch (mTitle.backgroundMode)
|
|
{
|
|
case 0: // El tileado de fondo se desplaza en diagonal
|
|
mTitle.backgroundWindow.x++;
|
|
mTitle.backgroundWindow.x %= 64;
|
|
mTitle.backgroundWindow.y++;
|
|
mTitle.backgroundWindow.y %= 64;
|
|
break;
|
|
|
|
case 1: // El tileado de fondo se desplaza en circulo
|
|
++mTitle.backgroundCounter %= 360;
|
|
mTitle.backgroundWindow.x = 128 + (int(mSin[(mTitle.backgroundCounter + 270) % 360] * 128));
|
|
mTitle.backgroundWindow.y = 96 + (int(mSin[(360 - mTitle.backgroundCounter) % 360] * 96));
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
SDL_RenderCopy(mRenderer, mTitleSurface, &mTitle.backgroundWindow, NULL);
|
|
|
|
// Dibuja los objetos
|
|
mTitle.coffeeBitmap->render();
|
|
mTitle.crisisBitmap->render();
|
|
if (mTitle.menuVisible == true)
|
|
{
|
|
mMenu.active->render();
|
|
}
|
|
mTitle.dustBitmapR->animate(0);
|
|
mTitle.dustBitmapL->animate(0);
|
|
mTitle.dustBitmapR->render();
|
|
mTitle.dustBitmapL->render();
|
|
|
|
// PRESS ANY KEY!
|
|
if ((mTitle.counter % 50 > 14) && (mTitle.menuVisible == false))
|
|
{
|
|
mText.black->writeCentered(SCREEN_CENTER_X + 1, PLAY_AREA_THIRD_QUARTER_Y + BLOCK + 1, "PRESS ANY KEY!", 0);
|
|
mText.white->writeCentered(SCREEN_CENTER_X, PLAY_AREA_THIRD_QUARTER_Y + BLOCK, "PRESS ANY KEY!", 0);
|
|
}
|
|
|
|
// Texto con el copyright y versión
|
|
mText.black->writeCentered(SCREEN_CENTER_X + 1, SCREEN_HEIGHT - (BLOCK * 2) + 1, TEXT_COPYRIGHT, 0);
|
|
mText.white->writeCentered(SCREEN_CENTER_X, SCREEN_HEIGHT - (BLOCK * 2), TEXT_COPYRIGHT, 0);
|
|
|
|
// Vuelve a usar el renderizador como destino
|
|
SDL_SetRenderTarget(mRenderer, NULL);
|
|
|
|
// Volca el contenido de la textura en el renderizador
|
|
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
|
|
|
|
// Actualiza la pantalla
|
|
SDL_RenderPresent(mRenderer);
|
|
|
|
// Comprueba las entradas para el menu
|
|
if (mTitle.menuVisible == true)
|
|
{
|
|
checkMenuInput(mMenu.active);
|
|
}
|
|
|
|
// Comprueba si se ha seleccionado algún item del menú
|
|
if (mMenu.active->getName() == "TITLE")
|
|
{
|
|
switch (mMenu.active->getItemSelected())
|
|
{
|
|
case 0:
|
|
setProgSection(PROG_SECTION_GAME);
|
|
mMenu.active->reset();
|
|
mMenu.keyPressed = false;
|
|
JA_PlaySound(mSound[SOUND_MENU_SELECT].sound);
|
|
renderFade(1);
|
|
JA_StopMusic();
|
|
disableDemoMode();
|
|
break;
|
|
case 1:
|
|
JA_PlaySound(mSound[SOUND_MENU_SELECT].sound);
|
|
mMenu.active->reset();
|
|
mMenu.active = mMenu.options;
|
|
mOptions.fullScreenModePrevious = mOptions.fullScreenMode;
|
|
mOptions.windowSizePrevious = mOptions.windowSize;
|
|
break;
|
|
case 2:
|
|
mProg.quit = true;
|
|
mMenu.active->reset();
|
|
mMenu.keyPressed = false;
|
|
JA_PlaySound(mSound[SOUND_MENU_CANCEL].sound);
|
|
renderFade(1);
|
|
JA_StopMusic();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Comprueba si se ha seleccionado algún item de opciones
|
|
if (mMenu.active->getName() == "OPTIONS")
|
|
{
|
|
switch (mMenu.active->getItemSelected())
|
|
{
|
|
case 0: // Fullscreen mode
|
|
JA_PlaySound(mSound[SOUND_MENU_SELECT].sound);
|
|
changeFullScreenMode();
|
|
updateOptionsMenu();
|
|
mMenu.active->deselectItem();
|
|
break;
|
|
case 1: // Windows size
|
|
JA_PlaySound(mSound[SOUND_MENU_SELECT].sound);
|
|
mOptions.windowSize++;
|
|
if (mOptions.windowSize == 5)
|
|
mOptions.windowSize = 1;
|
|
updateOptionsMenu();
|
|
mMenu.active->deselectItem();
|
|
break;
|
|
case 2: // OK
|
|
JA_PlaySound(mSound[SOUND_MENU_SELECT].sound);
|
|
SDL_SetWindowFullscreen(mWindow, mOptions.fullScreenMode);
|
|
SDL_SetWindowSize(mWindow, SCREEN_WIDTH * mOptions.windowSize, SCREEN_HEIGHT * mOptions.windowSize);
|
|
mMenu.active->reset();
|
|
mMenu.active = mMenu.title;
|
|
break;
|
|
case 3: // CANCEL
|
|
JA_PlaySound(mSound[SOUND_MENU_CANCEL].sound);
|
|
mOptions.fullScreenMode = mOptions.fullScreenModePrevious;
|
|
mOptions.windowSize = mOptions.windowSizePrevious;
|
|
updateOptionsMenu();
|
|
mMenu.active->reset();
|
|
mMenu.active = mMenu.title;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (mMenu.active->getName() == "TITLE")
|
|
{
|
|
mTitle.counter--;
|
|
}
|
|
}
|
|
else if (mTitle.counter == 0)
|
|
{
|
|
mTitle.counter = TITLE_COUNTER;
|
|
setProgSection(mTitle.nextProgSection);
|
|
mMenu.active->reset();
|
|
toogleTitleNextGS();
|
|
renderFade(1);
|
|
enableDemoMode();
|
|
}
|
|
}
|
|
|
|
// Sección Instrucciones
|
|
if (mTitle.section == TITLE_SECTION_INSTRUCTIONS)
|
|
runInstructions();
|
|
}
|
|
|
|
quitTitle();
|
|
}
|
|
|
|
// Bucle para el juego
|
|
void GameDirector::runGame()
|
|
{
|
|
initGame();
|
|
|
|
while ((mProg.section == PROG_SECTION_GAME) && (!exit()))
|
|
{
|
|
// Sección juego en pausa
|
|
if (mGame.section == GAME_SECTION_PAUSE)
|
|
runPausedGame();
|
|
|
|
// Sección Game Over
|
|
if (mGame.section == GAME_SECTION_GAMEOVER)
|
|
runGameOverScreen();
|
|
|
|
// Sección juego jugando
|
|
if (mGame.section == GAME_SECTION_PLAY)
|
|
{
|
|
// Si la música no está sonando
|
|
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
|
|
{
|
|
// Reproduce la música
|
|
if (mGame.player->isAlive())
|
|
JA_PlayMusic(mMusic[MUSIC_PLAYING].music, true);
|
|
}
|
|
|
|
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
|
if (SDL_GetTicks() - mProg.ticks > mProg.ticksSpeed)
|
|
{
|
|
// Actualiza el contador de ticks
|
|
mProg.ticks = SDL_GetTicks();
|
|
|
|
// Actualiza el contador de juego
|
|
mGame.counter++;
|
|
|
|
// Comprueba los eventos que hay en la cola
|
|
while (SDL_PollEvent(mEventHandler) != 0)
|
|
{
|
|
// Evento de salida de la aplicación
|
|
if (mEventHandler->type == SDL_QUIT)
|
|
{
|
|
mProg.quit = true;
|
|
break;
|
|
}
|
|
else if ((mEventHandler->type == SDL_KEYDOWN) && (mEventHandler->key.repeat == 0))
|
|
{
|
|
if (mDebug.enabled)
|
|
{
|
|
switch (mEventHandler->key.keysym.scancode)
|
|
{
|
|
case SDL_SCANCODE_F:
|
|
mDebug.enemySet--;
|
|
if (mDebug.enemySet == 255)
|
|
mDebug.enemySet = 0;
|
|
break;
|
|
case SDL_SCANCODE_R:
|
|
mDebug.enemySet = std::min((int)++mDebug.enemySet, 9);
|
|
break;
|
|
case SDL_SCANCODE_T:
|
|
mProg.ticksSpeed *= 2;
|
|
break;
|
|
case SDL_SCANCODE_G:
|
|
createNewBalloon(100, 0, BALLOON_1, BALLOON_VELX_POSITIVE, 1.0F, 0, mTexture[TEXTURE_BALLOON].texture);
|
|
break;
|
|
case SDL_SCANCODE_P:
|
|
popAllBalloons();
|
|
//mGame.balloonsPopped += 10;
|
|
break;
|
|
case SDL_SCANCODE_Z:
|
|
incBalloonSpeed();
|
|
break;
|
|
case SDL_SCANCODE_X:
|
|
decBalloonSpeed();
|
|
break;
|
|
case SDL_SCANCODE_C:
|
|
mDebug.gradB += 10;
|
|
break;
|
|
case SDL_SCANCODE_I:
|
|
mGame.player->setInvulnerable(true);
|
|
mGame.player->setInvulnerableCounter(65000);
|
|
break;
|
|
case SDL_SCANCODE_M:
|
|
break;
|
|
case SDL_SCANCODE_N:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Actualiza la lógica del juego
|
|
updatePlayField();
|
|
}
|
|
|
|
// Cambia el destino donde se pinta todo
|
|
SDL_SetRenderTarget(mRenderer, mBackbuffer);
|
|
|
|
// Limpia la pantalla
|
|
SDL_SetRenderDrawColor(mRenderer, 0x00, 0x00, 0x00, 0xFF);
|
|
SDL_RenderClear(mRenderer);
|
|
|
|
// Dibuja los objetos
|
|
renderPlayField();
|
|
|
|
// Vuelve a usar el renderizador como destino
|
|
SDL_SetRenderTarget(mRenderer, NULL);
|
|
|
|
// Volca el contenido de la textura en el renderizador
|
|
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
|
|
|
|
renderDebugInfo();
|
|
// Actualiza la pantalla
|
|
SDL_RenderPresent(mRenderer);
|
|
}
|
|
}
|
|
|
|
quitGame();
|
|
}
|
|
|
|
// Bucle para el menu de pausa del juego
|
|
void GameDirector::runPausedGame()
|
|
{
|
|
while ((mGame.section == GAME_SECTION_PAUSE) && (mProg.section == PROG_SECTION_GAME) && (!exit()))
|
|
{
|
|
// Comprueba los eventos que hay en la cola
|
|
while (SDL_PollEvent(mEventHandler) != 0)
|
|
{
|
|
// Evento de salida de la aplicación
|
|
if (mEventHandler->type == SDL_QUIT)
|
|
{
|
|
mProg.quit = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Calcula la lógica de los objetos
|
|
if (SDL_GetTicks() - mProg.ticks > mProg.ticksSpeed)
|
|
{
|
|
// Actualiza el contador de ticks
|
|
mProg.ticks = SDL_GetTicks();
|
|
|
|
// Actualiza la lógica del menu
|
|
mMenu.pause->update();
|
|
}
|
|
|
|
// Cambia el destino donde se pinta todo
|
|
SDL_SetRenderTarget(mRenderer, mBackbuffer);
|
|
|
|
// Dibuja los objetos
|
|
renderBackground();
|
|
renderBalloons();
|
|
renderBullets();
|
|
mGame.player->render();
|
|
renderScoreBoard();
|
|
mMenu.pause->render();
|
|
|
|
// Vuelve a usar el renderizador como destino
|
|
SDL_SetRenderTarget(mRenderer, NULL);
|
|
|
|
// Volca el contenido de la textura en el renderizador
|
|
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
|
|
|
|
// Actualiza la pantalla
|
|
SDL_RenderPresent(mRenderer);
|
|
|
|
// Comprueba las entradas para el menu
|
|
checkMenuInput(mMenu.pause);
|
|
|
|
// Comprueba si se ha seleccionado algún item del menú
|
|
switch (mMenu.pause->getItemSelected())
|
|
{
|
|
case 0:
|
|
JA_PlaySound(mSound[SOUND_MENU_SELECT].sound);
|
|
mGame.section = GAME_SECTION_PLAY;
|
|
mMenu.pause->reset();
|
|
mMenu.keyPressed = false;
|
|
if (JA_GetMusicState() == JA_MUSIC_PAUSED)
|
|
{
|
|
JA_ResumeMusic();
|
|
}
|
|
break;
|
|
case 1:
|
|
JA_PlaySound(mSound[SOUND_MENU_CANCEL].sound);
|
|
setProgSection(PROG_SECTION_TITLE);
|
|
mMenu.pause->reset();
|
|
mMenu.keyPressed = false;
|
|
JA_StopMusic();
|
|
renderFade(1);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Bucle para la pantalla de instrucciones
|
|
void GameDirector::runInstructions()
|
|
{
|
|
SDL_Rect window = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
|
|
Sprite *sprite = new Sprite();
|
|
SDL_Rect rect1 = {60, 88, 16, 16}; // Disquito
|
|
SDL_Rect rect2 = {60, 104, 16, 16}; // Gavineixon
|
|
SDL_Rect rect3 = {60, 120, 16, 16}; // Pacmar
|
|
SDL_Rect rect4 = {60, 136, 16, 16}; // Time Stopper
|
|
SDL_Rect rect5 = {60, 152, 16, 16}; // Explosive
|
|
SDL_Rect rect6 = {60, 168, 16, 16}; // Coffee
|
|
SDL_Rect rect = {0, 0, 16, 16};
|
|
sprite->init(rect1, mTexture[TEXTURE_ITEMS].texture, mRenderer);
|
|
|
|
while ((mTitle.section == TITLE_SECTION_INSTRUCTIONS) && (!exit()))
|
|
{
|
|
int y = 0;
|
|
// Comprueba los eventos que hay en la cola
|
|
while (SDL_PollEvent(mEventHandler) != 0)
|
|
{
|
|
// Evento de salida de la aplicación
|
|
if (mEventHandler->type == SDL_QUIT)
|
|
{
|
|
mProg.quit = true;
|
|
break;
|
|
}
|
|
|
|
if ((mEventHandler->type == SDL_KEYDOWN) || (mEventHandler->type == SDL_JOYBUTTONDOWN))
|
|
{
|
|
JA_StopMusic();
|
|
setProgSection(PROG_SECTION_TITLE);
|
|
}
|
|
}
|
|
|
|
// Pinta en la surface el texto y los sprites
|
|
SDL_SetRenderTarget(mRenderer, mInstructionsSurface);
|
|
SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 255);
|
|
SDL_RenderClear(mRenderer);
|
|
mText.white->writeCentered(SCREEN_CENTER_X, 8, "OBJECTIVE", 0);
|
|
mText.white->writeCentered(SCREEN_CENTER_X, 24, "YOU HAVE TO POP AS MANY", 0);
|
|
mText.white->writeCentered(SCREEN_CENTER_X, 34, "BALLOONS AS YOU CAN", 0);
|
|
mText.white->writeCentered(SCREEN_CENTER_X, 48, "DIFFICULTY WILL BE INCREASED", 0);
|
|
mText.white->writeCentered(SCREEN_CENTER_X, 58, "AS YOU SCORE POINTS", 0);
|
|
mText.white->writeCentered(SCREEN_CENTER_X, 75, "ITEMS", 0);
|
|
mText.white->write(84, 92, "1.000 POINTS", 0);
|
|
mText.white->write(84, 108, "2.500 POINTS", 0);
|
|
mText.white->write(84, 124, "5.000 POINTS", 0);
|
|
mText.white->write(84, 140, "TIME STOPPER", 0);
|
|
mText.white->write(84, 156, "FOUR EXPLOSIONS", 0);
|
|
mText.white->write(84, 172, "EXTRA HIT", 0);
|
|
|
|
sprite->init(rect1, mTexture[TEXTURE_ITEMS].texture, mRenderer);
|
|
sprite->setSpriteClip(rect);
|
|
rect.x += rect.w;
|
|
rect.y = 16 * (((mTitle.instructionsCounter + 3) / 36) % 2);
|
|
sprite->render();
|
|
sprite->init(rect2, mTexture[TEXTURE_ITEMS].texture, mRenderer);
|
|
sprite->setSpriteClip(rect);
|
|
rect.x += rect.w;
|
|
rect.y = 16 * (((mTitle.instructionsCounter + 6) / 36) % 2);
|
|
sprite->render();
|
|
sprite->init(rect3, mTexture[TEXTURE_ITEMS].texture, mRenderer);
|
|
sprite->setSpriteClip(rect);
|
|
rect.x += rect.w;
|
|
rect.y = 16 * (((mTitle.instructionsCounter + 9) / 36) % 2);
|
|
sprite->render();
|
|
sprite->init(rect4, mTexture[TEXTURE_ITEMS].texture, mRenderer);
|
|
sprite->setSpriteClip(rect);
|
|
rect.x += rect.w;
|
|
rect.y = 16 * (((mTitle.instructionsCounter + 12) / 36) % 2);
|
|
sprite->render();
|
|
sprite->init(rect5, mTexture[TEXTURE_ITEMS].texture, mRenderer);
|
|
sprite->setSpriteClip(rect);
|
|
rect.x += rect.w;
|
|
rect.y = 16 * (((mTitle.instructionsCounter + 15) / 36) % 2);
|
|
sprite->render();
|
|
sprite->init(rect6, mTexture[TEXTURE_ITEMS].texture, mRenderer);
|
|
sprite->setSpriteClip(rect);
|
|
rect.x = 0;
|
|
rect.y = 16 * (((mTitle.instructionsCounter + 0) / 36) % 2);
|
|
sprite->render();
|
|
|
|
SDL_SetRenderTarget(mRenderer, nullptr);
|
|
|
|
// Limpia la pantalla
|
|
SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 255);
|
|
SDL_RenderClear(mRenderer);
|
|
|
|
// Dibuja los objetos
|
|
y = SCREEN_HEIGHT - (INSTRUCTIONS_COUNTER - mTitle.instructionsCounter) + 100;
|
|
if (y < 0)
|
|
{
|
|
y = 0;
|
|
}
|
|
|
|
window.y = y;
|
|
SDL_RenderCopy(mRenderer, mInstructionsSurface, NULL, &window);
|
|
|
|
// Muestra la pantalla
|
|
SDL_RenderPresent(mRenderer);
|
|
|
|
mTitle.instructionsCounter--;
|
|
|
|
if (mTitle.instructionsCounter == 0)
|
|
{
|
|
mTitle.instructionsCounter = INSTRUCTIONS_COUNTER;
|
|
mTitle.section = TITLE_SECTION_1;
|
|
mTitle.nextProgSection = PROG_SECTION_LOGO;
|
|
}
|
|
}
|
|
delete sprite;
|
|
}
|
|
|
|
// Bucle para la pantalla de game over
|
|
void GameDirector::runGameOverScreen()
|
|
{
|
|
while ((mGame.section == GAME_SECTION_GAMEOVER) && (mProg.section == PROG_SECTION_GAME) && (!exit()))
|
|
{
|
|
// Comprueba los eventos que hay en la cola
|
|
while (SDL_PollEvent(mEventHandler) != 0)
|
|
{
|
|
// Evento de salida de la aplicación
|
|
if (mEventHandler->type == SDL_QUIT)
|
|
{
|
|
mProg.quit = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Calcula la lógica de los objetos
|
|
if (SDL_GetTicks() - mProg.ticks > mProg.ticksSpeed)
|
|
{
|
|
// Actualiza el contador de ticks
|
|
mProg.ticks = SDL_GetTicks();
|
|
|
|
// Actualiza la lógica del menu
|
|
mMenu.gameOver->update();
|
|
}
|
|
|
|
// Cambia el destino donde se pinta todo
|
|
SDL_SetRenderTarget(mRenderer, mBackbuffer);
|
|
|
|
// Limpia la pantalla
|
|
SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 0xFF);
|
|
SDL_RenderClear(mRenderer);
|
|
|
|
// Dibuja los objetos
|
|
mText.whiteX2->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - (BLOCK * 4), "GAME OVER", 0);
|
|
mText.white->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - (BLOCK * 1), "YOUR SCORE: " + std::to_string(mGame.player->getScore()), 0);
|
|
mText.white->write(PLAY_AREA_CENTER_X - (mText.white->lenght("RETRY?", 0) / 2), PLAY_AREA_CENTER_Y + BLOCK * 2, "RETRY?", 0);
|
|
mMenu.gameOver->render();
|
|
|
|
// Vuelve a usar el renderizador como destino
|
|
SDL_SetRenderTarget(mRenderer, NULL);
|
|
|
|
// Volca el contenido de la textura en el renderizador
|
|
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
|
|
|
|
// Muestra la pantalla
|
|
SDL_RenderPresent(mRenderer);
|
|
|
|
// Comprueba las entradas para el menu
|
|
checkMenuInput(mMenu.gameOver);
|
|
|
|
// Comprueba si se ha seleccionado algún item del menú
|
|
switch (mMenu.gameOver->getItemSelected())
|
|
{
|
|
case 0:
|
|
setProgSection(PROG_SECTION_GAME);
|
|
mGame.section = GAME_SECTION_PLAY;
|
|
mMenu.gameOver->reset();
|
|
mMenu.keyPressed = false;
|
|
JA_PlaySound(mSound[SOUND_MENU_SELECT].sound);
|
|
JA_StopMusic();
|
|
renderFade(1);
|
|
disableDemoMode();
|
|
resetGame();
|
|
break;
|
|
case 1:
|
|
setProgSection(PROG_SECTION_TITLE);
|
|
mMenu.gameOver->reset();
|
|
mMenu.keyPressed = false;
|
|
JA_PlaySound(mSound[SOUND_MENU_CANCEL].sound);
|
|
JA_StopMusic();
|
|
renderFade(1);
|
|
mTitle.nextProgSection = PROG_SECTION_GAME;
|
|
enableDemoMode();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Activa el modo Demo
|
|
void GameDirector::enableDemoMode()
|
|
{
|
|
mDemo.enabled = true;
|
|
}
|
|
|
|
// Desactiva el modo Demo
|
|
void GameDirector::disableDemoMode()
|
|
{
|
|
mDemo.enabled = false;
|
|
}
|
|
|
|
// Actualiza el proximo estado del juego despues del titulo
|
|
void GameDirector::toogleTitleNextGS()
|
|
{
|
|
if (mTitle.nextProgSection == PROG_SECTION_LOGO)
|
|
mTitle.nextProgSection = PROG_SECTION_GAME;
|
|
else
|
|
mTitle.nextProgSection = PROG_SECTION_LOGO;
|
|
}
|
|
|
|
// Dibuja la informacion de debug en pantalla
|
|
void GameDirector::renderDebugInfo()
|
|
{
|
|
if (mDebug.enabled)
|
|
{
|
|
Uint8 R = 0xFF;
|
|
Uint8 G = 0x20;
|
|
Uint8 B = 0x20;
|
|
|
|
SDL_RenderSetLogicalSize(mRenderer, SCREEN_WIDTH * 2, SCREEN_HEIGHT * 2);
|
|
|
|
mText.white->writeShadowed(2, 2 + 0 * BLOCK, "menace(umb): " + std::to_string(mGame.menaceCurrent) + "(" + std::to_string(mGame.menaceThreshold) + ")", R, G, B);
|
|
mText.white->writeShadowed(2, 2 + 1 * BLOCK, "currentPower: " + std::to_string(mGame.stage[mGame.currentStage].currentPower), R, G, B);
|
|
mText.white->writeShadowed(2, 2 + 2 * BLOCK, "currentStage: " + std::to_string(mGame.currentStage), R, G, B);
|
|
mText.white->writeShadowed(2, 2 + 3 * BLOCK, "counter: " + std::to_string(mGame.counter), R, G, B);
|
|
mText.white->writeShadowed(2, 2 + 4 * BLOCK, "(R)enemyset: " + std::to_string(mDebug.enemySet), R, G, B);
|
|
mText.white->writeShadowed(2, 2 + 5 * BLOCK, "RGB: " + std::to_string(mDebug.gradR) + "," + std::to_string(mDebug.gradG) + "," + std::to_string(mDebug.gradB), R, G, B);
|
|
mText.white->writeShadowed(2, 2 + 6 * BLOCK, "(I)invuln : " + std::to_string(mGame.player->getInvulnerableCounter()), R, G, B);
|
|
mText.white->writeShadowed(2, 2 + 7 * BLOCK, "balloons: " + std::to_string(countBalloons()), R, G, B);
|
|
mText.white->writeShadowed(2, 2 + 8 * BLOCK, "balloonsPop: " + std::to_string(mGame.balloonsPopped), R, G, B);
|
|
mText.white->writeShadowed(2, 2 + 9 * BLOCK, "(Z-X)ballSped:" + std::to_string(mGame.enemySpeed), R, G, B);
|
|
}
|
|
} |