diff --git a/source/const.h b/source/const.h index 10e8cd6..ee544dd 100644 --- a/source/const.h +++ b/source/const.h @@ -8,8 +8,8 @@ #define CONST_H // Textos -#define WINDOW_CAPTION "Coffee Crisis" -#define TEXT_COPYRIGHT "@2020,2021 JailDesigner (v2.0.1)" +#define WINDOW_CAPTION "Pepe el Cazavampiros" +#define TEXT_COPYRIGHT "@2021 JailDesigner (v0.1)" // Recursos #define BINFILE_SCORE 0 diff --git a/source/director.cpp b/source/director.cpp index dca9901..a676bcb 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -3,10 +3,6 @@ #include "director.h" #include #include -#ifdef __MIPSEL__ -#include -#include -#endif // Constructor Director::Director(std::string path) @@ -18,7 +14,7 @@ Director::Director(std::string path) setFileList(); // Si falta algún fichero no inicies el programa - Uint8 section = PROG_SECTION_LOGO; + Uint8 section = PROG_SECTION_GAME; if (!checkFileList()) section = PROG_SECTION_QUIT; @@ -53,18 +49,6 @@ Director::Director(std::string path) SDL_SetWindowSize(mWindow, SCREEN_WIDTH * mOptions->windowSize, SCREEN_HEIGHT * mOptions->windowSize); mLang->setLang(mOptions->language); -#ifdef __MIPSEL__ - DIR *dir = opendir("/media/data/local/home/.coffee_crisis"); - if (dir) - { - closedir(dir); - } - else if (ENOENT == errno) - { - int status = mkdir("/media/data/local/home/.coffee_crisis", 755); - } -#endif - // Inicializa el resto de variables init(section); } @@ -107,17 +91,11 @@ void Director::init(Uint8 name) mInput->bindKey(INPUT_RIGHT, SDL_SCANCODE_RIGHT); mInput->bindKey(INPUT_ACCEPT, SDL_SCANCODE_RETURN); mInput->bindKey(INPUT_CANCEL, SDL_SCANCODE_ESCAPE); -#ifdef __MIPSEL__ - mInput->bindKey(INPUT_BUTTON_1, SDL_SCANCODE_LSHIFT); - mInput->bindKey(INPUT_BUTTON_2, SDL_SCANCODE_SPACE); - mInput->bindKey(INPUT_BUTTON_3, SDL_SCANCODE_LCTRL); -#else - mInput->bindKey(INPUT_BUTTON_1, SDL_SCANCODE_Q); - mInput->bindKey(INPUT_BUTTON_2, SDL_SCANCODE_W); - mInput->bindKey(INPUT_BUTTON_3, SDL_SCANCODE_E); -#endif - mInput->bindKey(INPUT_BUTTON_PAUSE, SDL_SCANCODE_ESCAPE); // PAUSE - mInput->bindKey(INPUT_BUTTON_ESCAPE, SDL_SCANCODE_ESCAPE); // ESCAPE + mInput->bindKey(INPUT_BUTTON_1, SDL_SCANCODE_Z); + mInput->bindKey(INPUT_BUTTON_2, SDL_SCANCODE_X); + mInput->bindKey(INPUT_BUTTON_3, SDL_SCANCODE_C); + mInput->bindKey(INPUT_BUTTON_PAUSE, SDL_SCANCODE_ESCAPE); + mInput->bindKey(INPUT_BUTTON_ESCAPE, SDL_SCANCODE_ESCAPE); mInput->bindGameControllerButton(INPUT_UP, SDL_CONTROLLER_BUTTON_DPAD_UP); mInput->bindGameControllerButton(INPUT_DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN); @@ -128,8 +106,8 @@ void Director::init(Uint8 name) mInput->bindGameControllerButton(INPUT_BUTTON_1, SDL_CONTROLLER_BUTTON_X); mInput->bindGameControllerButton(INPUT_BUTTON_2, SDL_CONTROLLER_BUTTON_Y); mInput->bindGameControllerButton(INPUT_BUTTON_3, SDL_CONTROLLER_BUTTON_B); - mInput->bindGameControllerButton(INPUT_BUTTON_PAUSE, SDL_CONTROLLER_BUTTON_GUIDE); // PAUSE - mInput->bindGameControllerButton(INPUT_BUTTON_ESCAPE, SDL_CONTROLLER_BUTTON_GUIDE); // ESCAPE + mInput->bindGameControllerButton(INPUT_BUTTON_PAUSE, SDL_CONTROLLER_BUTTON_GUIDE); + mInput->bindGameControllerButton(INPUT_BUTTON_ESCAPE, SDL_CONTROLLER_BUTTON_GUIDE); } // Inicializa JailAudio @@ -208,15 +186,9 @@ void Director::setFileList() mFileList[i] = ""; // Ficheros binarios -#ifdef __MIPSEL__ - mFileList[0] = "/media/data/local/home/.coffee_crisis/score.bin"; - mFileList[1] = "/media/data/local/home/.coffee_crisis/demo.bin"; - mFileList[2] = "/media/data/local/home/.coffee_crisis/config.bin"; -#else mFileList[0] = mExecutablePath + "/" + "../data/score.bin"; mFileList[1] = mExecutablePath + "/" + "../data/demo.bin"; mFileList[2] = mExecutablePath + "/" + "../data/config.bin"; -#endif // Musicas mFileList[3] = mExecutablePath + "/" + "../media/music/intro.ogg"; @@ -485,33 +457,18 @@ void Director::setSection(section_t section) void Director::runLogo() { - mLogo = new Logo(mRenderer, mFileList); - setSection(mLogo->run()); - delete mLogo; } void Director::runIntro() { - mIntro = new Intro(mRenderer, mFileList, mLang); - setSection(mIntro->run()); - delete mIntro; } void Director::runTitle() { - mTitle = new Title(mWindow, mRenderer, mInput, mFileList, mOptions, mLang); - setSection(mTitle->run(mSection.subsection)); - delete mTitle; } void Director::runGame() { - if (mSection.subsection == GAME_SECTION_PLAY_1P) - mGame = new Game(1, mRenderer, mFileList, mLang, mInput, false, mOptions); - if (mSection.subsection == GAME_SECTION_PLAY_2P) - mGame = new Game(2, mRenderer, mFileList, mLang, mInput, false, mOptions); - setSection(mGame->run()); - delete mGame; } void Director::run() diff --git a/source/director.h b/source/director.h index 0d23e60..06b2c5a 100644 --- a/source/director.h +++ b/source/director.h @@ -3,24 +3,14 @@ #include "sprite.h" #include "movingsprite.h" #include "smartsprite.h" -#include "player.h" -#include "balloon.h" -#include "bullet.h" -#include "coffeedrop.h" -#include "item.h" #include "text.h" #include "writer.h" #include "menu.h" #include "const.h" #include "jail_audio.h" #include "utils.h" -#include "logo.h" -#include "intro.h" -#include "title.h" -#include "game.h" #include "input.h" #include "fade.h" -//#include #ifndef DIRECTOR_H #define DIRECTOR_H @@ -34,10 +24,6 @@ private: SDL_Window *mWindow; // La ventana donde dibujamos SDL_Renderer *mRenderer; // El renderizador de la ventana - Logo *mLogo; // Objeto para la sección del logo - Intro *mIntro; // Objeto para la sección de la intro - Title *mTitle; // Objeto para la sección del titulo y el menu de opciones - Game *mGame; // Objeto para la sección del juego Input *mInput; // Objeto Input para gestionar las entradas Lang *mLang; // Objeto para gestionar los textos en diferentes idiomas diff --git a/source/fade.cpp b/source/fade.cpp index 17a96de..21fa3ee 100644 --- a/source/fade.cpp +++ b/source/fade.cpp @@ -25,9 +25,6 @@ void Fade::init(Uint8 r, Uint8 g, Uint8 b) mEnabled = false; mFinished = false; mCounter = 0; - //mR = 0x27; - //mG = 0x27; - //mB = 0x36; mR = r; mG = g; mB = b; diff --git a/source/game.cpp b/source/game.cpp index e35e889..a18f64a 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -5,294 +5,40 @@ #endif // Constructor -Game::Game(int numPlayers, SDL_Renderer *renderer, std::string *filelist, Lang *lang, Input *input, bool demo, options_t *options) +Game::Game(SDL_Renderer *renderer, std::string *filelist, Lang *lang, Input *input) { // Copia los punteros mRenderer = renderer; mFileList = filelist; mLang = lang; mInput = input; - mOptions = options; - mOnePlayerControl = mOptions->input[0].deviceType; - - // Pasa variables - mDemo.enabled = demo; - mNumPlayers = numPlayers; - if (mNumPlayers == 1) - mOptions->input[0].deviceType = INPUT_USE_ANY; - mDifficulty = mOptions->difficulty; - - // Crea los objetos - for (int i = 0; i < mNumPlayers; i++) - mPlayer[i] = new Player(); - for (int i = 0; i < MAX_BALLOONS; i++) - mBalloon[i] = new Balloon(); - for (int i = 0; i < MAX_BULLETS; i++) - mBullet[i] = new Bullet(); - for (int i = 0; i < MAX_ITEMS; i++) - mItem[i] = new Item(); - for (int i = 0; i < MAX_SMART_SPRITES; i++) - mSmartSprite[i] = new SmartSprite(); - - mTextureBalloon = new LTexture(); - mTextureBullet = new LTexture(); - mTextureGameBG = new LTexture(); - mTextureGameText = new LTexture(); - mTextureItems = new LTexture(); - mTexturePlayer1Head = new LTexture(); - mTexturePlayer1Body = new LTexture(); - mTexturePlayer1Death = new LTexture(); - mTexturePlayer1Legs = new LTexture(); - mTexturePlayer2Head = new LTexture(); - mTexturePlayer2Body = new LTexture(); - mTexturePlayer2Death = new LTexture(); - mTexturePlayer2Legs = new LTexture(); mTextureText = new LTexture(); - mTextureTextScoreBoard = new LTexture(); - mTextureTextBig = new LTexture(); - mTextureTextNokia2 = new LTexture(); - mTextureTextNokiaBig2 = new LTexture(); mText = new Text(mFileList[48], mTextureText, mRenderer); - mTextScoreBoard = new Text(mFileList[46], mTextureTextScoreBoard, mRenderer); - mTextBig = new Text(mFileList[47], mTextureTextBig, mRenderer); - mTextNokia2 = new Text(mFileList[57], mTextureTextNokia2, mRenderer); - mTextNokiaBig2 = new Text(mFileList[55], mTextureTextNokiaBig2, mRenderer); - - mMenuGameOver = new Menu(mRenderer, mText, mInput, mFileList); - mMenuPause = new Menu(mRenderer, mText, mInput, mFileList); mFade = new Fade(mRenderer); mEventHandler = new SDL_Event(); - - mClouds1a = new MovingSprite(); - mClouds1b = new MovingSprite(); - mClouds2a = new MovingSprite(); - mClouds2b = new MovingSprite(); - m1000Bitmap = new SmartSprite(); - m2500Bitmap = new SmartSprite(); - m5000Bitmap = new SmartSprite(); - mSpriteBackground = new Sprite(); - mSpriteGetReady = new Sprite(); - mSpriteGradient = new Sprite(); - mSpriteGrass = new Sprite(); - mSpritePowerMeter = new Sprite(); - mSpriteScoreBoard = new Sprite(); - -#ifdef __MIPSEL__ - DIR *dir = opendir("/media/data/local/home/.coffee_crisis"); - if (dir) - { - closedir(dir); - } - else if (ENOENT == errno) - { - int status = mkdir("/media/data/local/home/.coffee_crisis", 755); - } -#endif } Game::~Game() { - saveScoreFile(); - saveDemoFile(); - - mOptions->input[0].deviceType = mOnePlayerControl; - mRenderer = nullptr; mFileList = nullptr; mLang = nullptr; mInput = nullptr; - for (int i = 0; i < mNumPlayers; i++) - { - delete mPlayer[i]; - mPlayer[i] = nullptr; - } - for (int i = 0; i < MAX_BALLOONS; i++) - { - delete mBalloon[i]; - mBalloon[i] = nullptr; - } - for (int i = 0; i < MAX_BULLETS; i++) - { - delete mBullet[i]; - mBullet[i] = nullptr; - } - for (int i = 0; i < MAX_ITEMS; i++) - { - delete mItem[i]; - mItem[i] = nullptr; - } - for (int i = 0; i < MAX_SMART_SPRITES; i++) - { - delete mSmartSprite[i]; - mSmartSprite[i] = nullptr; - } - - mTextureBalloon->unload(); - delete mTextureBalloon; - mTextureBalloon = nullptr; - - mTextureBullet->unload(); - delete mTextureBullet; - mTextureBullet = nullptr; - - mTextureGameBG->unload(); - delete mTextureGameBG; - mTextureGameBG = nullptr; - - mTextureGameText->unload(); - delete mTextureGameText; - mTextureGameText = nullptr; - - mTextureItems->unload(); - delete mTextureItems; - mTextureItems = nullptr; - - mTexturePlayer1Head->unload(); - delete mTexturePlayer1Head; - mTexturePlayer1Head = nullptr; - - mTexturePlayer1Body->unload(); - delete mTexturePlayer1Body; - mTexturePlayer1Body = nullptr; - - mTexturePlayer1Death->unload(); - delete mTexturePlayer1Death; - mTexturePlayer1Death = nullptr; - - mTexturePlayer1Legs->unload(); - delete mTexturePlayer1Legs; - mTexturePlayer1Legs = nullptr; - - mTexturePlayer2Head->unload(); - delete mTexturePlayer2Head; - mTexturePlayer2Head = nullptr; - - mTexturePlayer2Body->unload(); - delete mTexturePlayer2Body; - mTexturePlayer2Body = nullptr; - - mTexturePlayer2Death->unload(); - delete mTexturePlayer2Death; - mTexturePlayer2Death = nullptr; - - mTexturePlayer2Legs->unload(); - delete mTexturePlayer2Legs; - mTexturePlayer2Legs = nullptr; - mTextureText->unload(); delete mTextureText; mTextureText = nullptr; - mTextureTextScoreBoard->unload(); - delete mTextureTextScoreBoard; - mTextureTextScoreBoard = nullptr; - - mTextureTextBig->unload(); - delete mTextureTextBig; - mTextureTextBig = nullptr; - - mTextureTextNokia2->unload(); - delete mTextureTextNokia2; - mTextureTextNokia2 = nullptr; - - mTextureTextNokiaBig2->unload(); - delete mTextureTextNokiaBig2; - mTextureTextNokiaBig2 = nullptr; - delete mText; mText = nullptr; - delete mTextBig; - mTextBig = nullptr; - - delete mTextScoreBoard; - mTextScoreBoard = nullptr; - - delete mTextNokia2; - mTextNokia2 = nullptr; - - delete mTextNokiaBig2; - mTextNokiaBig2 = nullptr; - - delete mMenuGameOver; - mMenuGameOver = nullptr; - - delete mMenuPause; - mMenuPause = nullptr; - delete mFade; mFade = nullptr; delete mEventHandler; mEventHandler = nullptr; - - delete mClouds1a; - mClouds1a = nullptr; - - delete mClouds1b; - mClouds1b = nullptr; - - delete mClouds2a; - mClouds2a = nullptr; - - delete mClouds2b; - mClouds2b = nullptr; - - delete m1000Bitmap; - m1000Bitmap = nullptr; - - delete m2500Bitmap; - m2500Bitmap = nullptr; - - delete m5000Bitmap; - m5000Bitmap = nullptr; - - delete mSpriteBackground; - mSpriteBackground = nullptr; - - delete mSpriteGetReady; - mSpriteGetReady = nullptr; - - delete mSpriteGradient; - mSpriteGradient = nullptr; - - delete mSpriteGrass; - mSpriteGrass = nullptr; - - delete mSpritePowerMeter; - mSpritePowerMeter = nullptr; - - delete mSpriteScoreBoard; - mSpriteScoreBoard = nullptr; - - JA_DeleteSound(mSoundBalloon); - JA_DeleteSound(mSoundBullet); - JA_DeleteSound(mSoundPlayerCollision); - JA_DeleteSound(mSoundHiScore); - JA_DeleteSound(mSoundItemDrop); - JA_DeleteSound(mSoundItemPickup); - JA_DeleteSound(mSoundCoffeeOut); - JA_DeleteSound(mSoundStageChange); - JA_DeleteSound(mSoundBubble1); - JA_DeleteSound(mSoundBubble2); - JA_DeleteSound(mSoundBubble3); - JA_DeleteSound(mSoundBubble4); - JA_DeleteSound(mSoundClock); - JA_DeleteSound(mSoundPowerBall); - JA_DeleteSound(mSoundCollision); - - JA_DeleteMusic(mMusicPlaying); -} - -// Inicializa el vector con los valores del seno -void Game::initSin() -{ - // Vector con los valores del seno para 360 grados - for (int i = 0; i < 360; i++) - mSin[i] = SDL_sinf((float)i * 3.14f / 180.0f); } // Inicializa las variables necesarias para la sección 'Game' @@ -535,2562 +281,6 @@ void Game::init() mGradientRect[3] = {256, 384, SCREEN_WIDTH, SCREEN_HEIGHT}; } -// Carga los recursos necesarios para la sección 'Game' -bool Game::loadMedia() -{ - bool success = true; - - // Texturas - success &= loadTextureFromFile(mTextureText, mFileList[30], mRenderer); - success &= loadTextureFromFile(mTextureTextScoreBoard, mFileList[27], mRenderer); - success &= loadTextureFromFile(mTextureTextBig, mFileList[29], mRenderer); - success &= loadTextureFromFile(mTextureTextNokia2, mFileList[56], mRenderer); - success &= loadTextureFromFile(mTextureTextNokiaBig2, mFileList[54], mRenderer); - - success &= loadTextureFromFile(mTexturePlayer1Legs, mFileList[39], mRenderer); - success &= loadTextureFromFile(mTexturePlayer1Head, mFileList[41], mRenderer); - success &= loadTextureFromFile(mTexturePlayer1Body, mFileList[37], mRenderer); - success &= loadTextureFromFile(mTexturePlayer1Death, mFileList[38], mRenderer); - - success &= loadTextureFromFile(mTexturePlayer2Legs, mFileList[44], mRenderer); - success &= loadTextureFromFile(mTexturePlayer2Head, mFileList[45], mRenderer); - success &= loadTextureFromFile(mTexturePlayer2Body, mFileList[42], mRenderer); - success &= loadTextureFromFile(mTexturePlayer2Death, mFileList[43], mRenderer); - - success &= loadTextureFromFile(mTextureBalloon, mFileList[24], mRenderer); - success &= loadTextureFromFile(mTextureBullet, mFileList[25], mRenderer); - success &= loadTextureFromFile(mTextureGameBG, mFileList[31], mRenderer); - success &= loadTextureFromFile(mTextureItems, mFileList[34], mRenderer); - success &= loadTextureFromFile(mTextureGameText, mFileList[32], mRenderer); - - // Sonidos - mSoundBalloon = JA_LoadSound(mFileList[6].c_str()); - mSoundBubble1 = JA_LoadSound(mFileList[7].c_str()); - mSoundBubble2 = JA_LoadSound(mFileList[8].c_str()); - mSoundBubble3 = JA_LoadSound(mFileList[9].c_str()); - mSoundBubble4 = JA_LoadSound(mFileList[10].c_str()); - mSoundBullet = JA_LoadSound(mFileList[11].c_str()); - mSoundClock = JA_LoadSound(mFileList[22].c_str()); - mSoundCoffeeOut = JA_LoadSound(mFileList[12].c_str()); - mSoundHiScore = JA_LoadSound(mFileList[13].c_str()); - mSoundItemDrop = JA_LoadSound(mFileList[14].c_str()); - mSoundItemPickup = JA_LoadSound(mFileList[15].c_str()); - mSoundPlayerCollision = JA_LoadSound(mFileList[19].c_str()); - mSoundPowerBall = JA_LoadSound(mFileList[23].c_str()); - mSoundStageChange = JA_LoadSound(mFileList[20].c_str()); - mSoundCollision = JA_LoadSound(mFileList[21].c_str()); - - // Musicas - mMusicPlaying = JA_LoadMusic(mFileList[4].c_str()); - - return success; -} - -// Carga el fichero de puntos -bool Game::loadScoreFile() -{ - // Indicador de éxito en la carga - bool success = true; - const std::string p = mFileList[0]; - const 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) - { - mScoreDataFile[i] = 0; - SDL_RWwrite(file, &mScoreDataFile[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, &mScoreDataFile[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 (mScoreDataFile[0] == 0) - mHiScore = 10000; - // Comprueba el checksum para ver si se ha modificado el fichero - else if (mScoreDataFile[0] % 43 == mScoreDataFile[1]) - mHiScore = mScoreDataFile[0]; - else - mHiScore = 10000; - - return success; -} - -// Carga el fichero de datos para la demo -bool Game::loadDemoFile() -{ - // Indicador de éxito en la carga - bool success = true; - const std::string p = mFileList[1]; - const 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 Game::saveScoreFile() -{ - bool success = true; - const std::string p = mFileList[0]; - const 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, &mScoreDataFile[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 datos para la demo -bool Game::saveDemoFile() -{ - bool success = true; - const std::string p = mFileList[1]; - const 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; -} - -// Inicializa las formaciones enemigas -void Game::initEnemyFormations() -{ - const int y4 = (PLAY_AREA_TOP - BLOCK); - const int x4_0 = PLAY_AREA_LEFT; - const int x4_100 = (PLAY_AREA_RIGHT)-BALLOON_WIDTH_4; - - const int y3 = (PLAY_AREA_TOP - BLOCK); - const int x3_0 = PLAY_AREA_LEFT; - const int x3_100 = (PLAY_AREA_RIGHT)-BALLOON_WIDTH_3; - - const int y2 = (PLAY_AREA_TOP - BLOCK); - const int x2_0 = PLAY_AREA_LEFT; - const int x2_100 = (PLAY_AREA_RIGHT)-BALLOON_WIDTH_2; - - const int y1 = (PLAY_AREA_TOP - BLOCK); - const int x1_0 = PLAY_AREA_LEFT; - const int x1_50 = PLAY_AREA_CENTER_X - (BALLOON_WIDTH_1 / 2); - const int x1_100 = (PLAY_AREA_RIGHT)-BALLOON_WIDTH_1; - - // Inicializa a cero las variables - for (int i = 0; i < NUMBER_OF_ENEMY_FORMATIONS; i++) - { - mEnemyFormation[i].numberOfEnemies = 0; - for (int j = 0; j < MAX_NUMBER_OF_ENEMIES_IN_A_FORMATION; j++) - { - mEnemyFormation[i].init[j].x = 0; - mEnemyFormation[i].init[j].y = 0; - mEnemyFormation[i].init[j].velX = 0; - mEnemyFormation[i].init[j].kind = 0; - mEnemyFormation[i].init[j].creationCounter = 0; - } - } - - 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 (int 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 (int i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = PLAY_AREA_CENTER_FIRST_QUARTER_X - (BALLOON_WIDTH_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_WIDTH_2 + 1; - incTime = 10; - for (int 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_WIDTH_2 + 1; - incTime = 10; - for (int 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_WIDTH_3 * 2; - incTime = 10; - for (int 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_WIDTH_3 * 2; - incTime = 10; - for (int 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_WIDTH_3 + 1; - incTime = 10; - for (int 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_WIDTH_3 + 1; - incTime = 10; - for (int 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_WIDTH_1 + 1; - incTime = 10; - for (int 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_WIDTH_1 + 1; - incTime = 10; - for (int 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_WIDTH_4 + 1; - incTime = 15; - for (int 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_WIDTH_4 + 1; - incTime = 15; - for (int 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_WIDTH_2 + 1; - incTime = 10; - for (int 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_WIDTH_2 + 1; - incTime = 10; - for (int 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_WIDTH_3 * 2; - incTime = 10; - for (int 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_WIDTH_3 * 2; - incTime = 10; - for (int 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_WIDTH_3 + 1; - incTime = 10; - for (int 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_WIDTH_3 + 1; - incTime = 10; - for (int 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_WIDTH_1 + 1; - incTime = 10; - for (int 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_WIDTH_1 + 1; - incTime = 10; - for (int 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_WIDTH_4 + 1; - incTime = 0; - for (int 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_WIDTH_2 + 1; - incTime = 3; - for (int 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_WIDTH_3 * 2; - incTime = 10; - for (int 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_WIDTH_3 + 1; - incTime = 10; - for (int 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 (int 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_WIDTH_1 + 1; - incTime = 5; - for (int 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 (int k = 0; k < j + 1; k++) - { - mEnemyFormation[k + 50].numberOfEnemies = mEnemyFormation[k].numberOfEnemies; - for (int 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 Game::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 Game::initGameStages() -{ - // STAGE 1 - mStage[0].number = 1; - mStage[0].currentPower = 0; - mStage[0].powerToComplete = 200; - mStage[0].minMenace = 7 + (4 * 1); - mStage[0].maxMenace = 7 + (4 * 3); - mStage[0].enemyPool = &mEnemyPool[0]; - - // STAGE 2 - mStage[1].number = 2; - mStage[1].currentPower = 0; - mStage[1].powerToComplete = 300; - mStage[1].minMenace = 7 + (4 * 2); - mStage[1].maxMenace = 7 + (4 * 4); - mStage[1].enemyPool = &mEnemyPool[1]; - - // STAGE 3 - mStage[2].number = 3; - mStage[2].currentPower = 0; - mStage[2].powerToComplete = 600; - mStage[2].minMenace = 7 + (4 * 3); - mStage[2].maxMenace = 7 + (4 * 6); - mStage[2].enemyPool = &mEnemyPool[2]; - - // STAGE 4 - mStage[3].number = 4; - mStage[3].currentPower = 0; - mStage[3].powerToComplete = 600; - mStage[3].minMenace = 7 + (4 * 3); - mStage[3].maxMenace = 7 + (4 * 7); - mStage[3].enemyPool = &mEnemyPool[3]; - - // STAGE 5 - mStage[4].number = 5; - mStage[4].currentPower = 0; - mStage[4].powerToComplete = 600; - mStage[4].minMenace = 7 + (4 * 4); - mStage[4].maxMenace = 7 + (4 * 8); - mStage[4].enemyPool = &mEnemyPool[4]; - - // STAGE 6 - mStage[5].number = 6; - mStage[5].currentPower = 0; - mStage[5].powerToComplete = 600; - mStage[5].minMenace = 7 + (4 * 5); - mStage[5].maxMenace = 7 + (4 * 10); - mStage[5].enemyPool = &mEnemyPool[5]; - - // STAGE 7 - mStage[6].number = 7; - mStage[6].currentPower = 0; - mStage[6].powerToComplete = 650; - mStage[6].minMenace = 7 + (4 * 6); - mStage[6].maxMenace = 7 + (4 * 11); - mStage[6].enemyPool = &mEnemyPool[6]; - - // STAGE 8 - mStage[7].number = 8; - mStage[7].currentPower = 0; - mStage[7].powerToComplete = 750; - mStage[7].minMenace = 7 + (4 * 7); - mStage[7].maxMenace = 7 + (4 * 12); - mStage[7].enemyPool = &mEnemyPool[7]; - - // STAGE 9 - mStage[8].number = 9; - mStage[8].currentPower = 0; - mStage[8].powerToComplete = 850; - mStage[8].minMenace = 7 + (4 * 8); - mStage[8].maxMenace = 7 + (4 * 13); - mStage[8].enemyPool = &mEnemyPool[8]; - - // STAGE 10 - mStage[9].number = 10; - mStage[9].currentPower = 0; - mStage[9].powerToComplete = 950; - mStage[9].minMenace = 7 + (4 * 9); - mStage[9].maxMenace = 7 + (4 * 15); - mStage[9].enemyPool = &mEnemyPool[9]; -} - -// Crea una formación de enemigos -void Game::deployEnemyFormation() -{ - // Solo despliega una formación enemiga si ha pasado cierto tiempo desde la última - if (mEnemyDeployCounter == 0) - { - - // En este punto se decide entre crear una powerball o una formación enemiga - if ((rand() % 100 < 15) && (canPowerBallBeCreated())) - { - // Crea una powerball - createPowerBall(); - - // Da un poco de margen para que se creen mas enemigos - mEnemyDeployCounter = 50; - } - else - { - // Decrementa el contador de despliegues enemigos de la PowerBall - mPowerBallCounter > 0 ? mPowerBallCounter-- : mPowerBallCounter = 0; - - // Elige una formación enemiga la azar - Uint8 set = (rand() % 10); - - // Evita repetir la ultima formación enemiga desplegada - if (set == mLastEnemyDeploy) - ++set %= 10; - - mLastEnemyDeploy = set; - - if (mDebug.enabled) - set = mDebug.enemySet; - - Uint8 numEnemies = mStage[mCurrentStage].enemyPool->set[set]->numberOfEnemies; - for (int i = 0; i < numEnemies; i++) - createNewBalloon(mStage[mCurrentStage].enemyPool->set[set]->init[i].x, - mStage[mCurrentStage].enemyPool->set[set]->init[i].y, - mStage[mCurrentStage].enemyPool->set[set]->init[i].kind, - mStage[mCurrentStage].enemyPool->set[set]->init[i].velX, - mEnemySpeed, - mStage[mCurrentStage].enemyPool->set[set]->init[i].creationCounter, - mTextureBalloon); - - mEnemyDeployCounter = 255; - } - } -} - -// Aumenta el poder de la fase -void Game::increaseStageCurrentPower(Uint8 power) -{ - mStage[mCurrentStage].currentPower += power; -} - -// Establece el valor de la variable -/*void Game::setScore(Uint32 score) -{ - mScore = score; -}*/ - -// Establece el valor de la variable -void Game::setHiScore(Uint32 score) -{ - mHiScore = score; -} - -// Actualiza el valor de mHiScore en caso necesario -void Game::updateHiScore() -{ - // Si la puntuación actual es mayor que la máxima puntuación - for (int i = 0; i < mNumPlayers; i++) - if (mPlayer[i]->getScore() > mHiScore) - { - // Actualiza la máxima puntuación - mHiScore = mPlayer[i]->getScore(); - - // Almacena la máxima puntuación en el fichero junto con un checksum - mScoreDataFile[0] = mHiScore; - mScoreDataFile[1] = mHiScore % 43; - - // Si se supera la máxima puntuación emite sonido - if (mHiScoreAchieved == false) - { - mHiScoreAchieved = true; - JA_PlaySound(mSoundHiScore); - } - } -} - -// Transforma un valor numérico en una cadena de 6 cifras -std::string Game::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 Game::renderScoreBoard() -{ - //color_t color = {0, 0, 0}; - - // Si el jugador esta muerto, no pintes el fondo del marcador, así que pase por encima cuando sale despedido - //if (mPlayer[0]->isAlive()) - mSpriteScoreBoard->render(); - /* - // SCORE - mText->writeCentered(PLAY_AREA_CENTER_FIRST_QUARTER_X, SCORE_WORD_Y - 6, mLang->getText(39), 0); - mText->writeCentered(PLAY_AREA_CENTER_FIRST_QUARTER_X, SCORE_NUMBER_Y - 6, updateScoreText(mPlayer[0]->getScore()), 0); - - // HI-SCORE - mText->writeCentered(PLAY_AREA_CENTER_THIRD_QUARTER_X, HISCORE_WORD_Y - 6, mLang->getText(40), 0); - mText->writeCentered(PLAY_AREA_CENTER_THIRD_QUARTER_X, HISCORE_NUMBER_Y - 6, updateScoreText(mHiScore), 0); - - // MULT - color.g = 255; - mText->writeColored(MULTIPLIER_WORD_X, MULTIPLIER_WORD_Y - 6, mLang->getText(41), color); - - color.g = 192; - mTextX2->writeShadowed(PLAY_AREA_CENTER_X - 16, SCORE_WORD_Y + 5, std::to_string(mPlayer[0]->getScoreMultiplier()).substr(0, 1), color, 1); - mText->writeShadowed(PLAY_AREA_CENTER_X - 2, SCORE_WORD_Y + 12, ".", color); - mText->writeShadowed(PLAY_AREA_CENTER_X + 4, SCORE_WORD_Y + 12, std::to_string(mPlayer[0]->getScoreMultiplier()).substr(2, 1), color); - - // STAGE - mText->writeCentered(PLAY_AREA_CENTER_FIRST_QUARTER_X, SCORE_NUMBER_Y + 4, mLang->getText(42) + std::to_string(mStage[mCurrentStage].number), 0); - - // POWER - mSpritePowerMeter->setSpriteClip(256, 184, 40, 8); - mSpritePowerMeter->render(); - const float percent = (mStage[mCurrentStage].currentPower * 40.0f) / mStage[mCurrentStage].powerToComplete; - mSpritePowerMeter->setSpriteClip(296, 184, (int)percent, 8); - mSpritePowerMeter->render(); - */ - const int offset1 = 162; - const int offset2 = offset1 + 7; - const int offset3 = offset2 + 7; - const int offset4 = offset3 + 7; - - const int offsetLeft = PLAY_AREA_LEFT + 45; - const int offsetRight = PLAY_AREA_RIGHT - 45; - - // PLAYER1 - SCORE - mTextScoreBoard->writeCentered(offsetLeft, offset1, mLang->getText(53)); - mTextScoreBoard->writeCentered(offsetLeft, offset2, updateScoreText(mPlayer[0]->getScore())); - - // PLAYER1 - MULT - mTextScoreBoard->writeCentered(offsetLeft, offset3, mLang->getText(55)); - mTextScoreBoard->writeCentered(offsetLeft, offset4, std::to_string(mPlayer[0]->getScoreMultiplier()).substr(0, 3)); - - if (mNumPlayers == 2) - { - // PLAYER2 - SCORE - mTextScoreBoard->writeCentered(offsetRight, offset1, mLang->getText(54)); - mTextScoreBoard->writeCentered(offsetRight, offset2, updateScoreText(mPlayer[1]->getScore())); - - // PLAYER2 - MULT - mTextScoreBoard->writeCentered(offsetRight, offset3, mLang->getText(55)); - mTextScoreBoard->writeCentered(offsetRight, offset4, std::to_string(mPlayer[1]->getScoreMultiplier()).substr(0, 3)); - } - else - { - // PLAYER2 - SCORE - mTextScoreBoard->writeCentered(offsetRight, offset1, mLang->getText(54)); - mTextScoreBoard->writeCentered(offsetRight, offset2, "0000000"); - - // PLAYER2 - MULT - mTextScoreBoard->writeCentered(offsetRight, offset3, mLang->getText(55)); - mTextScoreBoard->writeCentered(offsetRight, offset4, "1.0"); - } - - // STAGE - mTextScoreBoard->writeCentered(PLAY_AREA_CENTER_X, offset1, mLang->getText(57) + std::to_string(mStage[mCurrentStage].number)); - - // POWER - mSpritePowerMeter->setPosY(offset2); - mSpritePowerMeter->setSpriteClip(256, 184, 40, 8); - mSpritePowerMeter->render(); - const float percent = (mStage[mCurrentStage].currentPower * 40.0f) / mStage[mCurrentStage].powerToComplete; - mSpritePowerMeter->setSpriteClip(296, 184, (int)percent, 8); - mSpritePowerMeter->render(); - - // HI-SCORE - mTextScoreBoard->writeCentered(PLAY_AREA_CENTER_X, offset3, mLang->getText(56)); - mTextScoreBoard->writeCentered(PLAY_AREA_CENTER_X, offset4, updateScoreText(mHiScore)); -} - -// Actualiza las variables del jugador -void Game::updatePlayer() -{ - for (int i = 0; i < mNumPlayers; i++) - { - mPlayer[i]->update(); - - // Comprueba la colisión entre el jugador y los globos - if (checkPlayerBalloonCollision(i)) - { - if (mPlayer[i]->isAlive()) - { - if (mDemo.enabled) - mSection = {PROG_SECTION_TITLE, TITLE_SECTION_INSTRUCTIONS}; - else - killPlayer(i); - } - } - - // Comprueba las colisiones entre el jugador y los items - checkPlayerItemCollision(i); - } -} - -// Actualiza las variables de la fase -void Game::updateStage() -{ - if (mStage[mCurrentStage].currentPower >= mStage[mCurrentStage].powerToComplete) - { - // Cambio de fase - mCurrentStage++; - if (mCurrentStage == 10) // Ha llegado al final el juego - { - mGameCompleted = true; // Marca el juego como completado - mCurrentStage = 9; // Deja el valor dentro de los limites - mStage[mCurrentStage].currentPower = 0; // Deja el poder a cero para que no vuelva a entrar en esta condición - destroyAllBalloons(); // Destruye a todos los enemigos - mStage[mCurrentStage].currentPower = 0; // Vuelve a dejar el poder a cero, por lo que hubiera podido subir al destruir todos lo globos - mMenaceCurrent = 255; // Sube el nivel de amenaza para que no cree mas globos - for (int i = 0; i < mNumPlayers; i++) // Añade un millon de puntos a los jugadores que queden vivos - if (mPlayer[i]->isAlive()) - mPlayer[i]->addScore(1000000); - updateHiScore(); - JA_StopMusic(); - } - JA_PlaySound(mSoundStageChange); - mStageBitmapCounter = 0; - mEnemySpeed = mDefaultEnemySpeed; - setBalloonSpeed(mEnemySpeed); - mEffect.flash = true; - mEffect.shake = true; - } - - // Incrementa el contador del bitmap que aparece mostrando el cambio de fase - if (mStageBitmapCounter < STAGE_COUNTER) - mStageBitmapCounter++; - - // Si el juego se ha completado, el bitmap se detiene en el centro de la pantalla - if (mGameCompleted) - if (mStageBitmapCounter > 100) - mStageBitmapCounter = 100; -} - -// Actualiza el estado de muerte -void Game::updateDeath() -{ - // Comprueba si todos los jugadores estan muertos - bool allAreDead = true; - for (int i = 0; i < mNumPlayers; i++) - { - allAreDead &= (!mPlayer[i]->isAlive()); - - if (!mPlayer[i]->isAlive()) - { - // Animación - if ((mPlayer[i]->getDeathCounter() / 5) % 4 == 0) - mSmartSprite[mPlayer[i]->mDeathIndex]->setSpriteClip(24 * 0, 24, 24, 24); - else if ((mPlayer[i]->getDeathCounter() / 5) % 4 == 1) - mSmartSprite[mPlayer[i]->mDeathIndex]->setSpriteClip(24 * 1, 24, 24, 24); - else if ((mPlayer[i]->getDeathCounter() / 5) % 4 == 2) - mSmartSprite[mPlayer[i]->mDeathIndex]->setSpriteClip(24 * 2, 24, 24, 24); - else if ((mPlayer[i]->getDeathCounter() / 5) % 4 == 3) - mSmartSprite[mPlayer[i]->mDeathIndex]->setSpriteClip(24 * 3, 24, 24, 24); - - // Rebote en los laterales - if (mSmartSprite[mPlayer[i]->mDeathIndex]->getVelX() > 0) - { - if (mSmartSprite[mPlayer[i]->mDeathIndex]->getPosX() > (SCREEN_WIDTH - mSmartSprite[mPlayer[i]->mDeathIndex]->getWidth())) - { - mSmartSprite[mPlayer[i]->mDeathIndex]->setPosX(SCREEN_WIDTH - mSmartSprite[mPlayer[i]->mDeathIndex]->getWidth()); - mSmartSprite[mPlayer[i]->mDeathIndex]->setVelX(mSmartSprite[mPlayer[i]->mDeathIndex]->getVelX() * (-1)); - mSmartSprite[mPlayer[i]->mDeathIndex]->setDestX(mSmartSprite[mPlayer[i]->mDeathIndex]->getDestX() * (-1)); - } - } - else - { - if (mSmartSprite[mPlayer[i]->mDeathIndex]->getPosX() < 0) - { - mSmartSprite[mPlayer[i]->mDeathIndex]->setPosX(0); - mSmartSprite[mPlayer[i]->mDeathIndex]->setVelX(mSmartSprite[mPlayer[i]->mDeathIndex]->getVelX() * (-1)); - mSmartSprite[mPlayer[i]->mDeathIndex]->setDestX(mSmartSprite[mPlayer[i]->mDeathIndex]->getDestX() * (-1)); - } - } - } - } - - if (allAreDead) - { - //JA_StopMusic(); - - if (mDeathCounter > 0) - { - mDeathCounter--; - if ((mDeathCounter == 250) || (mDeathCounter == 200) || (mDeathCounter == 180) || (mDeathCounter == 120) || (mDeathCounter == 60)) - { - Uint8 sound = rand() % 4; - switch (sound) - { - case 0: - JA_PlaySound(mSoundBubble1, 0); - break; - case 1: - JA_PlaySound(mSoundBubble2, 0); - break; - case 2: - JA_PlaySound(mSoundBubble3, 0); - break; - case 3: - JA_PlaySound(mSoundBubble4, 0); - break; - - default: - break; - } - } - } - else - { - mSection.subsection = GAME_SECTION_GAMEOVER; - } - } -} - -// Renderiza el fade final cuando se acaba la partida -void Game::renderDeathFade(int counter) -// Counter debe ir de 0 a 150 -{ - SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 255); - - if (counter < 150) - { - // 192 / 6 = 32, 6 cuadrados de 32 pixeles - SDL_Rect rect[12]; - Uint8 h = counter / 3; - for (int 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]); - } - } - else - { - SDL_Rect rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT}; - SDL_RenderFillRect(mRenderer, &rect); - } -} - -// Actualiza los globos -void Game::updateBalloons() -{ - for (int i = 0; i < MAX_BALLOONS; i++) - mBalloon[i]->update(); -} - -// Pinta en pantalla todos los globos activos -void Game::renderBalloons() -{ - for (int i = 0; i < MAX_BALLOONS; i++) - { - mBalloon[i]->render(); - if ((mDebug.enabled) && (mBalloon[i]->isPopping() == false)) - mText->writeCentered(mBalloon[i]->getPosX() + (mBalloon[i]->getWidth() / 2), mBalloon[i]->getPosY() - 8, std::to_string(i)); - } -} - -// Devuelve el primer indice no activo del vector de globos -Uint8 Game::getBalloonFreeIndex() -{ - for (int i = 0; i < MAX_BALLOONS; i++) - if (!mBalloon[i]->isEnabled()) - return i; - - return 0; -} - -// Crea un globo nuevo en el vector de globos -Uint8 Game::createNewBalloon(float x, int y, Uint8 kind, float velx, float speed, Uint16 creationtimer, LTexture *texture) -{ - const Uint8 index = getBalloonFreeIndex(); - mBalloon[index]->init(x, y, kind, velx, speed, creationtimer, texture, mRenderer); - return index; -} - -// Crea una PowerBall -void Game::createPowerBall() -{ - const int posY = PLAY_AREA_TOP; - - const int left = PLAY_AREA_LEFT; - const int center = PLAY_AREA_CENTER_X - (BALLOON_WIDTH_4 / 2); - const int right = PLAY_AREA_RIGHT - BALLOON_WIDTH_4; - - const int x[3] = {left, center, right}; - const int posX = x[rand() % 3]; - - mBalloon[getBalloonFreeIndex()]->init(posX, posY, POWER_BALL, BALLOON_VELX_POSITIVE * (((rand() % 2) * 2) - 1), mEnemySpeed, 100, mTextureBalloon, mRenderer); - mPowerBallEnabled = true; - mPowerBallCounter = POWERBALL_COUNTER; -} - -// Establece a cero todos los valores del vector de objetos globo -void Game::resetBalloons() -{ - for (int i = 0; i < MAX_BALLOONS; i++) - mBalloon[i]->disable(); -} - -// Establece la velocidad de los globos -void Game::setBalloonSpeed(float speed) -{ - for (int i = 0; i < MAX_BALLOONS; i++) - if (mBalloon[i]->isEnabled()) - mBalloon[i]->setSpeed(speed); -} - -// Incrementa la velocidad de los globos -void Game::incBalloonSpeed() -{ - // La velocidad solo se incrementa en el modo normal - if (mDifficulty == DIFFICULTY_NORMAL) - { - if (mEnemySpeed == BALLOON_SPEED_1) - mEnemySpeed = BALLOON_SPEED_2; - else if (mEnemySpeed == BALLOON_SPEED_2) - mEnemySpeed = BALLOON_SPEED_3; - else if (mEnemySpeed == BALLOON_SPEED_3) - mEnemySpeed = BALLOON_SPEED_4; - else if (mEnemySpeed == BALLOON_SPEED_4) - mEnemySpeed = BALLOON_SPEED_5; - - setBalloonSpeed(mEnemySpeed); - } -} - -// Decrementa la velocidad de los globos -void Game::decBalloonSpeed() -{ - // La velocidad solo se decrementa en el modo normal - if (mDifficulty == DIFFICULTY_NORMAL) - { - if (mEnemySpeed == BALLOON_SPEED_5) - mEnemySpeed = BALLOON_SPEED_4; - else if (mEnemySpeed == BALLOON_SPEED_4) - mEnemySpeed = BALLOON_SPEED_3; - else if (mEnemySpeed == BALLOON_SPEED_3) - mEnemySpeed = BALLOON_SPEED_2; - else if (mEnemySpeed == BALLOON_SPEED_2) - mEnemySpeed = BALLOON_SPEED_1; - - setBalloonSpeed(mEnemySpeed); - } -} - -// Actualiza la velocidad de los globos en funcion del poder acumulado de la fase -void Game::updateBalloonSpeed() -{ - const float percent = (float)mStage[mCurrentStage].currentPower / (float)mStage[mCurrentStage].powerToComplete; - if (mEnemySpeed == BALLOON_SPEED_1) - { - if (percent > 0.2f) - incBalloonSpeed(); - } - else if (mEnemySpeed == BALLOON_SPEED_2) - { - if (percent > 0.4f) - incBalloonSpeed(); - } - else if (mEnemySpeed == BALLOON_SPEED_3) - { - if (percent > 0.6f) - incBalloonSpeed(); - } - else if (mEnemySpeed == BALLOON_SPEED_4) - { - if (percent > 0.8f) - incBalloonSpeed(); - } -} - -// Explosiona un globo. Lo destruye y crea otros dos si es el caso -void Game::popBalloon(Uint8 index) -{ - // Aumenta el poder de la fase - increaseStageCurrentPower(1); - mBalloonsPopped++; - - const Uint8 kind = mBalloon[index]->getKind(); - Uint8 freeIndex = 0; - switch (kind) - { - // Si es del tipo más pequeño, simplemente elimina el globo - case BALLOON_1: - mBalloon[index]->pop(); - break; - - case HEXAGON_1: - mBalloon[index]->pop(); - break; - - // Si es del tipo PowerBall, destruye todos los globos - case POWER_BALL: - destroyAllBalloons(); - mPowerBallEnabled = false; - mEnemyDeployCounter = 20; - break; - - // En cualquier otro caso, crea dos globos de un tipo inferior - default: - freeIndex = getBalloonFreeIndex(); - mBalloon[freeIndex]->init(0, mBalloon[index]->getPosY(), mBalloon[index]->getKind() - 1, BALLOON_VELX_NEGATIVE, mEnemySpeed, 0, mTextureBalloon, mRenderer); - mBalloon[freeIndex]->allignTo(mBalloon[index]->getPosX() + (mBalloon[index]->getWidth() / 2)); - if (mBalloon[freeIndex]->getClass() == BALLOON_CLASS) - mBalloon[freeIndex]->setVelY(-2.50f); - else if (mBalloon[freeIndex]->getClass() == HEXAGON_CLASS) - mBalloon[freeIndex]->setVelY(BALLOON_VELX_NEGATIVE); - - freeIndex = getBalloonFreeIndex(); - mBalloon[freeIndex]->init(0, mBalloon[index]->getPosY(), mBalloon[index]->getKind() - 1, BALLOON_VELX_POSITIVE, mEnemySpeed, 0, mTextureBalloon, mRenderer); - mBalloon[freeIndex]->allignTo(mBalloon[index]->getPosX() + (mBalloon[index]->getWidth() / 2)); - if (mBalloon[freeIndex]->getClass() == BALLOON_CLASS) - mBalloon[freeIndex]->setVelY(-2.50f); - else if (mBalloon[freeIndex]->getClass() == HEXAGON_CLASS) - mBalloon[freeIndex]->setVelY(BALLOON_VELX_NEGATIVE); - - // Elimina el globo - mBalloon[index]->pop(); - break; - } - - // Recalcula el nivel de amenaza - evaluateAndSetMenace(); -} - -// Explosiona un globo. Lo destruye -void Game::destroyBalloon(Uint8 index) -{ - int score = 0; - Uint8 power = 0; - - // Calcula la puntuación y el poder que generaria el globo en caso de romperlo a él y a sus hijos - switch (mBalloon[index]->getSize()) - { - case BALLOON_SIZE_4: - score = BALLOON_SCORE_4 + (2 * BALLOON_SCORE_3) + (4 * BALLOON_SCORE_2) + (8 * BALLOON_SCORE_1); - power = 15; - break; - - case BALLOON_SIZE_3: - score = BALLOON_SCORE_3 + (2 * BALLOON_SCORE_2) + (4 * BALLOON_SCORE_1); - power = 7; - break; - - case BALLOON_SIZE_2: - score = BALLOON_SCORE_2 + (2 * BALLOON_SCORE_1); - power = 3; - break; - - case BALLOON_SIZE_1: - score = BALLOON_SCORE_1; - power = 1; - break; - - default: - score = 0; - power = 0; - break; - } - - // Otorga los puntos correspondientes al globo - for (int i = 0; i < mNumPlayers; i++) - mPlayer[i]->addScore(Uint32(score * mPlayer[i]->getScoreMultiplier() * mDifficultyScoreMultiplier)); - updateHiScore(); - - // Aumenta el poder de la fase - increaseStageCurrentPower(power); - mBalloonsPopped += power; - - // Destruye el globo - mBalloon[index]->pop(); - - // Recalcula el nivel de amenaza - evaluateAndSetMenace(); -} - -// Explosiona todos los globos -void Game::popAllBalloons() -{ - for (int i = 0; i < MAX_BALLOONS; i++) - if ((mBalloon[i]->isEnabled()) && (!mBalloon[i]->isPopping()) && (!mBalloon[i]->isBeingCreated())) - popBalloon(i); - - JA_PlaySound(mSoundBalloon); -} - -// Destruye todos los globos -void Game::destroyAllBalloons() -{ - for (int i = 0; i < MAX_BALLOONS; i++) - //if ((mBalloon[i]->isEnabled()) && (!mBalloon[i]->isPopping()) && (!mBalloon[i]->isBeingCreated())) - if ((mBalloon[i]->isEnabled()) && (!mBalloon[i]->isPopping())) - destroyBalloon(i); - - mEnemyDeployCounter = 255; - JA_PlaySound(mSoundPowerBall); - mEffect.flash = true; - mEffect.shake = true; -} - -// Detiene todos los globos -void Game::stopAllBalloons(Uint16 time) -{ - for (int i = 0; i < MAX_BALLOONS; i++) - if (mBalloon[i]->isEnabled()) - { - mBalloon[i]->setStop(true); - mBalloon[i]->setStoppedTimer(time); - } -} - -// Pone en marcha todos los globos -void Game::startAllBalloons() -{ - for (int i = 0; i < MAX_BALLOONS; i++) - if ((mBalloon[i]->isEnabled()) && (!mBalloon[i]->isBeingCreated())) - { - mBalloon[i]->setStop(false); - mBalloon[i]->setStoppedTimer(0); - } -} - -// Obtiene el numero de globos activos -Uint8 Game::countBalloons() -{ - Uint8 num = 0; - - for (int i = 0; i < MAX_BALLOONS; i++) - if (mBalloon[i]->isEnabled()) - if (!mBalloon[i]->isPopping()) - num++; - - return num; -} - -// Comprueba la colisión entre el jugador y los globos activos -bool Game::checkPlayerBalloonCollision(int index) -{ - for (int i = 0; i < MAX_BALLOONS; i++) - if ((mBalloon[i]->isEnabled()) && !(mBalloon[i]->isStopped()) && !(mBalloon[i]->isInvulnerable())) - if (checkCollision(mPlayer[index]->getCollider(), mBalloon[i]->getCollider())) - return true; - - return false; -} - -// Comprueba la colisión entre el jugador y los items -void Game::checkPlayerItemCollision(int index) -{ - if (mPlayer[index]->isAlive()) - for (int i = 0; i < MAX_ITEMS; i++) - { - if (mItem[i]->isEnabled()) - { - if (checkCollision(mPlayer[index]->getCollider(), mItem[i]->getCollider())) - { - switch (mItem[i]->getClass()) - { - case ITEM_POINTS_1_DISK: - mPlayer[index]->addScore(1000); - updateHiScore(); - createItemScoreSprite(mItem[i]->getPosX() + (mItem[i]->getWidth() / 2) - (m1000Bitmap->getWidth() / 2), mPlayer[index]->getPosY(), m1000Bitmap); - JA_PlaySound(mSoundItemPickup); - break; - case ITEM_POINTS_2_GAVINA: - mPlayer[index]->addScore(2500); - updateHiScore(); - createItemScoreSprite(mItem[i]->getPosX() + (mItem[i]->getWidth() / 2) - (m2500Bitmap->getWidth() / 2), mPlayer[index]->getPosY(), m2500Bitmap); - JA_PlaySound(mSoundItemPickup); - break; - case ITEM_POINTS_3_PACMAR: - mPlayer[index]->addScore(5000); - updateHiScore(); - createItemScoreSprite(mItem[i]->getPosX() + (mItem[i]->getWidth() / 2) - (m5000Bitmap->getWidth() / 2), mPlayer[index]->getPosY(), m5000Bitmap); - JA_PlaySound(mSoundItemPickup); - break; - case ITEM_CLOCK: - enableTimeStopItem(); - JA_PlaySound(mSoundItemPickup); - break; - case ITEM_COFFEE: - if (mPlayer[index]->getCoffees() == 2) - { - mPlayer[index]->addScore(5000); - updateHiScore(); - createItemScoreSprite(mItem[i]->getPosX() + (mItem[i]->getWidth() / 2) - (m5000Bitmap->getWidth() / 2), mPlayer[index]->getPosY(), m5000Bitmap); - } - mPlayer[index]->giveExtraHit(); - JA_PlaySound(mSoundItemPickup); - break; - case ITEM_COFFEE_MACHINE: - mPlayer[index]->setPowerUp(true); - JA_PlaySound(mSoundItemPickup); - mCoffeeMachineEnabled = false; - break; - - default: - break; - } - mItem[i]->erase(); - } - } - } -} - -// Comprueba y procesa la colisión entre las balas y los globos -void Game::checkBulletBalloonCollision() -{ - for (int i = 0; i < MAX_BALLOONS; i++) - for (int j = 0; j < MAX_BULLETS; j++) - if (mBalloon[i]->isEnabled() && (!mBalloon[i]->isInvulnerable()) && mBullet[j]->isActive()) - if (checkCollision(mBalloon[i]->getCollider(), mBullet[j]->getCollider())) - { - // Otorga los puntos correspondientes al globo al jugador que disparó la bala - int index = mBullet[j]->getOwner(); - mPlayer[index]->incScoreMultiplier(); - mPlayer[index]->addScore(Uint32(mBalloon[i]->getScore() * mPlayer[index]->getScoreMultiplier() * mDifficultyScoreMultiplier)); - //setScore(mPlayer[index]->getScore()); - updateHiScore(); - - // Explota el globo - popBalloon(i); - - // Si no es el modo demo, genera un sonido - if (!mDemo.enabled) - JA_PlaySound(mSoundBalloon); - - // Destruye la bala - mBullet[j]->erase(); - - // Suelta el item en caso de que salga uno - const Uint8 droppeditem = dropItem(); - if ((droppeditem != NO_KIND) && !(mDemo.enabled) && !(mDemo.recording)) - { - if (droppeditem != ITEM_COFFEE_MACHINE) - { - createItem(mBalloon[i]->getPosX(), mBalloon[i]->getPosY(), droppeditem); - JA_PlaySound(mSoundItemDrop); - } - else - { - createItem(mPlayer[index]->getPosX(), 0, droppeditem); - mCoffeeMachineEnabled = true; - } - } - break; - } -} - -// Mueve las balas activas -void Game::moveBullets() -{ - for (int i = 0; i < MAX_BULLETS; i++) - if (mBullet[i]->isActive()) - if (mBullet[i]->move() == MSG_BULLET_OUT) - mPlayer[mBullet[i]->getOwner()]->decScoreMultiplier(); -} - -// Pinta las balas activas -void Game::renderBullets() -{ - for (int i = 0; i < MAX_BULLETS; i++) - if (mBullet[i]->isActive()) - mBullet[i]->render(); -} - -// Devuelve el primer indice no activo del vector de balas -Uint8 Game::getBulletFreeIndex() -{ - for (int i = 0; i < MAX_BULLETS; i++) - if (mBullet[i]->isActive() == false) - return i; - - return 0; -} - -// Establece a cero todos los valores del vector de objetos bala -void Game::resetBullets() -{ - for (int i = 0; i < MAX_BULLETS; i++) - mBullet[i]->erase(); -} - -// Crea un objeto bala -void Game::createBullet(int x, int y, Uint8 kind, bool poweredUp, int owner) -{ - mBullet[getBulletFreeIndex()]->init(x, y, kind, poweredUp, owner, mTextureBullet, mRenderer); -} - -// Actualiza los items -void Game::updateItems() -{ - for (int i = 0; i < MAX_ITEMS; i++) - { - mItem[i]->update(); - if (mItem[i]->floorCollision()) - { - JA_PlaySound(mSoundCollision); - mEffect.shake = true; - } - } -} - -// Pinta los items activos -void Game::renderItems() -{ - for (int i = 0; i < MAX_ITEMS; i++) - mItem[i]->render(); -} - -// Devuelve el primer indice no activo del vector de items -Uint8 Game::getItemFreeIndex() -{ - for (int i = 0; i < MAX_ITEMS; i++) - if (mItem[i]->getClass() == NO_KIND) - return i; - - return 0; -} - -// Establece a cero todos los valores del vector de objetos item -void Game::resetItems() -{ - for (int i = 0; i < MAX_ITEMS; i++) - mItem[i]->erase(); -} - -// Devuelve un item en función del azar -Uint8 Game::dropItem() -{ - //if (mPlayer[0]->isPowerUp() || (mCoffeeMachineEnabled)) - // return NO_KIND; - //else - // return ITEM_COFFEE_MACHINE; - - const Uint8 luckyNumber = rand() % 100; - const Uint8 item = rand() % 6; - - switch (item) - { - case 0: - if (luckyNumber < mHelper.itemPoints1Odds) - return ITEM_POINTS_1_DISK; - break; - case 1: - if (luckyNumber < mHelper.itemPoints2Odds) - return ITEM_POINTS_2_GAVINA; - break; - case 2: - if (luckyNumber < mHelper.itemPoints3Odds) - return ITEM_POINTS_3_PACMAR; - break; - case 3: - if (luckyNumber < mHelper.itemClockOdds) - return ITEM_CLOCK; - break; - case 4: - if (luckyNumber < mHelper.itemCoffeeOdds) - { - mHelper.itemCoffeeOdds = ITEM_COFFEE_ODDS; - return ITEM_COFFEE; - } - else - { - if (mHelper.needCoffee) - mHelper.itemCoffeeOdds++; - } - break; - case 5: - if (luckyNumber < mHelper.itemCoffeeMachineOdds) - { - mHelper.itemCoffeeMachineOdds = ITEM_COFFEE_MACHINE_ODDS; - if ((!mCoffeeMachineEnabled) && (mHelper.needCoffeeMachine)) - return ITEM_COFFEE_MACHINE; - } - else - { - if (mHelper.needCoffeeMachine) - mHelper.itemCoffeeMachineOdds++; - } - break; - default: - break; - } - - return NO_KIND; -} - -// Crea un objeto item -void Game::createItem(int x, int y, Uint8 kind) -{ - mItem[getItemFreeIndex()]->init(kind, x, y, mTextureItems, mRenderer); -} - -// Crea un objeto SmartSprite para mostrar la puntuación al coger un objeto -void Game::createItemScoreSprite(int x, int y, SmartSprite *sprite) -{ - const Uint8 index = getSmartSpriteFreeIndex(); - - *mSmartSprite[index] = *sprite; - mSmartSprite[index]->setPosX(x); - mSmartSprite[index]->setPosY(y); - mSmartSprite[index]->setDestX(x); - mSmartSprite[index]->setDestY(y - 15); - mSmartSprite[index]->setEnabled(true); - mSmartSprite[index]->setEnabledTimer(100); -} - -// Dibuja el efecto de flash -void Game::renderFlashEffect() -{ - if (mEffect.flash) - { - // Pantallazo blanco - SDL_SetRenderDrawColor(mRenderer, 0xFF, 0xFF, 0xFF, 0xFF); - SDL_RenderClear(mRenderer); - - mEffect.flash = false; - } -} - -// Actualiza el efecto de agitar la pantalla -void Game::updateShakeEffect() -{ - if (mEffect.shake) - { - if (mEffect.shakeCounter > 0) - mEffect.shakeCounter--; - else - { - mEffect.shake = false; - mEffect.shakeCounter = SHAKE_COUNTER; - } - } -} - -// Crea un SmartSprite para arrojar el item café al recibir un impacto -void Game::throwCoffee(int x, int y) -{ - const Uint8 index = getSmartSpriteFreeIndex(); - - mSmartSprite[index]->init(mTextureItems, mRenderer); - mSmartSprite[index]->setPosX(x - 8); - mSmartSprite[index]->setPosY(y - 8); - mSmartSprite[index]->setWidth(16); - mSmartSprite[index]->setHeight(16); - mSmartSprite[index]->setVelX(-1.0f + ((rand() % 5) * 0.5f)); - mSmartSprite[index]->setVelY(-4.0f); - mSmartSprite[index]->setAccelX(0.0f); - mSmartSprite[index]->setAccelY(0.2f); - mSmartSprite[index]->setDestX(x + (mSmartSprite[index]->getVelX() * 50)); - mSmartSprite[index]->setDestY(SCREEN_HEIGHT + 1); - mSmartSprite[index]->setEnabled(true); - mSmartSprite[index]->setEnabledTimer(1); - mSmartSprite[index]->setSpriteClip(80, 16, 16, 16); - mSmartSprite[index]->setRotate(true); - mSmartSprite[index]->setRotateSpeed(10); - mSmartSprite[index]->setRotateAmount(90.0); -} - -// Crea un SmartSprite para arrojar al jugador al morir -void Game::throwPlayer(int x, int y, int index) -{ - const int sentit = ((rand() % 2) ? 1 : -1); - - mPlayer[index]->mDeathIndex = getSmartSpriteFreeIndex(); - mSmartSprite[mPlayer[index]->mDeathIndex]->init(mPlayer[index]->getDeadTexture(), mRenderer); - mSmartSprite[mPlayer[index]->mDeathIndex]->setPosX(x); - mSmartSprite[mPlayer[index]->mDeathIndex]->setPosY(y); - mSmartSprite[mPlayer[index]->mDeathIndex]->setWidth(24); - mSmartSprite[mPlayer[index]->mDeathIndex]->setHeight(24); - mSmartSprite[mPlayer[index]->mDeathIndex]->setVelX(2.0f * sentit); - mSmartSprite[mPlayer[index]->mDeathIndex]->setVelY(-5.0f); - mSmartSprite[mPlayer[index]->mDeathIndex]->setAccelX(0.0f); - mSmartSprite[mPlayer[index]->mDeathIndex]->setAccelY(0.2f); - mSmartSprite[mPlayer[index]->mDeathIndex]->setDestX(SCREEN_WIDTH * sentit); - mSmartSprite[mPlayer[index]->mDeathIndex]->setDestY(SCREEN_HEIGHT + 1); - mSmartSprite[mPlayer[index]->mDeathIndex]->setEnabled(true); - mSmartSprite[mPlayer[index]->mDeathIndex]->setEnabledTimer(1); - mSmartSprite[mPlayer[index]->mDeathIndex]->setSpriteClip(0, 0, 24, 24); -} - -// Actualiza los SmartSprites -void Game::updateSmartSprites() -{ - for (int i = 0; i < MAX_SMART_SPRITES; i++) - mSmartSprite[i]->update(); -} - -// Pinta los SmartSprites activos -void Game::renderSmartSprites() -{ - for (int i = 0; i < MAX_SMART_SPRITES; i++) - mSmartSprite[i]->render(); -} - -// Devuelve el primer indice no activo del vector de SmartSprites -Uint8 Game::getSmartSpriteFreeIndex() -{ - for (int i = 0; i < MAX_SMART_SPRITES; i++) - if (!mSmartSprite[i]->isEnabled()) - return i; - - return 0; -} - -// Establece a cero todos los valores del vector de objetos SmafrtSprite -void Game::resetSmartSprites() -{ - for (int i = 0; i < MAX_SMART_SPRITES; i++) - mSmartSprite[i]->erase(); -} - -// Acciones a realizar cuando el jugador muere -void Game::killPlayer(int index) -{ - if (!mPlayer[index]->isInvulnerable()) - { - if (mPlayer[index]->hasExtraHit()) - { - mPlayer[index]->removeExtraHit(); - throwCoffee(mPlayer[index]->getPosX() + (mPlayer[index]->getWidth() / 2), mPlayer[index]->getPosY() + (mPlayer[index]->getHeight() / 2)); - JA_PlaySound(mSoundCoffeeOut); - } - else - { - JA_PauseMusic(); - stopAllBalloons(10); - JA_PlaySound(mSoundPlayerCollision); - shakeScreen(); - SDL_Delay(500); - JA_PlaySound(mSoundCoffeeOut); - throwPlayer(mPlayer[index]->getPosX(), mPlayer[index]->getPosY(), index); - mPlayer[index]->setAlive(false); - if (allPlayersAreDead()) - JA_StopMusic(); - else - JA_ResumeMusic(); - } - } -} - -// Calcula y establece el valor de amenaza en funcion de los globos activos -void Game::evaluateAndSetMenace() -{ - mMenaceCurrent = 0; - for (int i = 0; i < MAX_BALLOONS; i++) - if (mBalloon[i]->isEnabled()) - mMenaceCurrent += mBalloon[i]->getMenace(); -} - -// Obtiene el valor de la variable -Uint8 Game::getMenace() -{ - return mMenaceCurrent; -} - -// Establece el valor de la variable -void Game::setTimeStopped(bool value) -{ - mTimeStopped = value; -} - -// Obtiene el valor de la variable -bool Game::isTimeStopped() -{ - return mTimeStopped; -} - -// Establece el valor de la variable -void Game::setTimeStoppedCounter(Uint16 value) -{ - mTimeStoppedCounter = value; -} - -// Incrementa el valor de la variable -void Game::incTimeStoppedCounter(Uint16 value) -{ - mTimeStoppedCounter += value; -} - -// Actualiza y comprueba el valor de la variable -void Game::updateTimeStoppedCounter() -{ - if (isTimeStopped()) - { - if (mTimeStoppedCounter > 0) - { - mTimeStoppedCounter--; - stopAllBalloons(TIME_STOPPED_COUNTER); - } - else - { - disableTimeStopItem(); - } - } -} - -// Establece el valor de la variable -void Game::setExplosionTime(bool value) -{ - mExplosionTime = value; -} - -// Obtiene el valor de la variable -bool Game::isExplosionTime() -{ - return mExplosionTime; -} - -// Establece el valor de la variable -void Game::setRemainingExplosions(Uint8 value) -{ - mRemainingExplosions = value; -} - -// Actualiza y comprueba el valor de la variable -void Game::updateRemainingExplosionsCounter() -{ - if (isExplosionTime()) - { - if (mRemainingExplosionsCounter > 0) - { - mRemainingExplosionsCounter--; - } - else if (mRemainingExplosions > 0) - { - popAllBalloons(); - mRemainingExplosions--; - mRemainingExplosionsCounter = REMAINING_EXPLOSIONS_COUNTER; - } - else - { - mExplosionTime = false; - mRemainingExplosions = REMAINING_EXPLOSIONS; - mRemainingExplosionsCounter = REMAINING_EXPLOSIONS_COUNTER; - } - } -} - -// Actualiza la variable mEnemyDeployCounter -void Game::updateEnemyDeployCounter() -{ - if (mEnemyDeployCounter > 0) - mEnemyDeployCounter--; -} - -// Actualiza el campo de juego -void Game::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 mCurrentStage - updateStage(); - - // Actualiza el estado de muerte - updateDeath(); - - // Actualiza los SmartSprites - updateSmartSprites(); - - // Actualiza los contadores de estado y efectos - updateTimeStoppedCounter(); - updateRemainingExplosionsCounter(); - updateEnemyDeployCounter(); - updateShakeEffect(); - - // Actualiza el ayudante - updateHelper(); - - // Comprueba las colisiones entre globos y balas - checkBulletBalloonCollision(); - - // Comprueba el nivel de amenaza para ver si se han de crear nuevos enemigos - if (!mGameCompleted) - updateMenace(); - - // Actualiza la velocidad de los enemigos - updateBalloonSpeed(); - - // Actualiza el tramo final de juego, una vez completado - updateGameCompleted(); -} - -// Actualiza el fondo -void Game::updateBackground() -{ - mClouds1a->move(); - mClouds1b->move(); - mClouds2a->move(); - mClouds2b->move(); - - if (mClouds1a->getPosX() < -mClouds1a->getWidth()) - mClouds1a->setPosX(mClouds1a->getWidth()); - - if (mClouds1b->getPosX() < -mClouds1b->getWidth()) - mClouds1b->setPosX(mClouds1b->getWidth()); - - if (mClouds2a->getPosX() < -mClouds2a->getWidth()) - mClouds2a->setPosX(mClouds2a->getWidth()); - - if (mClouds2b->getPosX() < -mClouds2b->getWidth()) - mClouds2b->setPosX(mClouds2b->getWidth()); - - mSpriteGrass->setSpriteClip(256, 85 + (6 * (mCounter / 20 % 2)), SCREEN_WIDTH, 6); - - if (mEffect.shake) - mSpriteBackground->setPosX(((mEffect.shakeCounter % 2) * 2) - 1); - else - mSpriteBackground->setPosX(0); -} - -// Dibuja el fondo -void Game::renderBackground() -{ - const float gradientNumber = std::min(((float)mBalloonsPopped / 1000.0f), 3.0f); - const float percent = gradientNumber - (int)gradientNumber; - const int alpha = std::max((255 - (int)(255 * percent)), 0); - - // Dibuja el gradiente 2 - mSpriteGradient->setSpriteClip(mGradientRect[((int)gradientNumber + 1) % 4]); - mSpriteGradient->render(); - - // Dibuja el gradiente 1 con una opacidad cada vez menor - mSpriteGradient->setSpriteClip(mGradientRect[(int)gradientNumber]); - mTextureGameBG->setAlpha(alpha); - mSpriteGradient->render(); - mTextureGameBG->setAlpha(255); - - mClouds1a->render(); - mClouds1b->render(); - mClouds2a->render(); - mClouds2b->render(); - - mSpriteBackground->render(); - - mSpriteGrass->render(); -} - -// Dibuja el campo de juego -void Game::renderPlayField() -{ - renderBackground(); - renderBalloons(); - renderBullets(); - renderMessages(); - renderItems(); - renderSmartSprites(); - renderScoreBoard(); - for (int i = 0; i < mNumPlayers; i++) - mPlayer[i]->render(); - if ((mDeathCounter <= 150) && !mPlayer[0]->isAlive()) - renderDeathFade(150 - mDeathCounter); - if ((mGameCompleted) && (mGameCompletedCounter >= 300)) - renderDeathFade(mGameCompletedCounter - 300); - renderFlashEffect(); -} - -// Gestiona el nivel de amenaza -void Game::updateMenace() -{ - const float percent = mStage[mCurrentStage].currentPower / mStage[mCurrentStage].powerToComplete; - const Uint8 difference = mStage[mCurrentStage].maxMenace - mStage[mCurrentStage].minMenace; - - // Aumenta el nivel de amenaza en función de la puntuación - mMenaceThreshold = mStage[mCurrentStage].minMenace + (difference * percent); - - // Si el nivel de amenza es inferior al umbral - if (mMenaceCurrent < mMenaceThreshold) - { - // Crea una formación de enemigos - deployEnemyFormation(); - - // Recalcula el nivel de amenaza con el nuevo globo - evaluateAndSetMenace(); - } -} - -// Gestiona la entrada durante el juego -void Game::checkGameInput() -{ - 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) - { - const int index = 0; - if (mDemo.dataFile[mDemo.counter].left == 1) - mPlayer[index]->setInput(INPUT_LEFT); - - if (mDemo.dataFile[mDemo.counter].right == 1) - mPlayer[index]->setInput(INPUT_RIGHT); - - if (mDemo.dataFile[mDemo.counter].noInput == 1) - mPlayer[index]->setInput(NO_INPUT); - - if (mDemo.dataFile[mDemo.counter].fire == 1) - if (mPlayer[index]->canFire()) - { - mPlayer[index]->setInput(INPUT_FIRE_UP); - createBullet(mPlayer[index]->getPosX() + (mPlayer[index]->getWidth() / 2) - 4, mPlayer[index]->getPosY() + (mPlayer[index]->getHeight() / 2), BULLET_UP, mPlayer[index]->isPowerUp(), index); - mPlayer[index]->setFireCooldown(10); - } - - if (mDemo.dataFile[mDemo.counter].fireLeft == 1) - if (mPlayer[index]->canFire()) - { - mPlayer[index]->setInput(INPUT_FIRE_LEFT); - createBullet(mPlayer[index]->getPosX() + (mPlayer[index]->getWidth() / 2) - 4, mPlayer[index]->getPosY() + (mPlayer[index]->getHeight() / 2), BULLET_UP, mPlayer[index]->isPowerUp(), index); - mPlayer[index]->setFireCooldown(10); - } - - if (mDemo.dataFile[mDemo.counter].fireRight == 1) - if (mPlayer[index]->canFire()) - { - mPlayer[index]->setInput(INPUT_FIRE_RIGHT); - createBullet(mPlayer[index]->getPosX() + (mPlayer[index]->getWidth() / 2) - 4, mPlayer[index]->getPosY() + (mPlayer[index]->getHeight() / 2), BULLET_UP, mPlayer[index]->isPowerUp(), index); - mPlayer[index]->setFireCooldown(10); - } - - // Comprueba el input de pausa - if (mInput->checkInput(INPUT_BUTTON_PAUSE, REPEAT_FALSE)) - mSection.name = PROG_SECTION_TITLE; - - // Incrementa el contador de la demo - if (mDemo.counter < TOTAL_DEMO_DATA) - mDemo.counter++; - else - mSection = {PROG_SECTION_TITLE, TITLE_SECTION_INSTRUCTIONS}; - } - // Modo Demo no activo - else - for (int i = 0; i < mNumPlayers; i++) - if (mPlayer[i]->isAlive()) - { - // Input a la izquierda - if (mInput->checkInput(INPUT_LEFT, REPEAT_TRUE, mOptions->input[i].deviceType, mOptions->input[i].id)) - { - mPlayer[i]->setInput(INPUT_LEFT); - mDemo.keys.left = 1; - } - else - { - // Input a la derecha - if (mInput->checkInput(INPUT_RIGHT, REPEAT_TRUE, mOptions->input[i].deviceType, mOptions->input[i].id)) - { - mPlayer[i]->setInput(INPUT_RIGHT); - mDemo.keys.right = 1; - } - else - { - // Ninguno de los dos inputs anteriores - mPlayer[i]->setInput(NO_INPUT); - mDemo.keys.noInput = 1; - } - } - // Comprueba el input de disparar al centro - if (mInput->checkInput(INPUT_BUTTON_2, REPEAT_TRUE, mOptions->input[i].deviceType, mOptions->input[i].id)) - { - if (mPlayer[i]->canFire()) - { - mPlayer[i]->setInput(INPUT_FIRE_UP); - createBullet(mPlayer[i]->getPosX() + (mPlayer[i]->getWidth() / 2) - 4, mPlayer[i]->getPosY() + (mPlayer[i]->getHeight() / 2), BULLET_UP, mPlayer[i]->isPowerUp(), i); - mPlayer[i]->setFireCooldown(10); - - // Reproduce el sonido de disparo - JA_PlaySound(mSoundBullet); - - mDemo.keys.fire = 1; - } - } - - // Comprueba el input de disparar a la izquierda - if (mInput->checkInput(INPUT_BUTTON_1, REPEAT_TRUE, mOptions->input[i].deviceType, mOptions->input[i].id)) - { - if (mPlayer[i]->canFire()) - { - mPlayer[i]->setInput(INPUT_FIRE_LEFT); - createBullet(mPlayer[i]->getPosX() + (mPlayer[i]->getWidth() / 2) - 4, mPlayer[i]->getPosY() + (mPlayer[i]->getHeight() / 2), BULLET_LEFT, mPlayer[i]->isPowerUp(), i); - mPlayer[i]->setFireCooldown(10); - - // Reproduce el sonido de disparo - JA_PlaySound(mSoundBullet); - - mDemo.keys.fireLeft = 1; - } - } - - // Comprueba el input de disparar a la derecha - if (mInput->checkInput(INPUT_BUTTON_3, REPEAT_TRUE, mOptions->input[i].deviceType, mOptions->input[i].id)) - { - if (mPlayer[i]->canFire()) - { - mPlayer[i]->setInput(INPUT_FIRE_RIGHT); - createBullet(mPlayer[i]->getPosX() + (mPlayer[i]->getWidth() / 2) - 4, mPlayer[i]->getPosY() + (mPlayer[i]->getHeight() / 2), BULLET_RIGHT, mPlayer[i]->isPowerUp(), i); - mPlayer[i]->setFireCooldown(10); - - // Reproduce el sonido de disparo - JA_PlaySound(mSoundBullet); - - mDemo.keys.fireRight = 1; - } - } - - // Comprueba el input de pausa - if (mInput->checkInput(INPUT_CANCEL, REPEAT_FALSE, mOptions->input[i].deviceType, mOptions->input[i].id)) - { - mSection.subsection = GAME_SECTION_PAUSE; - - if (JA_GetMusicState() == JA_MUSIC_PLAYING) - JA_PauseMusic(); - } - - if (mDemo.counter < TOTAL_DEMO_DATA) - { - if (mDemo.recording) - mDemo.dataFile[mDemo.counter] = mDemo.keys; - mDemo.counter++; - } - else if (mDemo.recording) - { - mSection.name = PROG_SECTION_QUIT; - } - } -} - -// Pinta diferentes mensajes en la pantalla -void Game::renderMessages() -{ - // GetReady - if ((mCounter < STAGE_COUNTER) && (!mDemo.enabled)) - { - mSpriteGetReady->setPosX((int)mGetReadyBitmapPath[mCounter]); - //mSpriteGetReady->render(); - //const color_t color = {0x17, 0x17, 0x26}; - //mTextBig->writeShadowed((int)mGetReadyBitmapPath[mCounter], PLAY_AREA_CENTER_Y - 8, mLang->getText(75), color, 2); - //mTextBig->writeDX(TXT_STROKE, (int)mGetReadyBitmapPath[mCounter], PLAY_AREA_CENTER_Y - 8, mLang->getText(75), 1, noColor, 1, shdwTxtColor); - mTextNokiaBig2->write((int)mGetReadyBitmapPath[mCounter], PLAY_AREA_CENTER_Y - 8, mLang->getText(75), -2); - } - - // Time Stopped - if (mTimeStopped) - { - if ((mTimeStoppedCounter > 100) || (mTimeStoppedCounter % 10 > 4)) - mTextNokia2->writeDX(TXT_CENTER, PLAY_AREA_CENTER_X, PLAY_AREA_FIRST_QUARTER_Y, mLang->getText(36) + std::to_string(mTimeStoppedCounter / 10), -1, noColor, 1, shdwTxtColor); - //{ - // mTextNokiaBig2->writeDX(TXT_CENTER, PLAY_AREA_CENTER_X, PLAY_AREA_FIRST_QUARTER_Y, mLang->getText(36), -2); - // mTextNokiaBig2->writeDX(TXT_CENTER, PLAY_AREA_CENTER_X, PLAY_AREA_FIRST_QUARTER_Y + mTextNokiaBig2->getCharacterWidth() + 2, std::to_string(mTimeStoppedCounter / 10), -2); - //} - - if (mTimeStoppedCounter > 100) - { - if (mTimeStoppedCounter % 30 == 0) - JA_PlaySound(mSoundClock, false); - } - else - { - if (mTimeStoppedCounter % 15 == 0) - JA_PlaySound(mSoundClock, false); - } - } - - // D E M O - if (mDemo.enabled) - if (mDemo.counter % 30 > 14) - mTextNokiaBig2->writeDX(TXT_CENTER, PLAY_AREA_CENTER_X, PLAY_AREA_FIRST_QUARTER_Y, mLang->getText(37), 0, noColor, 2, shdwTxtColor); - - // STAGE NUMBER - if (mStageBitmapCounter < STAGE_COUNTER) - { - std::string text = mLang->getText(38) + std::to_string(mStage[mCurrentStage].number); - if (!mGameCompleted) - { - mTextNokiaBig2->writeDX(TXT_CENTER, PLAY_AREA_CENTER_X, mStageBitmapPath[mStageBitmapCounter], text, -2, noColor, 2, shdwTxtColor); - } - else - { // Texto de juego completado - text = mLang->getText(50); - mTextNokiaBig2->writeDX(TXT_CENTER, PLAY_AREA_CENTER_X, mStageBitmapPath[mStageBitmapCounter], text, -2, noColor, 1, shdwTxtColor); - mTextNokiaBig2->writeDX(TXT_CENTER, PLAY_AREA_CENTER_X, mStageBitmapPath[mStageBitmapCounter] + mTextNokiaBig2->getCharacterWidth() + 2, mLang->getText(76), -1, noColor, 1, shdwTxtColor); - } - } -} - -// Habilita el efecto del item de detener el tiempo -void Game::enableTimeStopItem() -{ - stopAllBalloons(TIME_STOPPED_COUNTER); - setTimeStopped(true); - incTimeStoppedCounter(TIME_STOPPED_COUNTER); - if (JA_GetMusicState() == JA_MUSIC_PLAYING) - JA_PauseMusic(); -} - -// Deshabilita el efecto del item de detener el tiempo -void Game::disableTimeStopItem() -{ - mTimeStopped = false; - setTimeStoppedCounter(0); - startAllBalloons(); - if (JA_GetMusicState() == JA_MUSIC_PAUSED) - JA_ResumeMusic(); -} - -// Agita la pantalla -void Game::shakeScreen() -{ - const int v[] = {-1, 1, -1, 1, -1, 1, -1, 0}; - for (int n = 0; n < 8; n++) - { - // Limpia la pantalla - SDL_SetRenderDrawColor(mRenderer, 0x00, 0x00, 0x00, 0xFF); - SDL_RenderClear(mRenderer); - - // Dibuja los objetos - mSpriteBackground->setPosX(0); - mSpriteBackground->setWidth(1); - mSpriteBackground->setSpriteClip(0, 0, 1, 192); - renderBackground(); - - mSpriteBackground->setPosX(255); - mSpriteBackground->setSpriteClip(255, 0, 1, 192); - mSpriteBackground->render(); - - mSpriteBackground->setPosX(v[n]); - mSpriteBackground->setWidth(256); - mSpriteBackground->setSpriteClip(0, 0, 256, 192); - mSpriteBackground->render(); - - mSpriteGrass->render(); - renderBalloons(); - renderBullets(); - renderItems(); - for (int i = 0; i < mNumPlayers; i++) - mPlayer[i]->render(); - renderScoreBoard(); - - // Actualiza la pantalla - SDL_RenderPresent(mRenderer); - SDL_Delay(50); - } -} - // Bucle para el juego section_t Game::run() { @@ -3098,35 +288,15 @@ section_t Game::run() while (mSection.name == PROG_SECTION_GAME) { - // Sección juego en pausa - if (mSection.subsection == GAME_SECTION_PAUSE) - runPausedGame(); - - // Sección Game Over - if (mSection.subsection == GAME_SECTION_GAMEOVER) - runGameOverScreen(); - // Sección juego jugando if ((mSection.subsection == GAME_SECTION_PLAY_1P) || (mSection.subsection == GAME_SECTION_PLAY_2P)) { - // Si la música no está sonando - if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) - { - // Reproduce la música - if (!mGameCompleted) - if (mPlayer[0]->isAlive()) - JA_PlayMusic(mMusicPlaying); - } - // Comprueba que la diferencia de ticks sea mayor a la velocidad del juego if (SDL_GetTicks() - mTicks > mTicksSpeed) { // Actualiza el contador de ticks mTicks = SDL_GetTicks(); - // Actualiza el contador de juego - mCounter++; - // Comprueba los eventos que hay en la cola while (SDL_PollEvent(mEventHandler) != 0) { @@ -3137,21 +307,12 @@ section_t Game::run() break; } } - - // Actualiza la lógica del juego - updatePlayField(); } // Limpia la pantalla SDL_SetRenderDrawColor(mRenderer, 0x00, 0x00, 0x00, 0xFF); SDL_RenderClear(mRenderer); - // Dibuja los objetos - renderPlayField(); - - // Pinta la informacion de debug - renderDebugInfo(); - // Actualiza la pantalla SDL_RenderPresent(mRenderer); } @@ -3159,325 +320,3 @@ section_t Game::run() return mSection; } - -// Bucle para el menu de pausa del juego -void Game::runPausedGame() -{ - // Reinicia el menu - mMenuPause->reset(); - - while ((mSection.subsection == GAME_SECTION_PAUSE) && (mSection.name == PROG_SECTION_GAME)) - { - // 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) - { - mSection.name = PROG_SECTION_QUIT; - break; - } - } - - // Calcula la lógica de los objetos - if (SDL_GetTicks() - mTicks > mTicksSpeed) - { - // Actualiza el contador de ticks - mTicks = SDL_GetTicks(); - - // Actualiza la lógica del menu - mMenuPause->update(); - mFade->update(); - if (mFade->hasEnded()) - { - mSection.name = PROG_SECTION_TITLE; - mSection.subsection = TITLE_SECTION_1; - JA_StopMusic(); - break; - } - } - - // Dibuja los objetos - //renderBackground(); - //renderBalloons(); - //renderBullets(); - //for (int i = 0; i < mNumPlayers; i++) - // mPlayer[i]->render(); - //renderScoreBoard(); - renderPlayField(); - mMenuPause->render(); - mFade->render(); - - // Actualiza la pantalla - SDL_RenderPresent(mRenderer); - - // Comprueba las entradas para el menu - mMenuPause->checkInput(); - - // Comprueba si se ha seleccionado algún item del menú - switch (mMenuPause->getItemSelected()) - { - case 0: - //mMenuPause->reset(); - mSection.name = PROG_SECTION_GAME; - if (mNumPlayers == 1) - mSection.subsection = GAME_SECTION_PLAY_1P; - else - mSection.subsection = GAME_SECTION_PLAY_2P; - if (JA_GetMusicState() == JA_MUSIC_PAUSED) - JA_ResumeMusic(); - break; - - case 1: - //mMenuPause->reset(); - mFade->setFadeType(FADE_CENTER); - mFade->activateFade(); - break; - - default: - break; - } - } -} - -// Bucle para la pantalla de game over -void Game::runGameOverScreen() -{ - // Guarda los puntos - saveScoreFile(); - - // Reinicia el menu - mMenuGameOver->reset(); - - while ((mSection.subsection == GAME_SECTION_GAMEOVER) && (mSection.name == PROG_SECTION_GAME)) - { - // 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) - { - mSection.name = PROG_SECTION_QUIT; - break; - } - } - - // Calcula la lógica de los objetos - if (SDL_GetTicks() - mTicks > mTicksSpeed) - { - // Actualiza el contador de ticks - mTicks = SDL_GetTicks(); - - // Actualiza la lógica del menu - mMenuGameOver->update(); - mFade->update(); - if (mFade->hasEnded()) - { - switch (mPostFade) - { - case 0: // YES - mSection.name = PROG_SECTION_GAME; - if (mNumPlayers == 1) - mSection.subsection = GAME_SECTION_PLAY_1P; - else - mSection.subsection = GAME_SECTION_PLAY_2P; - init(); - break; - - case 1: // NO - mSection.name = PROG_SECTION_TITLE; - mSection.subsection = TITLE_SECTION_1; - break; - - default: - break; - } - - break; - } - } - - // Limpia la pantalla - SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 0xFF); - SDL_RenderClear(mRenderer); - - // Dibuja los objetos - if (mNumPlayers == 1) - { - mTextBig->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - (BLOCK * 4), mLang->getText(43)); - mText->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - (BLOCK * 1), mLang->getText(44) + std::to_string(mPlayer[0]->getScore())); - } - else - { - mTextBig->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - 36, mLang->getText(43)); - mText->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - 12, mLang->getText(77) + std::to_string(mPlayer[0]->getScore())); - mText->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y, mLang->getText(78) + std::to_string(mPlayer[1]->getScore())); - } - mText->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y + BLOCK * 2, mLang->getText(45)); - mMenuGameOver->render(); - mFade->render(); - - // Muestra la pantalla - SDL_RenderPresent(mRenderer); - - // Comprueba las entradas para el menu - mMenuGameOver->checkInput(); - - // Comprueba si se ha seleccionado algún item del menú - switch (mMenuGameOver->getItemSelected()) - { - case 0: // YES - mPostFade = 0; - mFade->activateFade(); - break; - - case 1: // NO - mPostFade = 1; - mFade->activateFade(); - break; - - default: - break; - } - } -} - -// Dibuja la informacion de debug en pantalla -void Game::renderDebugInfo() -{ - const color_t color = {0xFF, 0x20, 0x20}; - //mText->writeShadowed(2, 2 + 0 * BLOCK, "POW: " + std::to_string(mPlayer[0]->mPowerUpCounter), color); - //if (mHelper.needCoffeeMachine) - // mText->writeShadowed(2, 2 + 1 * BLOCK, "NEED COFFEMACHINE", color); - - if (mDebug.enabled) - { - //SDL_RenderSetLogicalSize(mRenderer, SCREEN_WIDTH * 2, SCREEN_HEIGHT * 2); - mText->writeShadowed(2, 2 + 0 * BLOCK, "menace(umb): " + std::to_string(mMenaceCurrent) + "(" + std::to_string(mMenaceThreshold) + ")", color); - mText->writeShadowed(2, 2 + 1 * BLOCK, "currentPower: " + std::to_string(mStage[mCurrentStage].currentPower), color); - mText->writeShadowed(2, 2 + 2 * BLOCK, "mCurrentStage:" + std::to_string(mCurrentStage), color); - mText->writeShadowed(2, 2 + 3 * BLOCK, "mCounter: " + std::to_string(mCounter), color); - mText->writeShadowed(2, 2 + 4 * BLOCK, "(R)enemyset: " + std::to_string(mDebug.enemySet), color); - mText->writeShadowed(2, 2 + 5 * BLOCK, "RGB: " + std::to_string(mDebug.gradR) + "," + std::to_string(mDebug.gradG) + "," + std::to_string(mDebug.gradB), color); - mText->writeShadowed(2, 2 + 6 * BLOCK, "(I)invuln: " + std::to_string(mPlayer[0]->getInvulnerableCounter()), color); - mText->writeShadowed(2, 2 + 7 * BLOCK, "balloons: " + std::to_string(countBalloons()), color); - mText->writeShadowed(2, 2 + 8 * BLOCK, "balloonsPop: " + std::to_string(mBalloonsPopped), color); - mText->writeShadowed(2, 2 + 9 * BLOCK, "(Z-X)ballSped:" + std::to_string(mEnemySpeed), color); - mText->writeShadowed(2, 2 + 10 * BLOCK, "EGcounter: " + std::to_string(mGameCompletedCounter), color); - } -} - -// Indica si se puede crear una powerball -bool Game::canPowerBallBeCreated() -{ - if ((!mPowerBallEnabled) && (calculateScreenPower() > POWERBALL_SCREENPOWER_MINIMUM) && (mPowerBallCounter == 0)) - return true; - else - return false; -} - -// Calcula el poder actual de los globos en pantalla -int Game::calculateScreenPower() -{ - int power = 0; - - for (int i = 0; i < MAX_BALLOONS; i++) - if (mBalloon[i]->isEnabled()) - power += mBalloon[i]->getPower(); - - return power; -} - -// Inicializa las variables que contienen puntos de ruta para mover objetos -void Game::initPaths() -{ - // Letrero de STAGE # - const int firstPart = STAGE_COUNTER / 4; // 50 - const int secondPart = firstPart * 3; // 150 - const int centerPoint = PLAY_AREA_CENTER_Y - (BLOCK * 2); - const int distance = (PLAY_AREA_BOTTOM) - (PLAY_AREA_CENTER_Y - 16); - - for (int i = 0; i < STAGE_COUNTER; i++) - { - if (i < firstPart) - mStageBitmapPath[i] = (mSin[(int)((i * 1.8f) + 90)] * (distance) + centerPoint); - else if (i < secondPart) - mStageBitmapPath[i] = (int)centerPoint; - else - mStageBitmapPath[i] = (mSin[(int)(((i - 149) * 1.8f) + 90)] * (centerPoint + 17) - 17); - } - - // Letrero de GetReady - const int size = mTextNokiaBig2->lenght(mLang->getText(75), -2); - - const float start1 = PLAY_AREA_LEFT - size; - const float finish1 = PLAY_AREA_CENTER_X - (size / 2); - - const float start2 = finish1; - const float finish2 = PLAY_AREA_RIGHT; - - const float distance1 = finish1 - start1; - const float distance2 = finish2 - start2; - - for (int i = 0; i < STAGE_COUNTER; i++) - { - if (i < firstPart) - { - mGetReadyBitmapPath[i] = mSin[(int)(i * 1.8f)]; - mGetReadyBitmapPath[i] *= distance1; - mGetReadyBitmapPath[i] -= size; - } - else if (i < secondPart) - mGetReadyBitmapPath[i] = (int)finish1; - else - { - mGetReadyBitmapPath[i] = mSin[(int)((i - 150) * 1.8f)]; - mGetReadyBitmapPath[i] *= distance2; - mGetReadyBitmapPath[i] += finish1; - } - } -} - -// Actualiza el tramo final de juego, una vez completado -void Game::updateGameCompleted() -{ - if (mGameCompleted) - mGameCompletedCounter++; - - if (mGameCompletedCounter == 500) - mSection.subsection = GAME_SECTION_GAMEOVER; -} - -// Actualiza las variables de ayuda -void Game::updateHelper() -{ - // El ayudante solo funciona para un jugador - // Solo ofrece ayuda cuando la amenaza o la velocidad es elevada - if (mMenaceCurrent > 15) - { - if (mPlayer[0]->getCoffees() == 0) - mHelper.needCoffee = true; - else - mHelper.needCoffee = false; - - if (!mPlayer[0]->isPowerUp()) - mHelper.needCoffeeMachine = true; - else - mHelper.needCoffeeMachine = false; - } - else - { - mHelper.needCoffee = false; - mHelper.needCoffeeMachine = false; - } -} - -// Comprueba si todos los jugadores han muerto -bool Game::allPlayersAreDead() -{ - bool success = true; - for (int i = 0; i < mNumPlayers; i++) - success &= (!mPlayer[i]->isAlive()); - - return success; -} \ No newline at end of file diff --git a/source/game.h b/source/game.h index 14aac9d..2a0b55f 100644 --- a/source/game.h +++ b/source/game.h @@ -7,11 +7,6 @@ #include "movingsprite.h" #include "smartsprite.h" -#include "player.h" -#include "balloon.h" -#include "bullet.h" -#include "item.h" - #include "text.h" #include "writer.h" #include "menu.h" @@ -26,481 +21,27 @@ class Game { private: - struct enemyInits_t - { - int x; // Posición en el eje X donde crear al enemigo - int y; // Posición en el eje Y donde crear al enemigo - float velX; // Velocidad inicial en el eje X - Uint8 kind; // Tipo de enemigo - Uint16 creationCounter; // Temporizador para la creación del enemigo - }; - - struct enemyFormation_t // Contiene la información de una formación enemiga - { - Uint8 numberOfEnemies; // Cantidad de enemigos que forman la formación - enemyInits_t init[MAX_NUMBER_OF_ENEMIES_IN_A_FORMATION]; // Vector con todas las inicializaciones de los enemigos de la formación - }; - enemyFormation_t mEnemyFormation[NUMBER_OF_ENEMY_FORMATIONS]; // Vector con todas las formaciones enemigas - - struct enemyPool_t - { - enemyFormation_t *set[10]; // Conjunto de formaciones enemigas - }; - enemyPool_t mEnemyPool[10]; // Variable con los diferentes conjuntos de formaciones enemigas - - struct stage_t // Contiene todas las variables relacionadas con una fase - { - enemyPool_t *enemyPool; // El conjunto de formaciones enemigas de la fase - Uint16 currentPower; // Cantidad actual de poder - Uint16 powerToComplete; // Cantidad de poder que se necesita para completar la fase - Uint8 maxMenace; // Umbral máximo de amenaza de la fase - Uint8 minMenace; // Umbral mínimo de amenaza de la fase - Uint8 number; // Numero de fase - }; - - struct effect_t - { - bool flash; // Indica si se ha de pintar la pantalla de blanco - bool shake; // Indica si se ha de agitar la pantalla - Uint8 shakeCounter; // Contador para medir el tiempo que dura el efecto - }; - - struct helper_t - { - bool needCoffee; // Indica si se necesitan cafes - bool needCoffeeMachine; // Indica si se necesita PowerUp - bool needPowerBall; // Indica si se necesita una PowerBall - int counter; // Contador para no dar ayudas consecutivas - int itemPoints1Odds; // Probabilidad de aparición del objeto - int itemPoints2Odds; // Probabilidad de aparición del objeto - int itemPoints3Odds; // Probabilidad de aparición del objeto - int itemClockOdds; // Probabilidad de aparición del objeto - int itemCoffeeOdds; // Probabilidad de aparición del objeto - int itemCoffeeMachineOdds; // Probabilidad de aparición del objeto - }; - - SDL_Renderer *mRenderer; // El renderizador de la ventana - std::string *mFileList; // Lista de ficheros con los recursos - Lang *mLang; // Objeto para gestionar los textos en diferentes idiomas - - int mNumPlayers; // Numero de jugadores - Player *mPlayer[2]; // Vector con los jugadores jugador - Input *mInput; // Manejador de entrada - - Balloon *mBalloon[MAX_BALLOONS]; // Vector con los objetos globo - Bullet *mBullet[MAX_BULLETS]; // Vector con los objetos bala - Item *mItem[MAX_ITEMS]; // Vector con los objetos item - SmartSprite *mSmartSprite[MAX_SMART_SPRITES]; // Vector para almacenar y gestionar SmartSprites - - LTexture *mTextureBalloon; // Textura para los enemigos - LTexture *mTextureBullet; // Textura para las balas - LTexture *mTextureGameBG; // Textura para el fondo del juego - LTexture *mTextureGameText; // Textura para los sprites con textos - LTexture *mTextureItems; // Textura para los items - LTexture *mTexturePlayer1Head; // Textura para la cabeza del jugador1 - LTexture *mTexturePlayer1Body; // Textura para el cuerpo del jugador1 - LTexture *mTexturePlayer1Death; // Textura para la animación de muerte del jugador1 - LTexture *mTexturePlayer1Legs; // Textura para las piernas del jugador - LTexture *mTexturePlayer2Head; // Textura para la cabeza del jugador2 - LTexture *mTexturePlayer2Body; // Textura para el cuerpo del jugador2 - LTexture *mTexturePlayer2Death; // Textura para la animación de muerte del jugador2 - LTexture *mTexturePlayer2Legs; // Textura para las piernas del jugador - LTexture *mTextureText; // Textura para el texto del juego - LTexture *mTextureTextScoreBoard; // Textura para el texto del marcador - LTexture *mTextureTextBig; // Textura para el texto grande - LTexture *mTextureTextNokia2; // Textura para la fuente de texto Nokia - LTexture *mTextureTextNokiaBig2; // Textura para la fuente de texto Nokia grande - - Text *mText; // Fuente para los textos del juego - Text *mTextBig; // Fuente de texto grande - Text *mTextScoreBoard; // Fuente para el marcador del juego - Text *mTextNokia2; // Otra fuente de texto para mesajes - Text *mTextNokiaBig2; // Y la versión en grande - - Menu *mMenuGameOver; // Menú de la pantalla de game over - Menu *mMenuPause; // Menú de la pantalla de pausa - - Fade *mFade; // Objeto para renderizar fades + SDL_Renderer *mRenderer; // El renderizador de la ventana SDL_Event *mEventHandler; // Manejador de eventos + std::string *mFileList; // Lista de ficheros con los recursos + Lang *mLang; // Objeto para gestionar los textos en diferentes idiomas + Input *mInput; // Manejador de entrada + Text *mText; // Fuente para los textos del juego + Fade *mFade; // Objeto para renderizar fades - MovingSprite *mClouds1a; // Sprite para las nubes superiores - MovingSprite *mClouds1b; // Sprite para las nubes superiores - MovingSprite *mClouds2a; // Sprite para las nubes inferiores - MovingSprite *mClouds2b; // Sprite para las nubes inferiores - SmartSprite *m1000Bitmap; // Sprite con el texto 1.000 - SmartSprite *m2500Bitmap; // Sprite con el texto 2.500 - SmartSprite *m5000Bitmap; // Sprite con el texto 5.000 - Sprite *mSpriteBackground; // Sprite con los graficos frontales del fondo - Sprite *mSpriteGetReady; // Sprite para el texto de GetReady del principio de la partida - Sprite *mSpriteGradient; // Sprite con los graficos del degradado de color de fondo - Sprite *mSpriteGrass; // Sprite para la hierba - Sprite *mSpritePowerMeter; // Sprite para el medidor de poder de la fase - Sprite *mSpriteScoreBoard; // Sprite para el fondo del marcador + LTexture *mTextureText; // Textura para la fuente de texto Nokia grande - JA_Sound mSoundBalloon; // Sonido para la explosión del globo - JA_Sound mSoundBullet; // Sonido para los disparos - JA_Sound mSoundPlayerCollision; // Sonido para la colisión del jugador con un enemigo - JA_Sound mSoundHiScore; // Sonido para cuando se alcanza la máxima puntuación - JA_Sound mSoundItemDrop; // Sonido para cuando se genera un item - JA_Sound mSoundItemPickup; // Sonido para cuando se recoge un item - JA_Sound mSoundCoffeeOut; // Sonido para cuando el jugador pierde el café al recibir un impacto - JA_Sound mSoundStageChange; // Sonido para cuando se cambia de fase - JA_Sound mSoundBubble1; // Sonido para cuando el jugador muere - JA_Sound mSoundBubble2; // Sonido para cuando el jugador muere - JA_Sound mSoundBubble3; // Sonido para cuando el jugador muere - JA_Sound mSoundBubble4; // Sonido para cuando el jugador muere - JA_Sound mSoundClock; // Sonido para cuando se detiene el tiempo con el item reloj - JA_Sound mSoundPowerBall; // Sonido para cuando se explota una Power Ball - JA_Sound mSoundCollision; // Sonido para cuando la máquina de café toca el suelo - - JA_Music mMusicPlaying; // Musica de fondo - - Uint32 mTicks; // Contador de ticks para ajustar la velocidad del programa + Uint32 mTicks; // Contador de ticks para ajustar la velocidad del programa Uint8 mTicksSpeed; // Velocidad a la que se repiten los bucles del programa - Uint32 mHiScore; // Puntuación máxima - bool mHiScoreAchieved; // Indica si se ha superado la puntuación máxima section_t mSection; // Seccion actual dentro del juego - stage_t mStage[10]; // Variable con los datos de cada pantalla - Uint8 mCurrentStage; // Indica la fase actual - Uint8 mStageBitmapCounter; // Contador para el tiempo visible del texto de Stage - float mStageBitmapPath[STAGE_COUNTER]; // Vector con los puntos Y por donde se desplaza el texto - float mGetReadyBitmapPath[STAGE_COUNTER]; // Vector con los puntos X por donde se desplaza el texto - Uint16 mDeathCounter; // Contador para la animación de muerte del jugador - Uint8 mDeathIndex; // Indice del vector de smartsprites que contiene el sprite del jugador - Uint8 mMenaceCurrent; // Nivel de amenaza actual - Uint8 mMenaceThreshold; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el numero de globos - bool mTimeStopped; // Indica si el tiempo está detenido - Uint16 mTimeStoppedCounter; // Temporizador para llevar la cuenta del tiempo detenido - Uint8 mRemainingExplosions; // Cantidad de explosiones restantes - Uint16 mRemainingExplosionsCounter; // Temporizador para la cantidad de explosiones restantes - bool mExplosionTime; // Indica si las explosiones estan en marcha - Uint32 mCounter; // Contador para el juego - Uint32 mScoreDataFile[TOTAL_SCORE_DATA]; // Datos del fichero de puntos - SDL_Rect mGradientRect[4]; // Vector con las coordenadas de los 4 gradientes - Uint16 mBalloonsPopped; // Lleva la cuenta de los globos explotados - Uint8 mLastEnemyDeploy; // Guarda cual ha sido la última formación desplegada para no repetir; - Uint8 mEnemyDeployCounter; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero - float mEnemySpeed; // Velocidad a la que se mueven los enemigos - float mDefaultEnemySpeed; // Velocidad base de los enemigos, sin incrementar - effect_t mEffect; // Variable para gestionar los efectos visuales - helper_t mHelper; // Variable para gestionar las ayudas - bool mPowerBallEnabled; // Indica si hay una powerball ya activa - Uint8 mPowerBallCounter; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra - bool mCoffeeMachineEnabled; // Indica si hay una máquina de café en el terreno de juego - Uint8 mPostFade; // Qué hacer al acabar el fade - float mSin[360]; // Vector con los valores del seno para 360 grados - bool mGameCompleted; // Indica si se ha completado la partida, llegando al final de la ultima pantalla - int mGameCompletedCounter; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos - Uint8 mDifficulty; // Dificultad del juego - float mDifficultyScoreMultiplier; // Multiplicador de puntos en función de la dificultad - struct options_t *mOptions; // Variable con todas las variables de las opciones del programa - Uint8 mOnePlayerControl; // Variable para almacenar el valor de las opciones - - struct demo_t - { - bool enabled; // Indica si está activo el modo demo - bool recording; // Indica si está activado el modo para grabar la demo - Uint16 counter; // Contador para el modo demo - demoKeys_t keys; // Variable con las pulsaciones de teclas del modo demo - demoKeys_t dataFile[TOTAL_DEMO_DATA]; // Datos del fichero con los movimientos para la demo - }; - demo_t mDemo; // Variable con todas las variables relacionadas con el modo demo - - struct debug_t - { - bool enabled; // Indica si se va a mostrar la información de debug - Uint8 enemySet; // Escoge el set enemigo a generar - Uint8 gradR, gradG, gradB; // Colores RGB para modificar el color del gradiente de fondo - float hudW, hudH; // Multiplica el tamaño del hud de debug; - }; - debug_t mDebug; - - // Inicializa el vector con los valores del seno - void initSin(); // Inicializa las variables necesarias para la sección 'Game' void init(); - // Carga los recursos necesarios para la sección 'Game' - bool loadMedia(); - - // Carga el fichero de puntos - bool loadScoreFile(); - - // Carga el fichero de datos para la demo - bool loadDemoFile(); - - // Guarda el fichero de puntos - bool saveScoreFile(); - - // Guarda el fichero de datos para la demo - bool saveDemoFile(); - - // Inicializa las formaciones enemigas - void initEnemyFormations(); - - // Inicializa los conjuntos de formaciones - void initEnemyPools(); - - // Inicializa las fases del juego - void initGameStages(); - - // Crea una formación de enemigos - void deployEnemyFormation(); - - // Aumenta el poder de la fase - void increaseStageCurrentPower(Uint8 power); - - // Establece el valor de la variable - void setHiScore(Uint32 score); - - // Actualiza el valor de HiScore en caso necesario - void updateHiScore(); - - // Transforma un valor numérico en una cadena de 6 cifras - std::string updateScoreText(Uint32 num); - - // Pinta el marcador en pantalla usando un objeto texto - void renderScoreBoard(); - - // Actualiza las variables del jugador - void updatePlayer(); - - // Actualiza las variables de la fase - void updateStage(); - - // Actualiza el estado de muerte - void updateDeath(); - - // Renderiza el fade final cuando se acaba la partida - void renderDeathFade(int counter); - - // Actualiza los globos - void updateBalloons(); - - // Pinta en pantalla todos los globos activos - void renderBalloons(); - - // Devuelve el primer indice no activo del vector de globos - Uint8 getBalloonFreeIndex(); - - // Crea un globo nuevo en el vector de globos - Uint8 createNewBalloon(float x, int y, Uint8 kind, float velx, float speed, Uint16 stoppedcounter, LTexture *texture); - - // Crea una PowerBall - void createPowerBall(); - - // Establece a cero todos los valores del vector de objetos globo - void resetBalloons(); - - // Establece la velocidad de los globos - void setBalloonSpeed(float speed); - - // Incrementa la velocidad de los globos - void incBalloonSpeed(); - - // Decrementa la velocidad de los globos - void decBalloonSpeed(); - - // Actualiza la velocidad de los globos en funcion del poder acumulado de la fase - void updateBalloonSpeed(); - - // Explosiona un globo. Lo destruye y crea otros dos si es el caso - void popBalloon(Uint8 index); - - // Explosiona un globo. Lo destruye - void destroyBalloon(Uint8 index); - - // Explosiona todos los globos - void popAllBalloons(); - - // Destruye todos los globos - void destroyAllBalloons(); - - // Detiene todos los globos - void stopAllBalloons(Uint16 time); - - // Pone en marcha todos los globos - void startAllBalloons(); - - // Obtiene el numero de globos activos - Uint8 countBalloons(); - - // Comprueba la colisión entre el jugador y los globos activos - bool checkPlayerBalloonCollision(int index); - - // Comprueba la colisión entre el jugador y los items - void checkPlayerItemCollision(int index); - - // Comprueba la colisión entre las balas y los globos - void checkBulletBalloonCollision(); - - // Mueve las balas activas - void moveBullets(); - - // Pinta las balas activas - void renderBullets(); - - // Devuelve el primer indice no activo del vector de balas - Uint8 getBulletFreeIndex(); - - // Establece a cero todos los valores del vector de objetos bala - void resetBullets(); - - // Crea un objeto bala - void createBullet(int x, int y, Uint8 kind, bool poweredUp, int owner); - - // Actualiza los items - void updateItems(); - - // Pinta los items activos - void renderItems(); - - // Devuelve el primer indice no activo del vector de items - Uint8 getItemFreeIndex(); - - // Establece a cero todos los valores del vector de objetos item - void resetItems(); - - // Devuelve un item en función del azar - Uint8 dropItem(); - - // Crea un objeto item - void createItem(int x, int y, Uint8 kind); - - // Crea un objeto SmartSprite - void createItemScoreSprite(int x, int y, SmartSprite *sprite); - - // Dibuja el efecto de flash - void renderFlashEffect(); - - // Actualiza el efecto de agitar la pantalla - void updateShakeEffect(); - - // Crea un SmartSprite para arrojar el item café al recibir un impacto - void throwCoffee(int x, int y); - - // Crea un SmartSprite para arrojar al jugador al morir - void throwPlayer(int x, int y, int index); - - // Actualiza los SmartSprites - void updateSmartSprites(); - - // Pinta los SmartSprites activos - void renderSmartSprites(); - - // Devuelve el primer indice no activo del vector de SmartSprites - Uint8 getSmartSpriteFreeIndex(); - - // Establece a cero todos los valores del vector de objetos SmafrtSprite - void resetSmartSprites(); - - // Acciones a realizar cuando el jugador muere - void killPlayer(int index); - - // Obtiene el valor de la variable - Uint8 getSubsection(); - - // Calcula y establece el valor de amenaza en funcion de los globos activos - void evaluateAndSetMenace(); - - // Obtiene el valor de la variable - Uint8 getMenace(); - - // Establece el valor de la variable - void setTimeStopped(bool value); - - // Obtiene el valor de la variable - bool isTimeStopped(); - - // Establece el valor de la variable - void setTimeStoppedCounter(Uint16 value); - - // Incrementa el valor de la variable - void incTimeStoppedCounter(Uint16 value); - - // Actualiza la variable EnemyDeployCounter - void updateEnemyDeployCounter(); - - // Actualiza y comprueba el valor de la variable - void updateTimeStoppedCounter(); - - // Establece el valor de la variable - void setExplosionTime(bool value); - - // Obtiene el valor de la variable - bool isExplosionTime(); - - // Establece el valor de la variable - void setRemainingExplosions(Uint8 value); - - // Actualiza y comprueba el valor de la variable - void updateRemainingExplosionsCounter(); - - // Gestiona el nivel de amenaza - void updateMenace(); - - // Actualiza el campo de juego - void updatePlayField(); - - // Actualiza el fondo - void updateBackground(); - - // Dibuja el fondo - void renderBackground(); - - // Dibuja el campo de juego - void renderPlayField(); - - // Gestiona las entradas desde el mando de juego - bool checkGameController(Uint8 state); - - // Gestiona la entrada durante el juego - void checkGameInput(); - - // Pinta diferentes mensajes en la pantalla - void renderMessages(); - - // Habilita el efecto del item de detener el tiempo - void enableTimeStopItem(); - - // Deshabilita el efecto del item de detener el tiempo - void disableTimeStopItem(); - - // Agita la pantalla - void shakeScreen(); - - // Bucle para el menu de pausa del juego - void runPausedGame(); - - // Bucle para la pantalla de game over - void runGameOverScreen(); - - // Dibuja la informacion de debug en pantalla - void renderDebugInfo(); - - // Indica si se puede crear una powerball - bool canPowerBallBeCreated(); - - // Calcula el poder actual de los globos en pantalla - int calculateScreenPower(); - - // Inicializa las variables que contienen puntos de ruta para mover objetos - void initPaths(); - - // Actualiza el tramo final de juego, una vez completado - void updateGameCompleted(); - - // Actualiza las variables de ayuda - void updateHelper(); - - // Comprueba si todos los jugadores han muerto - bool allPlayersAreDead(); - public: // Constructor - Game(int numPlayers, SDL_Renderer *renderer, std::string *filelist, Lang *lang, Input *input, bool demo, options_t *options); + Game(SDL_Renderer *renderer, std::string *filelist, Lang *lang, Input *input); // Destructor ~Game(); diff --git a/source/ifdefs.h b/source/ifdefs.h index d5a071e..3ed8075 100644 --- a/source/ifdefs.h +++ b/source/ifdefs.h @@ -1,15 +1,4 @@ -#ifdef _WIN64 -#include "C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\SDL2\SDL.h" -#endif - -#ifdef _WIN32 -#include "C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\SDL2\SDL.h" -#endif - -#ifdef __APPLE__ -//#include "/Library/Frameworks/SDL2.framework/Versions/A/Headers/SDL.h" #include -#endif #ifdef __linux__ #ifdef __MIPSEL__ @@ -17,6 +6,4 @@ #else #include #endif -#endif - -#define UNUSED \ No newline at end of file +#endif \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index da9b9e4..06e4fba 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,37 +1,8 @@ /* -Código fuente creado por JailDesigner (2020) -Empezado en Castalla el 15/07/2020. -Descripción del enfoque utilizado para crear el juego. +Código fuente creado por JailDesigner +Empezado en Castalla el 06/09/2021. -El programa contine una serie de clases/objetos básicos: la clase sprite -permite dibujar partes de un fichero png en pantalla. La clase AnimatedSprite -contiene funcionalidad adicional para crear animaciones. La clase text permite -dibujar letras de un png en pantalla a partir de una cadena de texto. La clase -menu permite crear una estructura con diferentes elementos, escribirlos en -pantalla y seleccionar uno de ellos. - -A continuación tenemos las clases enfocadas a la lógica del juego, la clase player -contiene la información del jugador, la clase balloon la de los enemigos y la -clase bullet para las balas que dispara el jugador. La clase background es -muy simple y sirve para pintar el fondo de la pantalla. Por ultimo, la clase -mDirector es la que realiza toda la lógica y se encarga de hacer interactuar -al resto de objetos entre si. - -El objeto mDirector tiene tres estados: titulo, juego y pausa. Segun su estado -el bucle que recorre es distinto. En el bucle juego, el objeto mDirector -tiene un objeto jugador, un vector con los objetos globo y un vector con los -objetos bala. Se encarga de comprobar las entradas de teclado o gamepad para -cerrar la aplicacion, saltar al estado de pausa y para mover al jugador. Recorre -el vector de globos y de balas y si tienen algun tipo asignado las gestiona. -Comprueba las colisiones entre los globos y el jugador y entre las balas y los -globos. Tiene ademas un nivel de amenaza que calcula en funcion del numero de globos -en pantalla y que se va incrementando conforme aumenta la puntuación del jugador. - -Los objetos globo tienen varios contadores para alternar de un estado a otro. - -En los vectores que contienen objetos, se considera activos los objetos que tienen -un tipo asociado diferente a NO_KIND */ #include "director.h"