From e9ff516b1db2db6bd37a2827065d87704041b222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Valor=20Mart=C3=ADnez?= Date: Sat, 17 Apr 2021 23:46:14 +0200 Subject: [PATCH] working on class sections --- media/.DS_Store | Bin 10244 -> 10244 bytes source/animatedsprite.cpp | 4 +- source/balloon.cpp | 54 +- source/const.h | 31 +- source/gamedirector.cpp | 5337 ------------------------------------- source/gamedirector.h | 679 ----- source/item.cpp | 14 +- source/main.cpp | 40 +- source/menu.cpp | 95 +- source/menu.h | 236 +- source/player.cpp | 2 +- source/player.h | 1 + source/text.cpp | 126 +- source/text.h | 23 +- source/text2.cpp | 8 +- source/text2.h | 4 +- source/utils.cpp | 12 + source/utils.h | 38 +- 18 files changed, 329 insertions(+), 6375 deletions(-) delete mode 100644 source/gamedirector.cpp delete mode 100644 source/gamedirector.h diff --git a/media/.DS_Store b/media/.DS_Store index 3e05191957fe1d5e5254b36483f427576cbe9b22..8b4ea8353e83c530e5a18f7e590e166e8cf03bf0 100644 GIT binary patch delta 800 zcma)(T}V?=0LRb&Ox?X6q%(0fb?&YV$=u{R=Tr(?mQ?dI{H#cGy6DoF(}`hXS&bh0 z5aNPm6!l^hXjv;ss)rtmvM34>=_M%$f)Fa`gD|>mdkdoT^5_4Db2$8d;kt0$_r!X=tcXvLKWMabmM!r_ zjjS+hO3%p5Vd{iY+QPU_6Cy^ZBFWA;gjgwM>ljba)Wm8Tb2Cmv1FB+ulT;ybLEujW zA^R@}|1|KFye9LSflr!&-_U8?SHOxK$Qti5xUmtNQGpuNVLR%h+}p4RUUa~ZfX2QX zJs7|s4q*sKZ~~`r8p9g?(N#FF@xO>GxQc5S#{{Nu7t^?h`*?uIc!~MQk|h~uhO#1h H>yrKtY8Am1 delta 776 zcmb8sOH30{6b9h)UxCiR07C^j+Cm{{ObkeQR*cG9L@OXz1&q*^HZTdawNoL25g!;A zN?c503hELy!3U-)#>d7)LliYp5`u97D_tlHHBlo*D@EhhyE*rqdpGC%2kHju#zsUg zH?JTwEytX%4(m#T^J2aR6KcHf2(RnwGZ$v2<(k#2QYr%Kq-4a9`d%`nRy(|%vf?+H zUV|-*h>X&3d~}QuD>XJX?-ll`NJ&z?i3jzKa+}B9AosdN@YmvWhV<2Iv-68Kmsiy` z1m_a8ux_p1rj;yG&7N*qksX~bYme;ocQo0RHkaEeyW2VOCD*KU*nO_r9=FRkwe-K9 z<66b|#ks|<_$!^V-}Cozx0<7uSRSd{^@e^vqr^nv!%+(5QUzJaMn3AJK?=|)-K5(z zPLJsYP178`rH}N9KGPRkKqR7|0S_(oFdzj+WTF6tFryq6>_83bU_}dBVS@wh@M1rF z@S_*UF@O^|i8JUAUQZ4{p-UtwxPCTFM8?R9i|97L+kkjx9Q#;OpU zVEL1a@!wo#;^M^w?efH=WL?_tc+4A1RejQfq8MYA!0}Vkik15H!UjQ%;6)|eZW4+G zk@y5y!hM;s!YFc_IKgolCI9FCgkI51$o)ge{U;(q+7i;S200<+Vw9o`mDqw>>_k0w zEo$3fM;n~zf+r;IgMvdijD8%&F`U9_4B{*T$QZ&ooW}?*;W9>X1-CGcJGhH`xQ|D8 R9@2jkoK1~JP?PpU^9$%^yGj56 diff --git a/source/animatedsprite.cpp b/source/animatedsprite.cpp index 44847c6..6b96708 100644 --- a/source/animatedsprite.cpp +++ b/source/animatedsprite.cpp @@ -19,13 +19,13 @@ void AnimatedSprite::init(LTexture *texture, SDL_Renderer *renderer) { mRenderer = renderer; mTexture = texture; - for (Uint8 i = 0; i < 20; i++) + for (int i = 0; i < 20; i++) { mAnimation[i].numFrames = 0; mAnimation[i].speed = 0; mAnimation[i].loop = true; mAnimation[i].completed = false; - for (Uint8 j = 0; i < 20; i++) + for (int j = 0; i < 20; i++) { mAnimation[i].frames[j].x = 0; mAnimation[i].frames[j].y = 0; diff --git a/source/balloon.cpp b/source/balloon.cpp index 9b79f67..ddabb7d 100644 --- a/source/balloon.cpp +++ b/source/balloon.cpp @@ -53,13 +53,13 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16 mMenace = 1; // Establece los frames de cada animación - for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++) + for (int i = 0; i < NUM_FRAMES_BALLON; i++) mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 50 + OFFSET_ORANGE_BALLOONS, 21 + (37 * i), getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++) mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 50 + OFFSET_BLUE_BALLOONS, 21 + (37 * i), getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++) mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 50 + OFFSET_EXPLOSIONS, 21 + (37 * i), getWidth(), getHeight()); break; @@ -87,13 +87,13 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16 mMenace = 2; // Establece los frames de cada animación - for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++) + for (int i = 0; i < NUM_FRAMES_BALLON; i++) mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 37 + OFFSET_ORANGE_BALLOONS, 21 + (37 * i), getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++) mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 37 + OFFSET_BLUE_BALLOONS, 21 + (37 * i), getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++) mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 37 + OFFSET_EXPLOSIONS, 21 + (37 * i), getWidth(), getHeight()); break; @@ -121,13 +121,13 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16 mMenace = 4; // Establece los frames de cada animación - for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++) + for (int i = 0; i < NUM_FRAMES_BALLON; i++) mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 37 + OFFSET_ORANGE_BALLOONS, 37 * i, getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++) mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 37 + OFFSET_BLUE_BALLOONS, 37 * i, getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++) mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 37 + OFFSET_EXPLOSIONS, 37 * i, getWidth(), getHeight()); break; @@ -155,13 +155,13 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16 mMenace = 8; // Establece los frames de cada animación - for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++) + for (int i = 0; i < NUM_FRAMES_BALLON; i++) mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, OFFSET_ORANGE_BALLOONS, 37 * i, getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++) mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, OFFSET_BLUE_BALLOONS, 37 * i, getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++) mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, OFFSET_EXPLOSIONS, 37 * i, getWidth(), getHeight()); break; @@ -189,13 +189,13 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16 mMenace = 1; // Establece los frames de cada animación - for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++) + for (int i = 0; i < NUM_FRAMES_BALLON; i++) mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 50 + OFFSET_GREEN_BALLOONS, 21 + (37 * i), getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++) mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 50 + OFFSET_PURPLE_BALLOONS, 21 + (37 * i), getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++) mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 50 + OFFSET_EXPLOSIONS, 21 + (37 * i), getWidth(), getHeight()); break; @@ -223,13 +223,13 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16 mMenace = 2; // Establece los frames de cada animación - for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++) + for (int i = 0; i < NUM_FRAMES_BALLON; i++) mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 37 + OFFSET_GREEN_BALLOONS, 21 + (37 * i), getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++) mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 37 + OFFSET_PURPLE_BALLOONS, 21 + (37 * i), getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++) mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 37 + OFFSET_EXPLOSIONS, 21 + (37 * i), getWidth(), getHeight()); break; @@ -257,13 +257,13 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16 mMenace = 4; // Establece los frames de cada animación - for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++) + for (int i = 0; i < NUM_FRAMES_BALLON; i++) mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 37 + OFFSET_GREEN_BALLOONS, 37 * i, getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++) mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 37 + OFFSET_PURPLE_BALLOONS, 37 * i, getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++) mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 37 + OFFSET_EXPLOSIONS, 37 * i, getWidth(), getHeight()); break; @@ -291,13 +291,13 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16 mMenace = 8; // Establece los frames de cada animación - for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++) + for (int i = 0; i < NUM_FRAMES_BALLON; i++) mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, OFFSET_GREEN_BALLOONS, 37 * i, getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++) mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, OFFSET_PURPLE_BALLOONS, 37 * i, getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++) mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, OFFSET_EXPLOSIONS, 37 * i, getWidth(), getHeight()); break; @@ -325,13 +325,13 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16 mMenace = 0; // Establece los frames de cada animación - for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++) + for (int i = 0; i < NUM_FRAMES_BALLON; i++) mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, OFFSET_POWER_BALL, 37 * i, getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++) mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, OFFSET_POWER_BALL, 37 * i, getWidth(), getHeight()); - for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++) + for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++) mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, OFFSET_EXPLOSIONS, 37 * i, getWidth(), getHeight()); // Añade rotación al sprite diff --git a/source/const.h b/source/const.h index 721c43b..06b608e 100644 --- a/source/const.h +++ b/source/const.h @@ -1,5 +1,6 @@ #pragma once #include "ifdefs.h" +#include "utils.h" #include #ifndef CONST_H @@ -140,6 +141,8 @@ const int SCREEN_THIRD_QUARTER_Y = (SCREEN_HEIGHT / 4) * 3; #define PROG_SECTION_INTRO 1 #define PROG_SECTION_TITLE 2 #define PROG_SECTION_GAME 3 +#define PROG_SECTION_INSTRUCTIONS 4 +#define PROG_SECTION_QUIT 5 // Secciones del juego #define GAME_SECTION_PLAY 0 @@ -150,11 +153,10 @@ const int SCREEN_THIRD_QUARTER_Y = (SCREEN_HEIGHT / 4) * 3; #define TITLE_SECTION_1 0 #define TITLE_SECTION_2 1 #define TITLE_SECTION_3 2 -#define TITLE_SECTION_INSTRUCTIONS 3 -// Modos -#define MODE_AUTO 0 -#define MODE_MANUAL 1 +// Secciones de las instrucciones +#define INSTRUCTIONS_MODE_MANUAL 0 +#define INSTRUCTIONS_MODE_AUTO 1 // Estados de cada elemento que pertenece a un evento #define EVENT_WAITING 1 @@ -270,9 +272,8 @@ const int MULTIPLIER_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2; #define ITEM_POINTS_2_GAVINA 2 #define ITEM_POINTS_3_PACMAR 3 #define ITEM_CLOCK 4 -#define ITEM_TNT 5 -#define ITEM_COFFEE 6 -#define ITEM_POWER_BALL 7 +#define ITEM_COFFEE 5 +#define ITEM_POWER_BALL 6 // Cantidad de objetos simultaneos #define MAX_ITEMS 5 @@ -284,14 +285,8 @@ const int MULTIPLIER_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2; // Estados de entrada #define NO_INPUT 0 -#define INPUT_UP 1 -#define INPUT_DOWN 2 -#define INPUT_LEFT 3 -#define INPUT_RIGHT 4 -#define INPUT_ACCEPT 5 -#define INPUT_CANCEL 6 -#define INPUT_FIRE_UP 7 -#define INPUT_FIRE_LEFT 8 +#define INPUT_FIRE_LEFT 7 +#define INPUT_FIRE_UP 8 #define INPUT_FIRE_RIGHT 9 #define INPUT_PAUSE 10 @@ -319,4 +314,10 @@ const int MULTIPLIER_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2; #define DEATH_COUNTER 350 #define SHAKE_COUNTER 10 +// Colores +const color_t bgColor = {0x27, 0x27, 0x36}; +const color_t noColor = {0xFF, 0xFF, 0xFF}; +const color_t shdwTxtColor = {0x43, 0x43, 0x4F}; + + #endif \ No newline at end of file diff --git a/source/gamedirector.cpp b/source/gamedirector.cpp deleted file mode 100644 index bfea4c4..0000000 --- a/source/gamedirector.cpp +++ /dev/null @@ -1,5337 +0,0 @@ -#include "const.h" -#include "utils.h" -#include "gamedirector.h" -#include -#ifdef __MIPSEL__ -#include -#include -#endif - -const Uint8 *keystates; -float mSin[360]; // Vector con los valores del seno para 360 grados - -// Constructor -GameDirector::GameDirector(std::string path) -{ - // Crea los objetos - mEventHandler = new SDL_Event(); - - mTexture[TEXTURE_MENU].texture = new LTexture(); - mTexture[TEXTURE_FONT_WHITE].texture = new LTexture(); - mTexture[TEXTURE_FONT_WHITE_X2].texture = new LTexture(); - mTexture[TEXTURE_FONT_BLACK].texture = new LTexture(); - mTexture[TEXTURE_FONT_BLACK_X2].texture = new LTexture(); - mTexture[TEXTURE_FONT_NOKIA].texture = new LTexture(); - - mMenu.gameOver = new Menu(); - mMenu.options = new Menu(); - mMenu.pause = new Menu(); - mMenu.title = new Menu(); - - mText.black = new Text(); - mText.blackX2 = new Text(); - mText.nokia = new Text(); - mText.white = new Text(); - mText.whiteX2 = new Text(); - - // Inicializa variables - setExecutablePath(path); - setFileList(); - checkFileList(); - - // Inicializa SDL - initSDL(); - - // Inicializa JailAudio - initJailAudio(); - -#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 - - // Carga recursos - loadMediaProg(); - loadScoreFile(); - loadConfigFile(); - loadDemoFile(); - - // Inicializa el resto de variables - initProg(); -} - -GameDirector::~GameDirector() -{ - quitProg(); - - // Destuye el manejador de eventos - delete mEventHandler; - - // Libera el mando - if (mGameControllerFound) - { - SDL_JoystickClose(mGameController); - mGameController = NULL; - } - - // Destruye los objetos - delete mTexture[TEXTURE_MENU].texture; - delete mTexture[TEXTURE_FONT_WHITE].texture; - delete mTexture[TEXTURE_FONT_WHITE_X2].texture; - delete mTexture[TEXTURE_FONT_BLACK].texture; - delete mTexture[TEXTURE_FONT_BLACK_X2].texture; - delete mTexture[TEXTURE_FONT_NOKIA].texture; - - delete mMenu.gameOver; - delete mMenu.options; - delete mMenu.pause; - delete mMenu.title; - mMenu.active = nullptr; - - delete mText.black; - delete mText.blackX2; - delete mText.nokia; - delete mText.white; - delete mText.whiteX2; - - SDL_DestroyTexture(mBackbuffer); - SDL_DestroyRenderer(mRenderer); - SDL_DestroyWindow(mWindow); - mBackbuffer = nullptr; - mRenderer = nullptr; - mWindow = nullptr; - - SDL_Quit(); -} - -// Inicia las variables necesarias para arrancar el programa -void GameDirector::initProg() -{ - // Debug mode - mDebug.enabled = false; - mDebug.enemySet = 0; - mDebug.gradR = mDebug.gradG = mDebug.gradB = 0; - - // Variables - mProg.quit = false; - mProg.ticks = 0; - mProg.ticksSpeed = 15; - mProg.section = PROG_SECTION_LOGO; - initSin(); - initPaths(); - initEnemyFormations(); - initEnemyPools(); - - mOptions.displayCoffeeDrops = false; - - mDemo.enabled = false; - mDemo.recording = false; - mDemo.counter = 0; - - mMenu.keyPressed = false; - mMenu.active = mMenu.title; - - // Teclado - mProg.keyboard.up = SDL_SCANCODE_UP; - mProg.keyboard.down = SDL_SCANCODE_DOWN; - mProg.keyboard.left = SDL_SCANCODE_LEFT; - mProg.keyboard.right = SDL_SCANCODE_RIGHT; - mProg.keyboard.accept = SDL_SCANCODE_RETURN; - mProg.keyboard.cancel = SDL_SCANCODE_ESCAPE; -#ifdef __MIPSEL__ - mProg.keyboard.fire = SDL_SCANCODE_SPACE; - mProg.keyboard.fireLeft = SDL_SCANCODE_LSHIFT; - mProg.keyboard.fireRight = SDL_SCANCODE_LCTRL; -#else - mProg.keyboard.fire = SDL_SCANCODE_W; - mProg.keyboard.fireLeft = SDL_SCANCODE_Q; - mProg.keyboard.fireRight = SDL_SCANCODE_E; -#endif - mProg.keyboard.pause = SDL_SCANCODE_ESCAPE; - mProg.keyboard.escape = SDL_SCANCODE_ESCAPE; - - // Buffer de teclado - mProg.keyboardBuffer.up = 0; - mProg.keyboardBuffer.down = 0; - mProg.keyboardBuffer.left = 0; - mProg.keyboardBuffer.right = 0; - mProg.keyboardBuffer.accept = 0; - mProg.keyboardBuffer.cancel = 0; - mProg.keyboardBuffer.fire = 0; - mProg.keyboardBuffer.fireLeft = 0; - mProg.keyboardBuffer.fireRight = 0; - mProg.keyboardBuffer.pause = 0; - mProg.keyboardBuffer.escape = 0; - - // Inicializa los objetos de texto - mText.white->init(mTexture[TEXTURE_FONT_WHITE].texture, mRenderer, TEXT_FIXED, BLOCK); - mText.whiteX2->init(mTexture[TEXTURE_FONT_WHITE_X2].texture, mRenderer, TEXT_FIXED, BLOCK * 2); - mText.black->init(mTexture[TEXTURE_FONT_BLACK].texture, mRenderer, TEXT_FIXED, BLOCK); - mText.blackX2->init(mTexture[TEXTURE_FONT_BLACK_X2].texture, mRenderer, TEXT_FIXED, BLOCK * 2); - mText.nokia->init(mTexture[TEXTURE_FONT_NOKIA].texture, mRenderer, TEXT_VARIABLE, 10); - - // Inicializa el objeto con el menu del titulo - mMenu.title->init("TITLE", 0, 15 * BLOCK, MENU_BACKGROUND_SOLID, mTexture[TEXTURE_MENU].texture, mRenderer, mText.white); - mMenu.title->addItem("PLAY"); - mMenu.title->addItem("OPTIONS"); - mMenu.title->addItem("HOW TO PLAY", 0, 5); - mMenu.title->addItem("QUIT"); - mMenu.title->setDefaultActionWhenCancel(3); - mMenu.title->setBackgroundColor(0x30, 0x30, 0x40, 192); - mMenu.title->setSelectorColor(0xe5, 0x1c, 0x23, 255); - mMenu.title->setSelectorTextColor(0xFF, 0xF1, 0x76); - mMenu.title->centerMenu(SCREEN_CENTER_X); - mMenu.title->centerMenuElements(); - - // Inicializa el objeto con el menu de pausa - mMenu.pause->init("PAUSE", 0, 12 * BLOCK, MENU_BACKGROUND_SOLID, mTexture[TEXTURE_MENU].texture, mRenderer, mText.white); - mMenu.pause->addItem("CONTINUE"); - mMenu.pause->addItem("EXIT TO TITLE"); - mMenu.pause->setDefaultActionWhenCancel(0); - mMenu.pause->setBackgroundColor(0x29, 0x39, 0x41, 240); - mMenu.pause->setSelectorColor(0xFF, 0x7A, 0x00, 255); - mMenu.pause->setSelectorTextColor(0xFF, 0xFF, 0xFF); - mMenu.pause->centerMenu(SCREEN_CENTER_X); - mMenu.pause->centerMenuElements(); - - // Inicializa el objeto con el menu de la pantalla de game over - mMenu.gameOver->init("GAME OVER", 0, PLAY_AREA_CENTER_Y + BLOCK * 4, MENU_BACKGROUND_TRANSPARENT, mTexture[TEXTURE_MENU].texture, mRenderer, mText.white); - mMenu.gameOver->addItem("YES"); - mMenu.gameOver->addItem("NO"); - mMenu.gameOver->setDefaultActionWhenCancel(1); - mMenu.gameOver->setBackgroundColor(0, 0, 0, 255); - mMenu.gameOver->setSelectorColor(0x54, 0x6e, 0x7a, 255); - mMenu.gameOver->setSelectorColor(0x54, 0x6e, 0x7a, 0); - mMenu.gameOver->setSelectorTextColor(0xFF, 0xFF, 0xFF); - mMenu.gameOver->setSelectorTextColor(0xFF, 0xF1, 0x76); - mMenu.gameOver->setSelectorTextColor(0xFF, 0x7A, 0x00); - mMenu.gameOver->centerMenu(SCREEN_CENTER_X); - mMenu.gameOver->centerMenuElements(); - - // Inicializa el objeto con el menu de las opciones - mMenu.options->init("OPTIONS", 0, 15 * BLOCK, MENU_BACKGROUND_SOLID, mTexture[TEXTURE_MENU].texture, mRenderer, mText.white); - mMenu.options->addItem("FULLSCREEN"); - mMenu.options->addItem("WINDOWS SIZE", 0, 5); - mMenu.options->addItem("[OK]"); - mMenu.options->addItem("[CANCEL]"); - mMenu.options->setDefaultActionWhenCancel(3); - mMenu.options->setBackgroundColor(0x30, 0x30, 0x40, 192); - mMenu.options->setSelectorColor(0xe5, 0x1c, 0x23, 255); - mMenu.options->setSelectorTextColor(0xFF, 0xF1, 0x76); - mMenu.options->centerMenu(SCREEN_CENTER_X); - mMenu.options->centerMenuElements(); - - // Actualiza los elementos del menu de opciones con los valores correspondientes - updateOptionsMenu(); -} - -// Carga los recursos necesarios para el programa -bool GameDirector::loadMediaProg() -{ - bool success = true; - - // Texturas - success &= loadTextureFromFile(mTexture[TEXTURE_MENU].texture, mTexture[TEXTURE_MENU].file, mRenderer); - success &= loadTextureFromFile(mTexture[TEXTURE_FONT_WHITE].texture, mTexture[TEXTURE_FONT_WHITE].file, mRenderer); - success &= loadTextureFromFile(mTexture[TEXTURE_FONT_WHITE_X2].texture, mTexture[TEXTURE_FONT_WHITE_X2].file, mRenderer); - success &= loadTextureFromFile(mTexture[TEXTURE_FONT_BLACK].texture, mTexture[TEXTURE_FONT_BLACK].file, mRenderer); - success &= loadTextureFromFile(mTexture[TEXTURE_FONT_BLACK_X2].texture, mTexture[TEXTURE_FONT_BLACK_X2].file, mRenderer); - success &= loadTextureFromFile(mTexture[TEXTURE_FONT_NOKIA].texture, mTexture[TEXTURE_FONT_NOKIA].file, mRenderer); - - // Sonidos - mSound[SOUND_MENU_SELECT].sound = JA_LoadSound(mSound[SOUND_MENU_SELECT].file.c_str()); - mSound[SOUND_MENU_CANCEL].sound = JA_LoadSound(mSound[SOUND_MENU_CANCEL].file.c_str()); - mSound[SOUND_MENU_MOVE].sound = JA_LoadSound(mSound[SOUND_MENU_MOVE].file.c_str()); - - // Musicas - mMusic[MUSIC_TITLE].music = JA_LoadMusic(mMusic[MUSIC_TITLE].file.c_str()); - - return success; -} - -// Libera las variables del programa -void GameDirector::quitProg() -{ - // Guarda los ficheros - saveScoreFile(); - saveConfigFile(); - saveDemoFile(); - - // Texturas - mTexture[TEXTURE_MENU].texture->unload(); - mTexture[TEXTURE_FONT_WHITE].texture->unload(); - mTexture[TEXTURE_FONT_WHITE_X2].texture->unload(); - mTexture[TEXTURE_FONT_BLACK].texture->unload(); - mTexture[TEXTURE_FONT_BLACK_X2].texture->unload(); - mTexture[TEXTURE_FONT_NOKIA].texture->unload(); - - // Sonidos - JA_DeleteSound(mSound[SOUND_MENU_SELECT].sound); - JA_DeleteSound(mSound[SOUND_MENU_CANCEL].sound); - JA_DeleteSound(mSound[SOUND_MENU_MOVE].sound); - - // Musicas - JA_DeleteMusic(mMusic[MUSIC_TITLE].music); -} - -// Inicializa JailAudio -void GameDirector::initJailAudio() -{ - JA_Init(48000, AUDIO_S16, 2); -} - -// Arranca SDL y crea la ventana -bool GameDirector::initSDL() -{ - // Indicador de inicialización - bool success = true; - - // Inicializa SDL - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_HAPTIC) < 0) - { - printf("SDL could not initialize!\nSDL Error: %s\n", SDL_GetError()); - success = false; - } - else - { - // Establece el filtro de la textura a nearest - if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0")) - { - printf("Warning: Nearest texture filtering not enabled!\n"); - } - - // Comprueba si hay algun mando conectado - if (SDL_NumJoysticks() < 1) - { - printf("Warning: No joysticks connected!\n"); - mGameControllerFound = false; - } - else - { - // Carga el mando - mGameController = SDL_JoystickOpen(0); - mGameControllerFound = true; - - if (mGameController == NULL) - { - printf("Warning: Unable to open game controller!\nSDL Error: %s\n", SDL_GetError()); - mGameControllerFound = false; - } - else - { - printf("%i joysticks were found.\n", SDL_NumJoysticks()); - std::cout << SDL_JoystickNumButtons(mGameController) << " buttons\n"; - - // Obtiene el dispositivo de control háptico - mControllerHaptic = SDL_HapticOpenFromJoystick(mGameController); - if (mControllerHaptic == NULL) - { - printf("Warning: Controller does not support haptics!\nSDL Error: %s\n", SDL_GetError()); - } - else - { - printf("Haptics detected\n"); - - // Inicializa la vibración - if (SDL_HapticRumbleInit(mControllerHaptic) < 0) - { - printf("Warning: Unable to initialize rumble!\nSDL Error: %s\n", SDL_GetError()); - } - } - } - } - - // Crea la ventana - mWindow = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, VIEW_WIDTH, VIEW_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI); - if (mWindow == NULL) - { - printf("Window could not be created!\nSDL Error: %s\n", SDL_GetError()); - success = false; - } - else - { - // Crea un renderizador para la ventana con vsync - mRenderer = SDL_CreateRenderer(mWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); - if (mRenderer == NULL) - { - printf("Renderer could not be created!\nSDL Error: %s\n", SDL_GetError()); - success = false; - } - else - { - // Inicializa el color de renderizado - SDL_SetRenderDrawColor(mRenderer, 0x00, 0x00, 0x00, 0xFF); - - // Establece el tamaño del buffer de renderizado - SDL_RenderSetLogicalSize(mRenderer, SCREEN_WIDTH, SCREEN_HEIGHT); - - // Establece el modo de mezcla - SDL_SetRenderDrawBlendMode(mRenderer, SDL_BLENDMODE_BLEND); - } - - // Crea un backbuffer para el renderizador - mBackbuffer = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH, SCREEN_HEIGHT); - if (mBackbuffer == NULL) - { - printf("Backbuffer could not be created!\nSDL Error: %s\n", SDL_GetError()); - success = false; - } - } - } - - printf("\n"); - return success; -} - -// Inicializa el vector con los valores del seno -void GameDirector::initSin() -{ - // Vector con los valores del seno para 360 grados - for (int i = 0; i < 360; i++) - { - mSin[i] = sin((float)i * 3.14f / 180.0f); - } -} - -// Inicializa las variables que contienen puntos de ruta para mover objetos -void GameDirector::initPaths() -{ - // Letrero de STAGE # - int firstPart = STAGE_COUNTER / 4; // 50 - int secondPart = firstPart * 3; // 150 - int centerPoint = PLAY_AREA_CENTER_Y - (BLOCK * 2); - int distance = (PLAY_AREA_BOTTOM) - (PLAY_AREA_CENTER_Y - 16); - - for (int i = 0; i < STAGE_COUNTER; i++) - { - if (i < firstPart) - mGame.stageBitmapPath[i] = (mSin[(int)((i * 1.8f) + 90)] * (distance) + centerPoint); - else if (i < secondPart) - mGame.stageBitmapPath[i] = (int)centerPoint; - else - mGame.stageBitmapPath[i] = (mSin[(int)(((i - 149) * 1.8f) + 90)] * (centerPoint + 17) - 17); - } - - float start1 = PLAY_AREA_LEFT - 130; - float finish1 = PLAY_AREA_CENTER_X - 55; - - float start2 = finish1; - float finish2 = PLAY_AREA_RIGHT + 20; - - float distance1 = finish1 - start1; - float distance2 = finish2 - start2; - - // Letrero de GetReady - for (int i = 0; i < STAGE_COUNTER; i++) - { - if (i < firstPart) - { - mGame.getReadyBitmapPath[i] = mSin[(int)(i * 1.8f)]; - mGame.getReadyBitmapPath[i] *= distance1; - mGame.getReadyBitmapPath[i] -= 130; - } - else if (i < secondPart) - mGame.getReadyBitmapPath[i] = (int)finish1; - else - { - mGame.getReadyBitmapPath[i] = mSin[(int)((i - 150) * 1.8f)]; - mGame.getReadyBitmapPath[i] *= distance2; - mGame.getReadyBitmapPath[i] += finish1; - } - } -} - -// Inicializa las variables necesarias para la sección 'Logo' -void GameDirector::initLogo() -{ - // Reserva memoria para los punteros - mTexture[TEXTURE_LOGO].texture = new LTexture(); - mLogo.sprite = new Sprite(); - - // Carga los recursos - loadMediaLogo(); - - // Inicializa variables - mLogo.counter = 0; - mLogo.sprite->init(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, mTexture[TEXTURE_LOGO].texture, mRenderer); -} - -// Carga los recursos necesarios para la sección 'Logo' -bool GameDirector::loadMediaLogo() -{ - bool success = true; - - success &= loadTextureFromFile(mTexture[TEXTURE_LOGO].texture, mTexture[TEXTURE_LOGO].file, mRenderer); - - return success; -} - -// Libera las variables necesarias para la sección 'Logo' -void GameDirector::quitLogo() -{ - // Texturas - mTexture[TEXTURE_LOGO].texture->unload(); - - // Libera la memoria de los punteros - delete mTexture[TEXTURE_LOGO].texture; - delete mLogo.sprite; - mTexture[TEXTURE_LOGO].texture = nullptr; - mLogo.sprite = nullptr; -} - -// Inicializa las variables necesarias para la sección 'Intro' -void GameDirector::initIntro() -{ - // Reserva memoria para los punteros - mTexture[TEXTURE_INTRO].texture = new LTexture(); - - for (Uint8 i = 0; i < INTRO_TOTAL_BITMAPS; i++) - mIntro.bitmap[i] = new SmartSprite(); - - for (Uint8 i = 0; i < INTRO_TOTAL_TEXTS; i++) - mIntro.text[i] = new Text2(); - - // Carga los recursos - loadMediaIntro(); - - // Inicializa el vector de eventos de la intro - for (Uint8 i = 0; i < INTRO_TOTAL_EVENTS; i++) - mIntro.events[i] = EVENT_WAITING; - - // Inicializa los bitmaps de la intro - for (Uint8 i = 0; i < INTRO_TOTAL_BITMAPS; i++) - { - mIntro.bitmap[i]->init(mTexture[TEXTURE_INTRO].texture, mRenderer); - mIntro.bitmap[i]->setId(i); - mIntro.bitmap[i]->setIntroEvents(&mIntro.events[0]); - mIntro.bitmap[i]->setWidth(128); - mIntro.bitmap[i]->setHeight(96); - mIntro.bitmap[i]->setEnabled(false); - mIntro.bitmap[i]->setEnabledTimer(20); - mIntro.bitmap[i]->setDestX(SCREEN_CENTER_X - 64); - mIntro.bitmap[i]->setDestY(SCREEN_FIRST_QUARTER_Y - 24); - } - - mIntro.bitmap[0]->setPosX(-128); - mIntro.bitmap[0]->setPosY(SCREEN_FIRST_QUARTER_Y - 24); - mIntro.bitmap[0]->setVelX(0.0f); - mIntro.bitmap[0]->setVelY(0.0f); - mIntro.bitmap[0]->setAccelX(0.6f); - mIntro.bitmap[0]->setAccelY(0.0f); - mIntro.bitmap[0]->setSpriteClip(0, 0, 128, 96); - - mIntro.bitmap[1]->setPosX(SCREEN_WIDTH); - mIntro.bitmap[1]->setPosY(SCREEN_FIRST_QUARTER_Y - 24); - mIntro.bitmap[1]->setVelX(-1.0f); - mIntro.bitmap[1]->setVelY(0.0f); - mIntro.bitmap[1]->setAccelX(-0.3f); - mIntro.bitmap[1]->setAccelY(0.0f); - mIntro.bitmap[1]->setSpriteClip(128, 0, 128, 96); - - mIntro.bitmap[2]->setPosX(SCREEN_CENTER_X - 64); - mIntro.bitmap[2]->setPosY(-96); - mIntro.bitmap[2]->setVelX(0.0f); - mIntro.bitmap[2]->setVelY(3.0f); - mIntro.bitmap[2]->setAccelX(0.1f); - mIntro.bitmap[2]->setAccelY(0.3f); - mIntro.bitmap[2]->setSpriteClip(0, 96, 128, 96); - - mIntro.bitmap[2]->setEnabledTimer(250); - - mIntro.bitmap[3]->setPosX(SCREEN_CENTER_X - 64); - mIntro.bitmap[3]->setPosY(SCREEN_HEIGHT); - mIntro.bitmap[3]->setVelX(0.0f); - mIntro.bitmap[3]->setVelY(-0.7f); - mIntro.bitmap[3]->setAccelX(0.0f); - mIntro.bitmap[3]->setAccelY(0.0f); - mIntro.bitmap[3]->setSpriteClip(128, 96, 128, 96); - - mIntro.bitmap[4]->setPosX(SCREEN_CENTER_X - 64); - mIntro.bitmap[4]->setPosY(-96); - mIntro.bitmap[4]->setVelX(0.0f); - mIntro.bitmap[4]->setVelY(3.0f); - mIntro.bitmap[4]->setAccelX(0.1f); - mIntro.bitmap[4]->setAccelY(0.3f); - mIntro.bitmap[4]->setSpriteClip(0, 192, 128, 96); - - mIntro.bitmap[5]->setPosX(SCREEN_WIDTH); - mIntro.bitmap[5]->setPosY(SCREEN_FIRST_QUARTER_Y - 24); - mIntro.bitmap[5]->setVelX(-0.7f); - mIntro.bitmap[5]->setVelY(0.0f); - mIntro.bitmap[5]->setAccelX(0.0f); - mIntro.bitmap[5]->setAccelY(0.0f); - mIntro.bitmap[5]->setSpriteClip(128, 192, 128, 96); - - // Inicializa los textos de la intro - for (Uint8 i = 0; i < INTRO_TOTAL_TEXTS; i++) - { - mIntro.text[i]->init(mTexture[TEXTURE_FONT_NOKIA].texture, mRenderer, TEXT_VARIABLE, 10); - mIntro.text[i]->setId(6 + i); - mIntro.text[i]->setIntroEvents(&mIntro.events[0]); - mIntro.text[i]->setPosX(BLOCK * 0); - mIntro.text[i]->setPosY(SCREEN_HEIGHT - (BLOCK * 6)); - mIntro.text[i]->setKerning(-1); - mIntro.text[i]->setEnabled(false); - mIntro.text[i]->setEnabledTimer(180); - } - - mIntro.text[0]->setCaption("Un dia qualsevol de l'any 2000"); - mIntro.text[0]->setWrittingSpeed(10); - - mIntro.text[1]->setCaption("Tot esta tranquil a la UPV"); - mIntro.text[1]->setWrittingSpeed(10); - - mIntro.text[2]->setCaption("Fins que un desaprensiu..."); - mIntro.text[2]->setWrittingSpeed(15); - - mIntro.text[3]->setCaption("HEY! ME ANE A FERME UN CORTAET..."); - mIntro.text[3]->setWrittingSpeed(10); - - mIntro.text[4]->setCaption("UAAAAAAAAAAAAA!!!"); - mIntro.text[4]->setWrittingSpeed(1); - - mIntro.text[5]->setCaption("Espera un moment..."); - mIntro.text[5]->setWrittingSpeed(20); - - mIntro.text[6]->setCaption("Si resulta que no tinc solt!"); - mIntro.text[6]->setWrittingSpeed(2); - - mIntro.text[7]->setCaption("MERDA DE MAQUINA!"); - mIntro.text[7]->setWrittingSpeed(3); - - mIntro.text[8]->setCaption("Blop... blop... blop..."); - mIntro.text[8]->setWrittingSpeed(20); - - for (Uint8 i = 0; i < INTRO_TOTAL_TEXTS; i++) - { - mIntro.text[i]->center(SCREEN_CENTER_X); - } -} - -// Carga los recursos necesarios para la sección 'Intro' -bool GameDirector::loadMediaIntro() -{ - bool success = true; - - // Texturas - success &= loadTextureFromFile(mTexture[TEXTURE_INTRO].texture, mTexture[TEXTURE_INTRO].file, mRenderer); - - // Musicas - mMusic[MUSIC_INTRO].music = JA_LoadMusic(mMusic[MUSIC_INTRO].file.c_str()); - - return success; -} - -// Libera las variables necesarias para la sección 'Intro' -void GameDirector::quitIntro() -{ - // Texturas - mTexture[TEXTURE_INTRO].texture->unload(); - - // Musicas - JA_DeleteMusic(mMusic[MUSIC_INTRO].music); - - // Libera la memoria de los punteros - delete mTexture[TEXTURE_INTRO].texture; - mTexture[TEXTURE_INTRO].texture = nullptr; - - for (Uint8 i = 0; i < INTRO_TOTAL_BITMAPS; i++) - { - delete mIntro.bitmap[i]; - mIntro.bitmap[i] = nullptr; - } - for (Uint8 i = 0; i < INTRO_TOTAL_TEXTS; i++) - { - delete mIntro.text[i]; - mIntro.text[i] = nullptr; - } -} - -// Inicializa las variables necesarias para la sección 'Title' -void GameDirector::initTitle(Uint8 subsection) -{ - // Reserva memoria para los punteros - mTexture[TEXTURE_TITLE].texture = new LTexture(); - mTexture[TEXTURE_ITEMS].texture = new LTexture(); - mTitle.coffeeBitmap = new SmartSprite(); - mTitle.crisisBitmap = new SmartSprite(); - mTitle.dustBitmapL = new AnimatedSprite(); - mTitle.dustBitmapR = new AnimatedSprite(); - mTitle.tile = new Sprite(); - - // Carga los recursos - loadMediaTitle(); - - // Inicializa las variables - resetTitle(subsection); -} - -// Resetea las variables necesarias para la sección 'Title' -void GameDirector::resetTitle(Uint8 subsection) -{ - // Inicializa variables - mTitle.section = subsection; - mTitle.counter = TITLE_COUNTER; - mTitle.backgroundCounter = 0; - mTitle.backgroundMode = rand() % 2; - mTitle.menuVisible = false; - mTitle.nextProgSection = PROG_SECTION_GAME; - mTitle.instructionsCounter = INSTRUCTIONS_COUNTER; - mTitle.instructionsMode = MODE_AUTO; - - // Inicializa el bitmap de Coffee - mTitle.coffeeBitmap->init(mTexture[TEXTURE_TITLE].texture, mRenderer); - mTitle.coffeeBitmap->setId(0); - mTitle.coffeeBitmap->setIntroEvents(&mTitle.events[0]); - mTitle.coffeeBitmap->setPosX(45); - mTitle.coffeeBitmap->setPosY(11 - 200); - mTitle.coffeeBitmap->setWidth(167); - mTitle.coffeeBitmap->setHeight(46); - mTitle.coffeeBitmap->setVelX(0.0f); - mTitle.coffeeBitmap->setVelY(2.5f); - mTitle.coffeeBitmap->setAccelX(0.0f); - mTitle.coffeeBitmap->setAccelY(0.1f); - mTitle.coffeeBitmap->setSpriteClip(0, 0, 167, 46); - mTitle.coffeeBitmap->setEnabled(true); - mTitle.coffeeBitmap->setEnabledTimer(0); - mTitle.coffeeBitmap->setDestX(45); - mTitle.coffeeBitmap->setDestY(11); - - // Inicializa el bitmap de Crisis - mTitle.crisisBitmap->init(mTexture[TEXTURE_TITLE].texture, mRenderer); - mTitle.crisisBitmap->setId(1); - mTitle.crisisBitmap->setIntroEvents(&mTitle.events[0]); - mTitle.crisisBitmap->setPosX(60); - mTitle.crisisBitmap->setPosY(57 + 200); - mTitle.crisisBitmap->setWidth(137); - mTitle.crisisBitmap->setHeight(46); - mTitle.crisisBitmap->setVelX(0.0f); - mTitle.crisisBitmap->setVelY(-2.5f); - mTitle.crisisBitmap->setAccelX(0.0f); - mTitle.crisisBitmap->setAccelY(-0.1f); - mTitle.crisisBitmap->setSpriteClip(0, 46, 137, 46); - mTitle.crisisBitmap->setEnabled(true); - mTitle.crisisBitmap->setEnabledTimer(0); - mTitle.crisisBitmap->setDestX(60); - mTitle.crisisBitmap->setDestY(57); - - // Inicializa el bitmap de DustRight - mTitle.dustBitmapR->init(mTexture[TEXTURE_TITLE].texture, mRenderer); - mTitle.dustBitmapR->setPosX(218); - mTitle.dustBitmapR->setPosY(47); - mTitle.dustBitmapR->setWidth(16); - mTitle.dustBitmapR->setHeight(14); - mTitle.dustBitmapR->setCurrentFrame(0); - mTitle.dustBitmapR->setAnimationCounter(0); - mTitle.dustBitmapR->setAnimationNumFrames(0, 7); - mTitle.dustBitmapR->setAnimationSpeed(0, 8); - mTitle.dustBitmapR->setAnimationLoop(0, false); - mTitle.dustBitmapR->setAnimationFrames(0, 0, 160 + (mTitle.dustBitmapR->getWidth() * 0), 80, mTitle.dustBitmapR->getWidth(), mTitle.dustBitmapR->getHeight()); - mTitle.dustBitmapR->setAnimationFrames(0, 1, 160 + (mTitle.dustBitmapR->getWidth() * 1), 80, mTitle.dustBitmapR->getWidth(), mTitle.dustBitmapR->getHeight()); - mTitle.dustBitmapR->setAnimationFrames(0, 2, 160 + (mTitle.dustBitmapR->getWidth() * 2), 80, mTitle.dustBitmapR->getWidth(), mTitle.dustBitmapR->getHeight()); - mTitle.dustBitmapR->setAnimationFrames(0, 3, 160 + (mTitle.dustBitmapR->getWidth() * 3), 80, mTitle.dustBitmapR->getWidth(), mTitle.dustBitmapR->getHeight()); - mTitle.dustBitmapR->setAnimationFrames(0, 4, 160 + (mTitle.dustBitmapR->getWidth() * 4), 80, mTitle.dustBitmapR->getWidth(), mTitle.dustBitmapR->getHeight()); - mTitle.dustBitmapR->setAnimationFrames(0, 5, 160 + (mTitle.dustBitmapR->getWidth() * 5), 80, mTitle.dustBitmapR->getWidth(), mTitle.dustBitmapR->getHeight()); - mTitle.dustBitmapR->setAnimationFrames(0, 6, 160 + (mTitle.dustBitmapR->getWidth() * 6), 80, mTitle.dustBitmapR->getWidth(), mTitle.dustBitmapR->getHeight()); - - // Inicializa el bitmap de DustLeft - mTitle.dustBitmapL->init(mTexture[TEXTURE_TITLE].texture, mRenderer); - mTitle.dustBitmapL->setPosX(33); - mTitle.dustBitmapL->setPosY(47); - mTitle.dustBitmapL->setWidth(16); - mTitle.dustBitmapL->setHeight(14); - mTitle.dustBitmapL->setCurrentFrame(0); - mTitle.dustBitmapL->setAnimationCounter(0); - mTitle.dustBitmapL->setAnimationNumFrames(0, 7); - mTitle.dustBitmapL->setAnimationSpeed(0, 8); - mTitle.dustBitmapL->setAnimationLoop(0, false); - mTitle.dustBitmapL->setAnimationFrames(0, 0, 160 + (mTitle.dustBitmapL->getWidth() * 0), 66, mTitle.dustBitmapL->getWidth(), mTitle.dustBitmapL->getHeight()); - mTitle.dustBitmapL->setAnimationFrames(0, 1, 160 + (mTitle.dustBitmapL->getWidth() * 1), 66, mTitle.dustBitmapL->getWidth(), mTitle.dustBitmapL->getHeight()); - mTitle.dustBitmapL->setAnimationFrames(0, 2, 160 + (mTitle.dustBitmapL->getWidth() * 2), 66, mTitle.dustBitmapL->getWidth(), mTitle.dustBitmapL->getHeight()); - mTitle.dustBitmapL->setAnimationFrames(0, 3, 160 + (mTitle.dustBitmapL->getWidth() * 3), 66, mTitle.dustBitmapL->getWidth(), mTitle.dustBitmapL->getHeight()); - mTitle.dustBitmapL->setAnimationFrames(0, 4, 160 + (mTitle.dustBitmapL->getWidth() * 4), 66, mTitle.dustBitmapL->getWidth(), mTitle.dustBitmapL->getHeight()); - mTitle.dustBitmapL->setAnimationFrames(0, 5, 160 + (mTitle.dustBitmapL->getWidth() * 5), 66, mTitle.dustBitmapL->getWidth(), mTitle.dustBitmapL->getHeight()); - mTitle.dustBitmapL->setAnimationFrames(0, 6, 160 + (mTitle.dustBitmapL->getWidth() * 6), 66, mTitle.dustBitmapL->getWidth(), mTitle.dustBitmapL->getHeight()); - - // Inicializa el vector de eventos de la pantalla de titulo - for (Uint8 i = 0; i < TITLE_TOTAL_EVENTS; i++) - mTitle.events[i] = EVENT_WAITING; -} - -// Carga los recursos necesarios para la sección 'Title' -bool GameDirector::loadMediaTitle() -{ - // Indicador de éxito en la carga - bool success = true; - - // Texturas - success &= loadTextureFromFile(mTexture[TEXTURE_TITLE].texture, mTexture[TEXTURE_TITLE].file, mRenderer); - success &= loadTextureFromFile(mTexture[TEXTURE_ITEMS].texture, mTexture[TEXTURE_ITEMS].file, mRenderer); - - // Crea el mosaico de fondo del titulo - mTitleSurface = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH * 2, SCREEN_HEIGHT * 2); - if (mTitleSurface == NULL) - { - printf("TitleSurface could not be created!\nSDL Error: %s\n", SDL_GetError()); - success = false; - } - else - { - SDL_SetRenderTarget(mRenderer, mTitleSurface); - SDL_SetRenderDrawColor(mRenderer, 0x43, 0x43, 0x4F, 0xFF); - SDL_RenderClear(mRenderer); - - mTitle.tile->init(0, 0, 64, 64, mTexture[TEXTURE_TITLE].texture, mRenderer); - mTitle.tile->setSpriteClip(192, 0, 64, 64); - for (Uint8 i = 0; i < 8; i++) - for (Uint8 j = 0; j < 6; j++) - { - mTitle.tile->setPosX(i * 64); - mTitle.tile->setPosY(j * 64); - mTitle.tile->render(); - } - - mTitle.backgroundWindow.x = 0; - mTitle.backgroundWindow.y = 0; - mTitle.backgroundWindow.w = SCREEN_WIDTH; - mTitle.backgroundWindow.h = SCREEN_HEIGHT; - SDL_SetRenderTarget(mRenderer, nullptr); - } - - // Crea una textura para dibujar las instrucciones - mInstructionsSurface = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH, SCREEN_HEIGHT); - if (mInstructionsSurface == NULL) - { - printf("InstructionsSurface could not be created!\nSDL Error: %s\n", SDL_GetError()); - success = false; - } - - // Sonidos - mSound[SOUND_TITLE].sound = JA_LoadSound(mSound[SOUND_TITLE].file.c_str()); - - return success; -} - -// Libera las variables necesarias para la sección 'Title' -void GameDirector::quitTitle() -{ - // Texturas - mTexture[TEXTURE_TITLE].texture->unload(); - mTexture[TEXTURE_ITEMS].texture->unload(); - - // Sonidos - JA_DeleteSound(mSound[SOUND_TITLE].sound); - - // Libera la memoria de los punteros - delete mTexture[TEXTURE_TITLE].texture; - delete mTexture[TEXTURE_ITEMS].texture; - delete mTitle.coffeeBitmap; - delete mTitle.crisisBitmap; - delete mTitle.dustBitmapL; - delete mTitle.dustBitmapR; - delete mTitle.tile; - mTexture[TEXTURE_TITLE].texture = nullptr; - mTexture[TEXTURE_ITEMS].texture = nullptr; - mTitle.coffeeBitmap = nullptr; - mTitle.crisisBitmap = nullptr; - mTitle.dustBitmapL = nullptr; - mTitle.dustBitmapR = nullptr; - mTitle.tile = nullptr; - - SDL_DestroyTexture(mTitleSurface); - SDL_DestroyTexture(mInstructionsSurface); - mTitleSurface = nullptr; - mInstructionsSurface = nullptr; -} - -// Inicializa las variables necesarias para la sección 'Game' -void GameDirector::initGame() -{ - // Reserva memoria para los punteros - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - mGame.balloon[i] = new Balloon(); - for (Uint8 i = 0; i < MAX_BULLETS; i++) - mGame.bullet[i] = new Bullet(); - for (Uint8 i = 0; i < MAX_ITEMS; i++) - mGame.item[i] = new Item(); - for (Uint8 i = 0; i < MAX_SMART_SPRITES; i++) - mGame.smartSprite[i] = new SmartSprite(); - mTexture[TEXTURE_PLAYER_LEGS].texture = new LTexture(); - mTexture[TEXTURE_PLAYER_BODY].texture = new LTexture(); - mTexture[TEXTURE_PLAYER_DEATH].texture = new LTexture(); - mTexture[TEXTURE_BALLOON].texture = new LTexture(); - mTexture[TEXTURE_BULLET].texture = new LTexture(); - mTexture[TEXTURE_GAME_BG].texture = new LTexture(); - mTexture[TEXTURE_GAME_TEXT].texture = new LTexture(); - mTexture[TEXTURE_ITEMS].texture = new LTexture(); - mGame.player = new Player(); - mGame._1000Bitmap = new SmartSprite(); - mGame._2500Bitmap = new SmartSprite(); - mGame._5000Bitmap = new SmartSprite(); - mGame.background = new Sprite(); - mGame.clouds1a = new MovingSprite(); - mGame.clouds1b = new MovingSprite(); - mGame.clouds2a = new MovingSprite(); - mGame.clouds2b = new MovingSprite(); - mGame.getReadyBitmap = new Sprite(); - mGame.gradient = new Sprite(); - mGame.grass = new Sprite(); - mGame.scoreBoard = new Sprite(); - mGame.powerMeter = new Sprite(); - - // Carga los recursos - loadMediaGame(); - - // Inicializa variables - resetGame(); -} - -// Inicializa las variables especificas de la sección 'Game' para empezar una nueva partida -void GameDirector::resetGame() -{ - // Inicializa las variables - mGame.section = GAME_SECTION_PLAY; - mGame.menaceCurrent = 0; - mGame.menaceThreshold = 0; - mGame.score = 0; - mGame.hiScoreAchieved = false; - mGame.currentStage = 0; - mGame.stageBitmapCounter = STAGE_COUNTER; - mGame.deathCounter = DEATH_COUNTER; - mGame.explosionTime = false; - mGame.remainingExplosions = REMAINING_EXPLOSIONS; - mGame.remainingExplosionsCounter = REMAINING_EXPLOSIONS_COUNTER; - mGame.timeStopped = false; - mGame.timeStoppedCounter = 0; - mGame.counter = 0; - mGame.balloonsPopped = 0; - mGame.lastEnemyDeploy = 0; - mGame.enemyDeployCounter = 0; - mGame.enemySpeed = BALLOON_SPEED_1; - mGame.effect.flash = false; - mGame.effect.shake = false; - mGame.effect.shakeCounter = SHAKE_COUNTER; - mGame.powerBallEabled = false; - initGameStages(); - - // Sprites - mGame.clouds1a->init(0, 0, 256, 52, -0.4f, 0.0f, 0.0f, 0.0f, mTexture[TEXTURE_GAME_BG].texture, mRenderer); - mGame.clouds1a->setSpriteClip(256, 0, 256, 52); - - mGame.clouds1b->init(256, 0, 256, 52, -0.4f, 0.0f, 0.0f, 0.0f, mTexture[TEXTURE_GAME_BG].texture, mRenderer); - mGame.clouds1b->setSpriteClip(256, 0, 256, 52); - - mGame.clouds2a->init(0, 52, 256, 32, -0.2f, 0.0f, 0.0f, 0.0f, mTexture[TEXTURE_GAME_BG].texture, mRenderer); - mGame.clouds2a->setSpriteClip(256, 52, 256, 32); - - mGame.clouds2b->init(256, 52, 256, 32, -0.2f, 0.0f, 0.0f, 0.0f, mTexture[TEXTURE_GAME_BG].texture, mRenderer); - mGame.clouds2b->setSpriteClip(256, 52, 256, 32); - - mGame.grass->init(0, 85, SCREEN_WIDTH, 6, mTexture[TEXTURE_GAME_BG].texture, mRenderer); - mGame.grass->setPosY(154); - - mGame.scoreBoard->init(0, 160, SCREEN_WIDTH, 32, mTexture[TEXTURE_GAME_BG].texture, mRenderer); - mGame.scoreBoard->setSpriteClip(0, 160, 256, 32); - - mGame.powerMeter->init(PLAY_AREA_CENTER_THIRD_QUARTER_X - 20, HISCORE_NUMBER_Y + 4, 40, 8, mTexture[TEXTURE_GAME_BG].texture, mRenderer); - mGame.powerMeter->setSpriteClip(256, 192 - 8, 40, 8); - - // Objeto jugador - mGame.player->init(PLAY_AREA_CENTER_X - 11, PLAY_AREA_BOTTOM - 24, mTexture[TEXTURE_PLAYER_LEGS].texture, mTexture[TEXTURE_PLAYER_BODY].texture, mRenderer); - - // Establece a cero todos los valores del vector de objetos globo - resetBalloons(); - - // Crea objetos globo y los centra en el area de juego - //mGame.balloon[0]->init(0, -BLOCK, POWER_BALL, BALLOON_VELX_POSITIVE, mGame.enemySpeed, 300, mTexture[TEXTURE_BALLOON].texture, mRenderer); - //mGame.balloon[0]->allignTo(PLAY_AREA_CENTER_X); - - // Con los globos creados, calcula el nivel de amenaza - setMenace(); - - // Establece a cero todos los valores del vector de objetos bala - resetBullets(); - - // Establece a cero todos los valores del vector de objetos item - resetItems(); - - // Establece a cero todos los valores del vector de objetos SmafrtSprite - resetSmartSprites(); - - // Inicializa el bitmap de GetLeady! - mGame.getReadyBitmap->init(0, PLAY_AREA_CENTER_Y - 10, 109, 20, mTexture[TEXTURE_GAME_TEXT].texture, mRenderer); - mGame.getReadyBitmap->setSpriteClip(0, 0, 109, 20); - - // Inicializa el bitmap de 1000 puntos - mGame._1000Bitmap->init(mTexture[TEXTURE_GAME_TEXT].texture, mRenderer); - mGame._1000Bitmap->setPosX(0); - mGame._1000Bitmap->setPosY(0); - mGame._1000Bitmap->setWidth(26); - mGame._1000Bitmap->setHeight(9); - mGame._1000Bitmap->setVelX(0.0f); - mGame._1000Bitmap->setVelY(-0.5f); - mGame._1000Bitmap->setAccelX(0.0f); - mGame._1000Bitmap->setAccelY(-0.1f); - mGame._1000Bitmap->setSpriteClip(0, 20, 26, 9); - mGame._1000Bitmap->setEnabled(false); - mGame._1000Bitmap->setEnabledTimer(0); - mGame._1000Bitmap->setDestX(0); - mGame._1000Bitmap->setDestY(0); - - // Inicializa el bitmap de 2500 puntos - mGame._2500Bitmap->init(mTexture[TEXTURE_GAME_TEXT].texture, mRenderer); - mGame._2500Bitmap->setPosX(0); - mGame._2500Bitmap->setPosY(0); - mGame._2500Bitmap->setWidth(28); - mGame._2500Bitmap->setHeight(9); - mGame._2500Bitmap->setVelX(0.0f); - mGame._2500Bitmap->setVelY(-0.5f); - mGame._2500Bitmap->setAccelX(0.0f); - mGame._2500Bitmap->setAccelY(-0.1f); - mGame._2500Bitmap->setSpriteClip(26, 20, 28, 9); - mGame._2500Bitmap->setEnabled(false); - mGame._2500Bitmap->setEnabledTimer(0); - mGame._2500Bitmap->setDestX(0); - mGame._2500Bitmap->setDestY(0); - - // Inicializa el bitmap de 5000 puntos - mGame._5000Bitmap->init(mTexture[TEXTURE_GAME_TEXT].texture, mRenderer); - mGame._5000Bitmap->setPosX(0); - mGame._5000Bitmap->setPosY(0); - mGame._5000Bitmap->setWidth(28); - mGame._5000Bitmap->setHeight(9); - mGame._5000Bitmap->setVelX(0.0f); - mGame._5000Bitmap->setVelY(-0.5f); - mGame._5000Bitmap->setAccelX(0.0f); - mGame._5000Bitmap->setAccelY(-0.1f); - mGame._5000Bitmap->setSpriteClip(54, 20, 28, 9); - mGame._5000Bitmap->setEnabled(false); - mGame._5000Bitmap->setEnabledTimer(0); - mGame._5000Bitmap->setDestX(0); - mGame._5000Bitmap->setDestY(0); - - // Los fondos - mGame.background->init(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, mTexture[TEXTURE_GAME_BG].texture, mRenderer); - mGame.gradient->init(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, mTexture[TEXTURE_GAME_BG].texture, mRenderer); - mGame.gradientRect[0] = {0, 192, SCREEN_WIDTH, SCREEN_HEIGHT}; - mGame.gradientRect[1] = {256, 192, SCREEN_WIDTH, SCREEN_HEIGHT}; - mGame.gradientRect[2] = {0, 384, SCREEN_WIDTH, SCREEN_HEIGHT}; - mGame.gradientRect[3] = {256, 384, SCREEN_WIDTH, SCREEN_HEIGHT}; -} - -// Carga los recursos necesarios para la sección 'Game' -bool GameDirector::loadMediaGame() -{ - bool success = true; - - // Texturas - success &= loadTextureFromFile(mTexture[TEXTURE_PLAYER_LEGS].texture, mTexture[TEXTURE_PLAYER_LEGS].file, mRenderer); - success &= loadTextureFromFile(mTexture[TEXTURE_PLAYER_BODY].texture, mTexture[TEXTURE_PLAYER_BODY].file, mRenderer); - success &= loadTextureFromFile(mTexture[TEXTURE_PLAYER_DEATH].texture, mTexture[TEXTURE_PLAYER_DEATH].file, mRenderer); - success &= loadTextureFromFile(mTexture[TEXTURE_BALLOON].texture, mTexture[TEXTURE_BALLOON].file, mRenderer); - success &= loadTextureFromFile(mTexture[TEXTURE_BULLET].texture, mTexture[TEXTURE_BULLET].file, mRenderer); - success &= loadTextureFromFile(mTexture[TEXTURE_GAME_BG].texture, mTexture[TEXTURE_GAME_BG].file, mRenderer); - success &= loadTextureFromFile(mTexture[TEXTURE_GAME_TEXT].texture, mTexture[TEXTURE_GAME_TEXT].file, mRenderer); - success &= loadTextureFromFile(mTexture[TEXTURE_ITEMS].texture, mTexture[TEXTURE_ITEMS].file, mRenderer); - - // Sonidos - mSound[SOUND_BALLOON].sound = JA_LoadSound(mSound[SOUND_BALLOON].file.c_str()); - mSound[SOUND_BULLET].sound = JA_LoadSound(mSound[SOUND_BULLET].file.c_str()); - mSound[SOUND_PLAYER_COLLISION].sound = JA_LoadSound(mSound[SOUND_PLAYER_COLLISION].file.c_str()); - mSound[SOUND_HISCORE].sound = JA_LoadSound(mSound[SOUND_HISCORE].file.c_str()); - mSound[SOUND_ITEM_DROP].sound = JA_LoadSound(mSound[SOUND_ITEM_DROP].file.c_str()); - mSound[SOUND_ITEM_PICKUP].sound = JA_LoadSound(mSound[SOUND_ITEM_PICKUP].file.c_str()); - mSound[SOUND_COFFEE_OUT].sound = JA_LoadSound(mSound[SOUND_COFFEE_OUT].file.c_str()); - mSound[SOUND_STAGE_CHANGE].sound = JA_LoadSound(mSound[SOUND_STAGE_CHANGE].file.c_str()); - mSound[SOUND_TITLE].sound = JA_LoadSound(mSound[SOUND_TITLE].file.c_str()); - mSound[SOUND_BUBBLE1].sound = JA_LoadSound(mSound[SOUND_BUBBLE1].file.c_str()); - mSound[SOUND_BUBBLE2].sound = JA_LoadSound(mSound[SOUND_BUBBLE2].file.c_str()); - mSound[SOUND_BUBBLE3].sound = JA_LoadSound(mSound[SOUND_BUBBLE3].file.c_str()); - mSound[SOUND_BUBBLE4].sound = JA_LoadSound(mSound[SOUND_BUBBLE4].file.c_str()); - mSound[SOUND_CLOCK].sound = JA_LoadSound(mSound[SOUND_CLOCK].file.c_str()); - mSound[SOUND_POWERBALL].sound = JA_LoadSound(mSound[SOUND_POWERBALL].file.c_str()); - - // Musicas - mMusic[MUSIC_PLAYING].music = JA_LoadMusic(mMusic[MUSIC_PLAYING].file.c_str()); - - return success; -} - -// Libera las variables necesarias para la sección 'Game' -void GameDirector::quitGame() -{ - // Texturas - mTexture[TEXTURE_PLAYER_LEGS].texture->unload(); - mTexture[TEXTURE_PLAYER_BODY].texture->unload(); - mTexture[TEXTURE_PLAYER_DEATH].texture->unload(); - mTexture[TEXTURE_BALLOON].texture->unload(); - mTexture[TEXTURE_BULLET].texture->unload(); - mTexture[TEXTURE_GAME_BG].texture->unload(); - mTexture[TEXTURE_GAME_TEXT].texture->unload(); - mTexture[TEXTURE_ITEMS].texture->unload(); - - // Sonidos - JA_DeleteSound(mSound[SOUND_BALLOON].sound); - JA_DeleteSound(mSound[SOUND_BULLET].sound); - JA_DeleteSound(mSound[SOUND_PLAYER_COLLISION].sound); - JA_DeleteSound(mSound[SOUND_HISCORE].sound); - JA_DeleteSound(mSound[SOUND_ITEM_DROP].sound); - JA_DeleteSound(mSound[SOUND_ITEM_PICKUP].sound); - JA_DeleteSound(mSound[SOUND_COFFEE_OUT].sound); - JA_DeleteSound(mSound[SOUND_STAGE_CHANGE].sound); - JA_DeleteSound(mSound[SOUND_TITLE].sound); - JA_DeleteSound(mSound[SOUND_BUBBLE1].sound); - JA_DeleteSound(mSound[SOUND_BUBBLE2].sound); - JA_DeleteSound(mSound[SOUND_BUBBLE3].sound); - JA_DeleteSound(mSound[SOUND_BUBBLE4].sound); - JA_DeleteSound(mSound[SOUND_CLOCK].sound); - JA_DeleteSound(mSound[SOUND_POWERBALL].sound); - - // Musicas - JA_DeleteMusic(mMusic[MUSIC_PLAYING].music); - - // Libera la memoria de los punteros - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - { - delete mGame.balloon[i]; - mGame.balloon[i] = nullptr; - } - for (Uint8 i = 0; i < MAX_BULLETS; i++) - { - delete mGame.bullet[i]; - mGame.bullet[i] = nullptr; - } - for (Uint8 i = 0; i < MAX_ITEMS; i++) - { - delete mGame.item[i]; - mGame.item[i] = nullptr; - } - for (Uint8 i = 0; i < MAX_SMART_SPRITES; i++) - { - delete mGame.smartSprite[i]; - mGame.smartSprite[i] = nullptr; - } - delete mTexture[TEXTURE_PLAYER_LEGS].texture; - delete mTexture[TEXTURE_PLAYER_BODY].texture; - delete mTexture[TEXTURE_PLAYER_DEATH].texture; - delete mTexture[TEXTURE_BALLOON].texture; - delete mTexture[TEXTURE_BULLET].texture; - delete mTexture[TEXTURE_GAME_BG].texture; - delete mTexture[TEXTURE_GAME_TEXT].texture; - delete mTexture[TEXTURE_ITEMS].texture; - delete mGame.player; - delete mGame._1000Bitmap; - delete mGame._2500Bitmap; - delete mGame._5000Bitmap; - delete mGame.background; - delete mGame.clouds1a; - delete mGame.clouds1b; - delete mGame.clouds2a; - delete mGame.clouds2b; - delete mGame.getReadyBitmap; - delete mGame.gradient; - delete mGame.grass; - delete mGame.scoreBoard; - delete mGame.powerMeter; - mTexture[TEXTURE_PLAYER_LEGS].texture = nullptr; - mTexture[TEXTURE_PLAYER_BODY].texture = nullptr; - mTexture[TEXTURE_PLAYER_DEATH].texture = nullptr; - mTexture[TEXTURE_BALLOON].texture = nullptr; - mTexture[TEXTURE_BULLET].texture = nullptr; - mTexture[TEXTURE_GAME_BG].texture = nullptr; - mTexture[TEXTURE_GAME_TEXT].texture = nullptr; - mTexture[TEXTURE_ITEMS].texture = nullptr; - mGame.player = nullptr; - mGame._1000Bitmap = nullptr; - mGame._2500Bitmap = nullptr; - mGame._5000Bitmap = nullptr; - mGame.background = nullptr; - mGame.clouds1a = nullptr; - mGame.clouds1b = nullptr; - mGame.clouds2a = nullptr; - mGame.clouds2b = nullptr; - mGame.getReadyBitmap = nullptr; - mGame.gradient = nullptr; - mGame.grass = nullptr; - mGame.scoreBoard = nullptr; - mGame.powerMeter = nullptr; -} - -// Crea el indice de ficheros -void GameDirector::setFileList() -{ - // Ficheros binarios -#ifdef __MIPSEL__ - mBinFile[BINFILE_SCORE].file = "/media/data/local/home/.coffee_crisis/score.bin"; - mBinFile[BINFILE_DEMO].file = "/media/data/local/home/.coffee_crisis/demo.bin"; - mBinFile[BINFILE_CONFIG].file = "/media/data/local/home/.coffee_crisis/config.bin"; -#else - mBinFile[BINFILE_SCORE].file = mProg.executablePath + "/" + "../data/score.bin"; - mBinFile[BINFILE_DEMO].file = mProg.executablePath + "/" + "../data/demo.bin"; - mBinFile[BINFILE_CONFIG].file = mProg.executablePath + "/" + "../data/config.bin"; -#endif - - // Musicas - mMusic[MUSIC_INTRO].file = mProg.executablePath + "/" + "../media/music/intro.ogg"; - mMusic[MUSIC_PLAYING].file = mProg.executablePath + "/" + "../media/music/playing.ogg"; - mMusic[MUSIC_TITLE].file = mProg.executablePath + "/" + "../media/music/title.ogg"; - - // Sonidos - mSound[SOUND_BALLOON].file = mProg.executablePath + "/" + "../media/sound/balloon.wav"; - mSound[SOUND_BUBBLE1].file = mProg.executablePath + "/" + "../media/sound/bubble1.wav"; - mSound[SOUND_BUBBLE2].file = mProg.executablePath + "/" + "../media/sound/bubble2.wav"; - mSound[SOUND_BUBBLE3].file = mProg.executablePath + "/" + "../media/sound/bubble3.wav"; - mSound[SOUND_BUBBLE4].file = mProg.executablePath + "/" + "../media/sound/bubble4.wav"; - mSound[SOUND_BULLET].file = mProg.executablePath + "/" + "../media/sound/bullet.wav"; - mSound[SOUND_COFFEE_OUT].file = mProg.executablePath + "/" + "../media/sound/coffeeout.wav"; - mSound[SOUND_HISCORE].file = mProg.executablePath + "/" + "../media/sound/hiscore.wav"; - mSound[SOUND_ITEM_DROP].file = mProg.executablePath + "/" + "../media/sound/itemdrop.wav"; - mSound[SOUND_ITEM_PICKUP].file = mProg.executablePath + "/" + "../media/sound/itempickup.wav"; - mSound[SOUND_MENU_CANCEL].file = mProg.executablePath + "/" + "../media/sound/menu_cancel.wav"; - mSound[SOUND_MENU_MOVE].file = mProg.executablePath + "/" + "../media/sound/menu_move.wav"; - mSound[SOUND_MENU_SELECT].file = mProg.executablePath + "/" + "../media/sound/menu_select.wav"; - mSound[SOUND_PLAYER_COLLISION].file = mProg.executablePath + "/" + "../media/sound/player_collision.wav"; - mSound[SOUND_STAGE_CHANGE].file = mProg.executablePath + "/" + "../media/sound/stage_change.wav"; - mSound[SOUND_TITLE].file = mProg.executablePath + "/" + "../media/sound/title.wav"; - mSound[SOUND_CLOCK].file = mProg.executablePath + "/" + "../media/sound/clock.wav"; - mSound[SOUND_POWERBALL].file = mProg.executablePath + "/" + "../media/sound/powerball.wav"; - - // Texturas - mTexture[TEXTURE_BALLOON].file = mProg.executablePath + "/" + "../media/gfx/balloon.png"; - mTexture[TEXTURE_BULLET].file = mProg.executablePath + "/" + "../media/gfx/bullet.png"; - mTexture[TEXTURE_FONT_BLACK_X2].file = mProg.executablePath + "/" + "../media/gfx/font_black_x2.png"; - mTexture[TEXTURE_FONT_BLACK].file = mProg.executablePath + "/" + "../media/gfx/font_black.png"; - mTexture[TEXTURE_FONT_NOKIA].file = mProg.executablePath + "/" + "../media/gfx/font_nokia.png"; - mTexture[TEXTURE_FONT_WHITE_X2].file = mProg.executablePath + "/" + "../media/gfx/font_white_x2.png"; - mTexture[TEXTURE_FONT_WHITE].file = mProg.executablePath + "/" + "../media/gfx/font_white.png"; - mTexture[TEXTURE_GAME_BG].file = mProg.executablePath + "/" + "../media/gfx/game_bg.png"; - mTexture[TEXTURE_GAME_TEXT].file = mProg.executablePath + "/" + "../media/gfx/game_text.png"; - mTexture[TEXTURE_INTRO].file = mProg.executablePath + "/" + "../media/gfx/intro.png"; - mTexture[TEXTURE_ITEMS].file = mProg.executablePath + "/" + "../media/gfx/items.png"; - mTexture[TEXTURE_LOGO].file = mProg.executablePath + "/" + "../media/gfx/logo.png"; - mTexture[TEXTURE_MENU].file = mProg.executablePath + "/" + "../media/gfx/menu.png"; - mTexture[TEXTURE_PLAYER_BODY].file = mProg.executablePath + "/" + "../media/gfx/player_body.png"; - mTexture[TEXTURE_PLAYER_DEATH].file = mProg.executablePath + "/" + "../media/gfx/player_death.png"; - mTexture[TEXTURE_PLAYER_LEGS].file = mProg.executablePath + "/" + "../media/gfx/player_legs.png"; - mTexture[TEXTURE_TITLE].file = mProg.executablePath + "/" + "../media/gfx/title.png"; -} - -// Comprueba que todos los ficheros existen -bool GameDirector::checkFileList() -{ - bool success = true; - std::string p; - std::string filename; - SDL_RWops *file; - - // Comprueba los ficheros de musica - printf("\n>> MUSIC FILES\n"); - if (success) - for (Uint8 i = 0; i < TOTAL_MUSIC; i++) - { - p = mMusic[i].file.c_str(); - filename = p.substr(p.find_last_of("\\/") + 1); - file = SDL_RWFromFile(p.c_str(), "r+b"); - if (file != NULL) - { - printf("Checking file %-20s [OK]\n", filename.c_str()); - } - else - { - printf("Checking file %-20s [ERROR]\n", filename.c_str()); - success = false; - break; - } - SDL_RWclose(file); - } - - // Comprueba los ficheros de sonidos - printf("\n>> SOUND FILES\n"); - if (success) - for (Uint8 i = 0; i < TOTAL_SOUND; i++) - { - p = mSound[i].file.c_str(); - filename = p.substr(p.find_last_of("\\/") + 1); - file = SDL_RWFromFile(p.c_str(), "r+b"); - if (file != NULL) - { - printf("Checking file %-20s [OK]\n", filename.c_str()); - } - else - { - printf("Checking file %-20s [ERROR]\n", filename.c_str()); - success = false; - break; - } - SDL_RWclose(file); - } - - // Comprueba los ficheros con texturas - printf("\n>> TEXTURE FILES\n"); - if (success) - for (Uint8 i = 0; i < TOTAL_TEXTURE; i++) - { - p = mTexture[i].file.c_str(); - filename = p.substr(p.find_last_of("\\/") + 1); - file = SDL_RWFromFile(p.c_str(), "r+b"); - if (file != NULL) - { - printf("Checking file %-20s [OK]\n", filename.c_str()); - } - else - { - printf("Checking file %-20s [ERROR]\n", filename.c_str()); - success = false; - break; - } - SDL_RWclose(file); - } - - // Resultado - if (success) - printf("\n** All files OK.\n\n"); - else - printf("\n** A file is missing. Exiting.\n\n"); - - return success; -} - -// Carga el fichero de puntos -bool GameDirector::loadScoreFile() -{ - // Indicador de éxito en la carga - bool success = true; - std::string path = mProg.executablePath + "/"; - std::string p = mBinFile[BINFILE_SCORE].file.c_str(); - std::string filename = p.substr(p.find_last_of("\\/") + 1); - SDL_RWops *file = SDL_RWFromFile(p.c_str(), "r+b"); - - // El fichero no existe - if (file == NULL) - { - printf("Warning: Unable to open %s file\n", filename.c_str()); - - // Creamos el fichero para escritura - file = SDL_RWFromFile(p.c_str(), "w+b"); - if (file != NULL) - { - printf("New file (%s) created!\n", filename.c_str()); - - // Inicializamos los datos - for (int i = 0; i < TOTAL_SCORE_DATA; ++i) - { - mGame.scoreDataFile[i] = 0; - SDL_RWwrite(file, &mGame.scoreDataFile[i], sizeof(Uint32), 1); - } - - // Cerramos el fichero - SDL_RWclose(file); - } - else - { - printf("Error: Unable to create file %s\n", filename.c_str()); - success = false; - } - } - // El fichero existe - else - { - // Cargamos los datos - printf("Reading file %s\n", filename.c_str()); - for (int i = 0; i < TOTAL_SCORE_DATA; ++i) - SDL_RWread(file, &mGame.scoreDataFile[i], sizeof(Uint32), 1); - - // Cierra el fichero - SDL_RWclose(file); - } - - // Establece el valor de la máxima puntuación a partir del vector con los datos - if (mGame.scoreDataFile[0] == 0) - mGame.hiScore = 10000; - // Comprueba el checksum para ver si se ha modificado el fichero - else if (mGame.scoreDataFile[0] % 43 == mGame.scoreDataFile[1]) - mGame.hiScore = mGame.scoreDataFile[0]; - else - mGame.hiScore = 10000; - - return success; -} - -// Carga el fichero de configuración -bool GameDirector::loadConfigFile() -{ - // Indicador de éxito en la carga - bool success = true; - std::string path = mProg.executablePath + "/"; - std::string p = mBinFile[BINFILE_CONFIG].file.c_str(); - std::string filename = p.substr(p.find_last_of("\\/") + 1); - SDL_RWops *file = SDL_RWFromFile(p.c_str(), "r+b"); - - // El fichero no existe - if (file == NULL) - { - printf("Warning: Unable to open %s file\n", filename.c_str()); - - // Creamos el fichero para escritura - file = SDL_RWFromFile(p.c_str(), "w+b"); - if (file != NULL) - { - printf("New file (%s) created!\n", filename.c_str()); - - // Inicializamos los datos - mOptions.fullScreenMode = 0; - SDL_RWwrite(file, &mOptions.fullScreenMode, sizeof(mOptions.fullScreenMode), 1); - - mOptions.windowSize = 3; - SDL_RWwrite(file, &mOptions.windowSize, sizeof(mOptions.windowSize), 1); - - // Cerramos el fichero - SDL_RWclose(file); - } - else - { - printf("Error: Unable to create file %s\n", filename.c_str()); - success = false; - } - } - // El fichero existe - else - { - // Cargamos los datos - printf("Reading file %s\n", filename.c_str()); - SDL_RWread(file, &mOptions.fullScreenMode, sizeof(mOptions.fullScreenMode), 1); - SDL_SetWindowFullscreen(mWindow, mOptions.fullScreenMode); - SDL_RWread(file, &mOptions.windowSize, sizeof(mOptions.windowSize), 1); - SDL_SetWindowSize(mWindow, SCREEN_WIDTH * mOptions.windowSize, SCREEN_HEIGHT * mOptions.windowSize); - - // Cierra el fichero - SDL_RWclose(file); - } - - return success; -} - -// Carga el fichero de datos para la demo -bool GameDirector::loadDemoFile() -{ - // Indicador de éxito en la carga - bool success = true; - std::string path = mProg.executablePath + "/"; - std::string p = mBinFile[BINFILE_DEMO].file.c_str(); - std::string filename = p.substr(p.find_last_of("\\/") + 1); - SDL_RWops *file = SDL_RWFromFile(p.c_str(), "r+b"); - - // El fichero no existe - if (file == NULL) - { - printf("Warning: Unable to open %s file\n", filename.c_str()); - - // Creamos el fichero para escritura - file = SDL_RWFromFile(p.c_str(), "w+b"); - if (file != NULL) - { - printf("New file (%s) created!\n", filename.c_str()); - - // Inicializamos los datos - for (int i = 0; i < TOTAL_DEMO_DATA; ++i) - { - mDemo.keys.left = 0; - mDemo.keys.right = 0; - mDemo.keys.noInput = 0; - mDemo.keys.fire = 0; - mDemo.keys.fireLeft = 0; - mDemo.keys.fireRight = 0; - mDemo.dataFile[i] = mDemo.keys; - SDL_RWwrite(file, &mDemo.dataFile[i], sizeof(demoKeys_t), 1); - } - - // Cerramos el fichero - SDL_RWclose(file); - } - else - { - printf("Error: Unable to create file %s\n", filename.c_str()); - success = false; - } - } - // El fichero existe - else - { - // Cargamos los datos - printf("Reading file %s\n", filename.c_str()); - for (int i = 0; i < TOTAL_DEMO_DATA; ++i) - SDL_RWread(file, &mDemo.dataFile[i], sizeof(demoKeys_t), 1); - - // Cierra el fichero - SDL_RWclose(file); - } - - return success; -} - -// Guarda el fichero de puntos -bool GameDirector::saveScoreFile() -{ - bool success = true; - std::string path = mProg.executablePath + "/"; - std::string p = mBinFile[BINFILE_SCORE].file; - std::string filename = p.substr(p.find_last_of("\\/") + 1); - SDL_RWops *file = SDL_RWFromFile(p.c_str(), "w+b"); - if (file != NULL) - { - // Guardamos los datos - for (int i = 0; i < TOTAL_SCORE_DATA; ++i) - { - SDL_RWwrite(file, &mGame.scoreDataFile[i], sizeof(Uint32), 1); - } - - printf("Writing file %s\n", filename.c_str()); - - // Cerramos el fichero - SDL_RWclose(file); - } - else - { - printf("Error: Unable to save %s file! %s\n", filename.c_str(), SDL_GetError()); - } - return success; -} - -// Guarda el fichero de configuración -bool GameDirector::saveConfigFile() -{ - bool success = true; - std::string path = mProg.executablePath + "/"; - std::string p = mBinFile[BINFILE_CONFIG].file; - std::string filename = p.substr(p.find_last_of("\\/") + 1); - SDL_RWops *file = SDL_RWFromFile(p.c_str(), "w+b"); - if (file != NULL) - { - // Guarda los datos - SDL_RWwrite(file, &mOptions.fullScreenMode, sizeof(Uint32), 1); - SDL_RWwrite(file, &mOptions.windowSize, sizeof(Uint8), 1); - - printf("Writing file %s\n", filename.c_str()); - - // Cierra el fichero - SDL_RWclose(file); - } - else - { - printf("Error: Unable to save %s file! %s\n", filename.c_str(), SDL_GetError()); - } - return success; -} - -// Guarda el fichero de datos para la demo -bool GameDirector::saveDemoFile() -{ - bool success = true; - std::string path = mProg.executablePath + "/"; - std::string p = mBinFile[BINFILE_DEMO].file; - std::string filename = p.substr(p.find_last_of("\\/") + 1); - if (mDemo.recording) - { - SDL_RWops *file = SDL_RWFromFile(p.c_str(), "w+b"); - if (file != NULL) - { - // Guardamos los datos - for (int i = 0; i < TOTAL_DEMO_DATA; ++i) - { - SDL_RWwrite(file, &mDemo.dataFile[i], sizeof(demoKeys_t), 1); - } - - printf("Writing file %s\n", filename.c_str()); - - // Cerramos el fichero - SDL_RWclose(file); - } - else - { - printf("Error: Unable to save %s file! %s\n", filename.c_str(), SDL_GetError()); - } - } - return success; -} - -// Carga un archivo de imagen en una textura -bool GameDirector::loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer) -{ - bool success = true; - if (!texture->loadFromFile(path, renderer)) - { - printf("Failed to load %s texture!\n", path.c_str()); - success = false; - } - return success; -} - -// Comprueba el valor de la variable 'quit' -bool GameDirector::exit() -{ - return mProg.quit; -} - -// Establece el valor de la variable -void GameDirector::setExecutablePath(std::string path) -{ - mProg.executablePath = path.substr(0, path.find_last_of("\\/")); -} - -// Inicializa las formaciones enemigas -void GameDirector::initEnemyFormations() -{ - const int y4 = (PLAY_AREA_TOP - BLOCK); - const int x4_0 = PLAY_AREA_LEFT; - //const int x4_50 = PLAY_AREA_CENTER_X - (BALLOON_WIDTH_4 / 2); - 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_50 = PLAY_AREA_CENTER_X - (BALLOON_WIDTH_3 / 2); - 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_50 = PLAY_AREA_CENTER_X - (BALLOON_WIDTH_2 / 2); - 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; - - const Uint16 creationTime = 300; - int incX = 0; - Uint8 incTime = 0; - Uint8 j = 0; - - // #00 - Dos enemigos BALLOON4 uno a cada extremo - j = 0; - mEnemyFormation[j].numberOfEnemies = 2; - incX = x4_100; - incTime = 0; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x4_0 + (i * incX); - mEnemyFormation[j].init[i].y = y4; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE * (((i % 2) * 2) - 1); - mEnemyFormation[j].init[i].kind = BALLOON_4; - mEnemyFormation[j].init[i].creationCounter = creationTime + (incTime * i); - } - - // #01 - Dos enemigos BALLOON4 uno a cada cuarto. Ambos van hacia el centro - j = 1; - mEnemyFormation[j].numberOfEnemies = 2; - incX = PLAY_AREA_CENTER_X; - incTime = 0; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = PLAY_AREA_CENTER_FIRST_QUARTER_X - (BALLOON_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 (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x2_0 + (i * incX); - mEnemyFormation[j].init[i].y = y2; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE; - mEnemyFormation[j].init[i].kind = BALLOON_2; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #03 - Cuatro enemigos BALLOON2 uno detras del otro. A la derecha y hacia el centro - j = 3; - mEnemyFormation[j].numberOfEnemies = 4; - incX = BALLOON_WIDTH_2 + 1; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x2_100 - (i * incX); - mEnemyFormation[j].init[i].y = y2; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE; - mEnemyFormation[j].init[i].kind = BALLOON_2; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #04 - Tres enemigos BALLOON3. 0, 25, 50. Hacia la derecha - j = 4; - mEnemyFormation[j].numberOfEnemies = 3; - incX = BALLOON_WIDTH_3 * 2; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x3_0 + (i * incX); - mEnemyFormation[j].init[i].y = y3; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE; - mEnemyFormation[j].init[i].kind = BALLOON_3; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #05 - Tres enemigos BALLOON3. 50, 75, 100. Hacia la izquierda - j = 5; - mEnemyFormation[j].numberOfEnemies = 3; - incX = BALLOON_WIDTH_3 * 2; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x3_100 - (i * incX); - mEnemyFormation[j].init[i].y = y3; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE; - mEnemyFormation[j].init[i].kind = BALLOON_3; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #06 - Tres enemigos BALLOON3. 0, 0, 0. Hacia la derecha - j = 6; - mEnemyFormation[j].numberOfEnemies = 3; - incX = BALLOON_WIDTH_3 + 1; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x3_0 + (i * incX); - mEnemyFormation[j].init[i].y = y3; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE; - mEnemyFormation[j].init[i].kind = BALLOON_3; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #07 - Tres enemigos BALLOON3. 100, 100, 100. Hacia la izquierda - j = 7; - mEnemyFormation[j].numberOfEnemies = 3; - incX = BALLOON_WIDTH_3 + 1; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x3_100 - (i * incX); - mEnemyFormation[j].init[i].y = y3; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE; - mEnemyFormation[j].init[i].kind = BALLOON_3; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #08 - Seis enemigos BALLOON1. 0, 0, 0, 0, 0, 0. Hacia la derecha - j = 8; - mEnemyFormation[j].numberOfEnemies = 6; - incX = BALLOON_WIDTH_1 + 1; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x1_0 + (i * incX); - mEnemyFormation[j].init[i].y = 13; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE; - mEnemyFormation[j].init[i].kind = BALLOON_1; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #09 - Seis enemigos BALLOON1. 100, 100, 100, 100, 100, 100. Hacia la izquierda - j = 9; - mEnemyFormation[j].numberOfEnemies = 6; - incX = BALLOON_WIDTH_1 + 1; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x1_100 - (i * incX); - mEnemyFormation[j].init[i].y = 13; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE; - mEnemyFormation[j].init[i].kind = BALLOON_1; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #10 - Tres enemigos BALLOON4 seguidos desde la izquierda - j = 10; - mEnemyFormation[j].numberOfEnemies = 3; - incX = BALLOON_WIDTH_4 + 1; - incTime = 15; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x4_0 + (i * incX); - mEnemyFormation[j].init[i].y = y4; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE; - mEnemyFormation[j].init[i].kind = BALLOON_4; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #11 - Tres enemigos BALLOON4 seguidos desde la derecha - j = 11; - mEnemyFormation[j].numberOfEnemies = 3; - incX = BALLOON_WIDTH_4 + 1; - incTime = 15; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x4_100 - (i * incX); - mEnemyFormation[j].init[i].y = y4; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE; - mEnemyFormation[j].init[i].kind = BALLOON_4; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #12 - Seis enemigos BALLOON2 uno detras del otro. A la izquierda y hacia el centro - j = 12; - mEnemyFormation[j].numberOfEnemies = 6; - incX = BALLOON_WIDTH_2 + 1; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x2_0 + (i * incX); - mEnemyFormation[j].init[i].y = y2; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE; - mEnemyFormation[j].init[i].kind = BALLOON_2; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #13 - Seis enemigos BALLOON2 uno detras del otro. A la derecha y hacia el centro - j = 13; - mEnemyFormation[j].numberOfEnemies = 6; - incX = BALLOON_WIDTH_2 + 1; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x2_100 - (i * incX); - mEnemyFormation[j].init[i].y = y2; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE; - mEnemyFormation[j].init[i].kind = BALLOON_2; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #14 - Cinco enemigos BALLOON3. Hacia la derecha. Separados - j = 14; - mEnemyFormation[j].numberOfEnemies = 5; - incX = BALLOON_WIDTH_3 * 2; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x3_0 + (i * incX); - mEnemyFormation[j].init[i].y = y3; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE; - mEnemyFormation[j].init[i].kind = BALLOON_3; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #15 - Cinco enemigos BALLOON3. Hacia la izquierda. Separados - j = 15; - mEnemyFormation[j].numberOfEnemies = 5; - incX = BALLOON_WIDTH_3 * 2; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x3_100 - (i * incX); - mEnemyFormation[j].init[i].y = y3; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE; - mEnemyFormation[j].init[i].kind = BALLOON_3; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #16 - Cinco enemigos BALLOON3. Hacia la derecha. Juntos - j = 16; - mEnemyFormation[j].numberOfEnemies = 5; - incX = BALLOON_WIDTH_3 + 1; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x3_0 + (i * incX); - mEnemyFormation[j].init[i].y = y3; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE; - mEnemyFormation[j].init[i].kind = BALLOON_3; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #17 - Cinco enemigos BALLOON3. Hacia la izquierda. Juntos - j = 17; - mEnemyFormation[j].numberOfEnemies = 5; - incX = BALLOON_WIDTH_3 + 1; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x3_100 - (i * incX); - mEnemyFormation[j].init[i].y = y3; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE; - mEnemyFormation[j].init[i].kind = BALLOON_3; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #18 - Doce enemigos BALLOON1. Hacia la derecha. Juntos - j = 18; - mEnemyFormation[j].numberOfEnemies = 12; - incX = BALLOON_WIDTH_1 + 1; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x1_0 + (i * incX); - mEnemyFormation[j].init[i].y = y1; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE; - mEnemyFormation[j].init[i].kind = BALLOON_1; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #19 - Doce enemigos BALLOON1. Hacia la izquierda. Juntos - j = 19; - mEnemyFormation[j].numberOfEnemies = 12; - incX = BALLOON_WIDTH_1 + 1; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - mEnemyFormation[j].init[i].x = x1_100 - (i * incX); - mEnemyFormation[j].init[i].y = y1; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE; - mEnemyFormation[j].init[i].kind = BALLOON_1; - mEnemyFormation[j].init[i].creationCounter = creationTime - (incTime * i); - } - - // #20 - Dos enemigos BALLOON4 seguidos desde la izquierda/derecha. Simetricos - j = 20; - mEnemyFormation[j].numberOfEnemies = 4; - incX = BALLOON_WIDTH_4 + 1; - incTime = 0; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - Uint8 half = mEnemyFormation[j].numberOfEnemies / 2; - if (i < half) - { - mEnemyFormation[j].init[i].x = x4_0 + (i * incX); - mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE; - } - else - { - mEnemyFormation[j].init[i].x = x4_100 - ((i - half) * incX); - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE; - } - mEnemyFormation[j].init[i].y = y4; - mEnemyFormation[j].init[i].kind = BALLOON_4; - mEnemyFormation[j].init[i].creationCounter = creationTime + (incTime * i); - } - - // #21 - Diez enemigos BALLOON2 uno detras del otro. Izquierda/derecha. Simetricos - j = 21; - mEnemyFormation[j].numberOfEnemies = 10; - incX = BALLOON_WIDTH_2 + 1; - incTime = 3; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - Uint8 half = mEnemyFormation[j].numberOfEnemies / 2; - if (i < half) - { - mEnemyFormation[j].init[i].x = x2_0 + (i * incX); - mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE; - mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * i); - } - else - { - mEnemyFormation[j].init[i].x = x2_100 - ((i - half) * incX); - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE; - mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * (i - half)); - } - mEnemyFormation[j].init[i].y = y2; - mEnemyFormation[j].init[i].kind = BALLOON_2; - } - - // #22 - Diez enemigos BALLOON3. Hacia la derecha/izquierda. Separados. Simetricos - j = 22; - mEnemyFormation[j].numberOfEnemies = 10; - incX = BALLOON_WIDTH_3 * 2; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - Uint8 half = mEnemyFormation[j].numberOfEnemies / 2; - if (i < half) - { - mEnemyFormation[j].init[i].x = x3_0 + (i * incX); - mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE; - mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * i); - } - else - { - mEnemyFormation[j].init[i].x = x3_100 - ((i - half) * incX); - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE; - mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * (i - half)); - } - mEnemyFormation[j].init[i].y = y3; - mEnemyFormation[j].init[i].kind = BALLOON_3; - } - - // #23 - Diez enemigos BALLOON3. Hacia la derecha. Juntos. Simetricos - j = 23; - mEnemyFormation[j].numberOfEnemies = 10; - incX = BALLOON_WIDTH_3 + 1; - incTime = 10; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - Uint8 half = mEnemyFormation[j].numberOfEnemies / 2; - if (i < half) - { - mEnemyFormation[j].init[i].x = x3_0 + (i * incX); - mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE; - mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * i); - } - else - { - mEnemyFormation[j].init[i].x = x3_100 - ((i - half) * incX); - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE; - mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * (i - half)); - } - mEnemyFormation[j].init[i].y = y3; - mEnemyFormation[j].init[i].kind = BALLOON_3; - } - - // #24 - Treinta enemigos BALLOON1. Del centro hacia los extremos. Juntos. Simetricos - j = 24; - mEnemyFormation[j].numberOfEnemies = 30; - incX = 0; - incTime = 5; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - Uint8 half = mEnemyFormation[j].numberOfEnemies / 2; - if (i < half) - { - mEnemyFormation[j].init[i].x = x1_50; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE; - mEnemyFormation[j].init[i].creationCounter = (creationTime) + (incTime * i); - } - else - { - mEnemyFormation[j].init[i].x = x1_50; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE; - mEnemyFormation[j].init[i].creationCounter = (creationTime) + (incTime * (i - half)); - } - mEnemyFormation[j].init[i].y = y1; - mEnemyFormation[j].init[i].kind = BALLOON_1; - } - - // #25 - Treinta enemigos BALLOON1. Del centro hacia adentro. Juntos. Simetricos - j = 25; - mEnemyFormation[j].numberOfEnemies = 30; - incX = BALLOON_WIDTH_1 + 1; - incTime = 5; - for (Uint8 i = 0; i < mEnemyFormation[j].numberOfEnemies; i++) - { - Uint8 half = mEnemyFormation[j].numberOfEnemies / 2; - if (i < half) - { - mEnemyFormation[j].init[i].x = x1_50 + 20; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE; - mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * i); - } - else - { - mEnemyFormation[j].init[i].x = x1_50 - 20; - mEnemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE; - mEnemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * (i - half)); - } - mEnemyFormation[j].init[i].y = y1; - mEnemyFormation[j].init[i].kind = BALLOON_1; - } - - // Crea las mismas formaciones pero con hexagonos a partir de la posición 50 del vector - for (Uint8 k = 0; k < 50; k++) - { - mEnemyFormation[k + 50].numberOfEnemies = mEnemyFormation[k].numberOfEnemies; - for (Uint8 i = 0; i < mEnemyFormation[k + 50].numberOfEnemies; i++) - { - mEnemyFormation[k + 50].init[i].x = mEnemyFormation[k].init[i].x; - mEnemyFormation[k + 50].init[i].y = mEnemyFormation[k].init[i].y; - mEnemyFormation[k + 50].init[i].velX = mEnemyFormation[k].init[i].velX; - mEnemyFormation[k + 50].init[i].creationCounter = mEnemyFormation[k].init[i].creationCounter; - mEnemyFormation[k + 50].init[i].kind = mEnemyFormation[k].init[i].kind + 4; - } - } - - // TEST - mEnemyFormation[99].numberOfEnemies = 4; - - mEnemyFormation[99].init[0].x = 10; - mEnemyFormation[99].init[0].y = y1; - mEnemyFormation[99].init[0].velX = 0; - mEnemyFormation[99].init[0].kind = BALLOON_1; - mEnemyFormation[99].init[0].creationCounter = 200; - - mEnemyFormation[99].init[1].x = 50; - mEnemyFormation[99].init[1].y = y1; - mEnemyFormation[99].init[1].velX = 0; - mEnemyFormation[99].init[1].kind = BALLOON_2; - mEnemyFormation[99].init[1].creationCounter = 200; - - mEnemyFormation[99].init[2].x = 90; - mEnemyFormation[99].init[2].y = y1; - mEnemyFormation[99].init[2].velX = 0; - mEnemyFormation[99].init[2].kind = BALLOON_3; - mEnemyFormation[99].init[2].creationCounter = 200; - - mEnemyFormation[99].init[3].x = 140; - mEnemyFormation[99].init[3].y = y1; - mEnemyFormation[99].init[3].velX = 0; - mEnemyFormation[99].init[3].kind = BALLOON_4; - mEnemyFormation[99].init[3].creationCounter = 200; -} - -// Inicializa los conjuntos de formaciones -void GameDirector::initEnemyPools() -{ - // EnemyPool #0 - mEnemyPool[0].set[0] = &mEnemyFormation[0]; - mEnemyPool[0].set[1] = &mEnemyFormation[1]; - mEnemyPool[0].set[2] = &mEnemyFormation[2]; - mEnemyPool[0].set[3] = &mEnemyFormation[3]; - mEnemyPool[0].set[4] = &mEnemyFormation[4]; - mEnemyPool[0].set[5] = &mEnemyFormation[5]; - mEnemyPool[0].set[6] = &mEnemyFormation[6]; - mEnemyPool[0].set[7] = &mEnemyFormation[7]; - mEnemyPool[0].set[8] = &mEnemyFormation[8]; - mEnemyPool[0].set[9] = &mEnemyFormation[9]; - - // EnemyPool #1 - mEnemyPool[1].set[0] = &mEnemyFormation[10]; - mEnemyPool[1].set[1] = &mEnemyFormation[11]; - mEnemyPool[1].set[2] = &mEnemyFormation[12]; - mEnemyPool[1].set[3] = &mEnemyFormation[13]; - mEnemyPool[1].set[4] = &mEnemyFormation[14]; - mEnemyPool[1].set[5] = &mEnemyFormation[15]; - mEnemyPool[1].set[6] = &mEnemyFormation[16]; - mEnemyPool[1].set[7] = &mEnemyFormation[17]; - mEnemyPool[1].set[8] = &mEnemyFormation[18]; - mEnemyPool[1].set[9] = &mEnemyFormation[19]; - - // EnemyPool #2 - mEnemyPool[2].set[0] = &mEnemyFormation[0]; - mEnemyPool[2].set[1] = &mEnemyFormation[1]; - mEnemyPool[2].set[2] = &mEnemyFormation[2]; - mEnemyPool[2].set[3] = &mEnemyFormation[3]; - mEnemyPool[2].set[4] = &mEnemyFormation[4]; - mEnemyPool[2].set[5] = &mEnemyFormation[55]; - mEnemyPool[2].set[6] = &mEnemyFormation[56]; - mEnemyPool[2].set[7] = &mEnemyFormation[57]; - mEnemyPool[2].set[8] = &mEnemyFormation[58]; - mEnemyPool[2].set[9] = &mEnemyFormation[59]; - - // EnemyPool #3 - mEnemyPool[3].set[0] = &mEnemyFormation[50]; - mEnemyPool[3].set[1] = &mEnemyFormation[51]; - mEnemyPool[3].set[2] = &mEnemyFormation[52]; - mEnemyPool[3].set[3] = &mEnemyFormation[53]; - mEnemyPool[3].set[4] = &mEnemyFormation[54]; - mEnemyPool[3].set[5] = &mEnemyFormation[5]; - mEnemyPool[3].set[6] = &mEnemyFormation[6]; - mEnemyPool[3].set[7] = &mEnemyFormation[7]; - mEnemyPool[3].set[8] = &mEnemyFormation[8]; - mEnemyPool[3].set[9] = &mEnemyFormation[9]; - - // EnemyPool #4 - mEnemyPool[4].set[0] = &mEnemyFormation[60]; - mEnemyPool[4].set[1] = &mEnemyFormation[61]; - mEnemyPool[4].set[2] = &mEnemyFormation[62]; - mEnemyPool[4].set[3] = &mEnemyFormation[63]; - mEnemyPool[4].set[4] = &mEnemyFormation[64]; - mEnemyPool[4].set[5] = &mEnemyFormation[65]; - mEnemyPool[4].set[6] = &mEnemyFormation[66]; - mEnemyPool[4].set[7] = &mEnemyFormation[67]; - mEnemyPool[4].set[8] = &mEnemyFormation[68]; - mEnemyPool[4].set[9] = &mEnemyFormation[69]; - - // EnemyPool #5 - mEnemyPool[5].set[0] = &mEnemyFormation[10]; - mEnemyPool[5].set[1] = &mEnemyFormation[61]; - mEnemyPool[5].set[2] = &mEnemyFormation[12]; - mEnemyPool[5].set[3] = &mEnemyFormation[63]; - mEnemyPool[5].set[4] = &mEnemyFormation[14]; - mEnemyPool[5].set[5] = &mEnemyFormation[65]; - mEnemyPool[5].set[6] = &mEnemyFormation[16]; - mEnemyPool[5].set[7] = &mEnemyFormation[67]; - mEnemyPool[5].set[8] = &mEnemyFormation[18]; - mEnemyPool[5].set[9] = &mEnemyFormation[69]; - - // EnemyPool #6 - mEnemyPool[6].set[0] = &mEnemyFormation[60]; - mEnemyPool[6].set[1] = &mEnemyFormation[11]; - mEnemyPool[6].set[2] = &mEnemyFormation[62]; - mEnemyPool[6].set[3] = &mEnemyFormation[13]; - mEnemyPool[6].set[4] = &mEnemyFormation[64]; - mEnemyPool[6].set[5] = &mEnemyFormation[15]; - mEnemyPool[6].set[6] = &mEnemyFormation[66]; - mEnemyPool[6].set[7] = &mEnemyFormation[17]; - mEnemyPool[6].set[8] = &mEnemyFormation[68]; - mEnemyPool[6].set[9] = &mEnemyFormation[19]; - - // EnemyPool #7 - mEnemyPool[7].set[0] = &mEnemyFormation[20]; - mEnemyPool[7].set[1] = &mEnemyFormation[21]; - mEnemyPool[7].set[2] = &mEnemyFormation[22]; - mEnemyPool[7].set[3] = &mEnemyFormation[23]; - mEnemyPool[7].set[4] = &mEnemyFormation[24]; - mEnemyPool[7].set[5] = &mEnemyFormation[65]; - mEnemyPool[7].set[6] = &mEnemyFormation[66]; - mEnemyPool[7].set[7] = &mEnemyFormation[67]; - mEnemyPool[7].set[8] = &mEnemyFormation[68]; - mEnemyPool[7].set[9] = &mEnemyFormation[69]; - - // EnemyPool #8 - mEnemyPool[8].set[0] = &mEnemyFormation[70]; - mEnemyPool[8].set[1] = &mEnemyFormation[71]; - mEnemyPool[8].set[2] = &mEnemyFormation[72]; - mEnemyPool[8].set[3] = &mEnemyFormation[73]; - mEnemyPool[8].set[4] = &mEnemyFormation[74]; - mEnemyPool[8].set[5] = &mEnemyFormation[15]; - mEnemyPool[8].set[6] = &mEnemyFormation[16]; - mEnemyPool[8].set[7] = &mEnemyFormation[17]; - mEnemyPool[8].set[8] = &mEnemyFormation[18]; - mEnemyPool[8].set[9] = &mEnemyFormation[19]; - - // EnemyPool #9 - mEnemyPool[9].set[0] = &mEnemyFormation[20]; - mEnemyPool[9].set[1] = &mEnemyFormation[21]; - mEnemyPool[9].set[2] = &mEnemyFormation[22]; - mEnemyPool[9].set[3] = &mEnemyFormation[23]; - mEnemyPool[9].set[4] = &mEnemyFormation[24]; - mEnemyPool[9].set[5] = &mEnemyFormation[70]; - mEnemyPool[9].set[6] = &mEnemyFormation[71]; - mEnemyPool[9].set[7] = &mEnemyFormation[72]; - mEnemyPool[9].set[8] = &mEnemyFormation[73]; - mEnemyPool[9].set[9] = &mEnemyFormation[74]; -} - -// Inicializa las fases del juego -void GameDirector::initGameStages() -{ - // STAGE 1 - mGame.stage[0].number = 1; - mGame.stage[0].currentPower = 0; - mGame.stage[0].powerToComplete = 200; - mGame.stage[0].minMenace = 7 + (4 * 1); - mGame.stage[0].maxMenace = 7 + (4 * 3); - mGame.stage[0].enemyPool = &mEnemyPool[0]; - - // STAGE 2 - mGame.stage[1].number = 2; - mGame.stage[1].currentPower = 0; - mGame.stage[1].powerToComplete = 300; - mGame.stage[1].minMenace = 7 + (4 * 2); - mGame.stage[1].maxMenace = 7 + (4 * 4); - mGame.stage[1].enemyPool = &mEnemyPool[1]; - - // STAGE 3 - mGame.stage[2].number = 3; - mGame.stage[2].currentPower = 0; - mGame.stage[2].powerToComplete = 600; - mGame.stage[2].minMenace = 7 + (4 * 3); - mGame.stage[2].maxMenace = 7 + (4 * 6); - mGame.stage[2].enemyPool = &mEnemyPool[2]; - - // STAGE 4 - mGame.stage[3].number = 4; - mGame.stage[3].currentPower = 0; - mGame.stage[3].powerToComplete = 600; - mGame.stage[3].minMenace = 7 + (4 * 3); - mGame.stage[3].maxMenace = 7 + (4 * 7); - mGame.stage[3].enemyPool = &mEnemyPool[3]; - - // STAGE 5 - mGame.stage[4].number = 5; - mGame.stage[4].currentPower = 0; - mGame.stage[4].powerToComplete = 600; - mGame.stage[4].minMenace = 7 + (4 * 4); - mGame.stage[4].maxMenace = 7 + (4 * 8); - mGame.stage[4].enemyPool = &mEnemyPool[4]; - - // STAGE 6 - mGame.stage[5].number = 6; - mGame.stage[5].currentPower = 0; - mGame.stage[5].powerToComplete = 600; - mGame.stage[5].minMenace = 7 + (4 * 5); - mGame.stage[5].maxMenace = 7 + (4 * 10); - mGame.stage[5].enemyPool = &mEnemyPool[5]; - - // STAGE 7 - mGame.stage[6].number = 7; - mGame.stage[6].currentPower = 0; - mGame.stage[6].powerToComplete = 650; - mGame.stage[6].minMenace = 7 + (4 * 6); - mGame.stage[6].maxMenace = 7 + (4 * 11); - mGame.stage[6].enemyPool = &mEnemyPool[6]; - - // STAGE 8 - mGame.stage[7].number = 8; - mGame.stage[7].currentPower = 0; - mGame.stage[7].powerToComplete = 750; - mGame.stage[7].minMenace = 7 + (4 * 7); - mGame.stage[7].maxMenace = 7 + (4 * 12); - mGame.stage[7].enemyPool = &mEnemyPool[7]; - - // STAGE 9 - mGame.stage[8].number = 9; - mGame.stage[8].currentPower = 0; - mGame.stage[8].powerToComplete = 850; - mGame.stage[8].minMenace = 7 + (4 * 8); - mGame.stage[8].maxMenace = 7 + (4 * 13); - mGame.stage[8].enemyPool = &mEnemyPool[8]; - - // STAGE 10 - mGame.stage[9].number = 10; - mGame.stage[9].currentPower = 0; - mGame.stage[9].powerToComplete = 950; - mGame.stage[9].minMenace = 7 + (4 * 9); - mGame.stage[9].maxMenace = 7 + (4 * 15); - mGame.stage[9].enemyPool = &mEnemyPool[9]; -} - -// Crea una formación de enemigos -void GameDirector::deployEnemyFormation() -{ - // Solo despliega una formación enemiga si ha pasado cierto tiempo desde la última - if (mGame.enemyDeployCounter == 0) - { - - // En este punto se decide entre crear una powerball o una formación enemiga - if ((rand() % 100 < 15) && (canPowerBallBeCreated())) - { - // Crea una powerball - createPowerBall(); - - mGame.enemyDeployCounter = 50; - } - else - { - - // Elige una formación enemiga la azar - Uint8 set = (rand() % 10); - - // Evita repetir la ultima formación enemiga desplegada - if (set == mGame.lastEnemyDeploy) - { - set++; - set %= 10; - } - mGame.lastEnemyDeploy = set; - - if (mDebug.enabled) - set = mDebug.enemySet; - - Uint8 numEnemies = mGame.stage[mGame.currentStage].enemyPool->set[set]->numberOfEnemies; - for (Uint8 i = 0; i < numEnemies; i++) - createNewBalloon(mGame.stage[mGame.currentStage].enemyPool->set[set]->init[i].x, - mGame.stage[mGame.currentStage].enemyPool->set[set]->init[i].y, - mGame.stage[mGame.currentStage].enemyPool->set[set]->init[i].kind, - mGame.stage[mGame.currentStage].enemyPool->set[set]->init[i].velX, - mGame.enemySpeed, - mGame.stage[mGame.currentStage].enemyPool->set[set]->init[i].creationCounter, - mTexture[TEXTURE_BALLOON].texture); - - mGame.enemyDeployCounter = 255; - } - } -} - -// Aumenta el poder de la fase -void GameDirector::increaseStageCurrentPower(Uint8 power) -{ - mGame.stage[mGame.currentStage].currentPower += power; -} - -// Establece el valor de la variable -void GameDirector::setScore(Uint32 score) -{ - mGame.score = score; -} - -// Establece el valor de la variable -void GameDirector::setHiScore(Uint32 score) -{ - mGame.hiScore = score; -} - -// Actualiza el valor de HiScore en caso necesario -void GameDirector::updateHiScore() -{ - // La puntuación es mayor que la máxima puntuación - if (mGame.score > mGame.hiScore) - { - // Actualiza la máxima puntuación - mGame.hiScore = mGame.score; - - // Almacena la máxima puntuación en el fichero junto con un checksum - mGame.scoreDataFile[0] = mGame.hiScore; - mGame.scoreDataFile[1] = mGame.hiScore % 43; - - // Si superamos la máxima puntuación - if (mGame.hiScoreAchieved == false) - { - mGame.hiScoreAchieved = true; - JA_PlaySound(mSound[SOUND_HISCORE].sound); - } - } -} - -// Transforma un valor numérico en una cadena de 6 cifras -std::string GameDirector::updateScoreText(Uint32 num) -{ - return (std::to_string(num)); - - if ((num >= 0) && (num <= 9)) - { - return ("000000" + std::to_string(num)); - } - - if ((num >= 10) && (num <= 99)) - { - return ("00000" + std::to_string(num)); - } - - if ((num >= 100) && (num <= 999)) - { - return ("0000" + std::to_string(num)); - } - - if ((num >= 1000) && (num <= 9999)) - { - return ("000" + std::to_string(num)); - } - - if ((num >= 010000) && (num <= 99999)) - { - return ("00" + std::to_string(num)); - } - - if ((num >= 100000) && (num <= 999999)) - { - return ("0" + std::to_string(num)); - } - - if ((num >= 1000000) && (num <= 9999999)) - { - return (std::to_string(num)); - } - - return (std::to_string(num)); -} - -// Pinta el marcador en pantalla usando un objeto texto -void GameDirector::renderScoreBoard() -{ - // Si el jugador esta muerto, no pintes el fondo del marcador, así que pase por encima cuando sale despedido - if (mGame.player->isAlive()) - mGame.scoreBoard->render(); - - if (!mDemo.enabled) - { - // SCORE - mText.white->writeCentered(PLAY_AREA_CENTER_FIRST_QUARTER_X, SCORE_WORD_Y - 6, "SCORE", 0); - mText.white->writeCentered(PLAY_AREA_CENTER_FIRST_QUARTER_X, SCORE_NUMBER_Y - 6, updateScoreText(mGame.score), 0); - - // HI-SCORE - mText.white->writeCentered(PLAY_AREA_CENTER_THIRD_QUARTER_X, HISCORE_WORD_Y - 6, "HI-SCORE", 0); - mText.white->writeCentered(PLAY_AREA_CENTER_THIRD_QUARTER_X, HISCORE_NUMBER_Y - 6, updateScoreText(mGame.hiScore), 0); - - // MULT - mText.white->writeColored(MULTIPLIER_WORD_X, MULTIPLIER_WORD_Y - 6, "MULT", 0, 255, 0); - mText.whiteX2->writeShadowed(PLAY_AREA_CENTER_X - 16, SCORE_WORD_Y + 5, std::to_string(mGame.player->getScoreMultiplier()).substr(0, 1), 0, 192, 0); - mText.white->writeShadowed(PLAY_AREA_CENTER_X - 2, SCORE_WORD_Y + 12, ".", 0, 192, 0); - mText.white->writeShadowed(PLAY_AREA_CENTER_X + 4, SCORE_WORD_Y + 12, std::to_string(mGame.player->getScoreMultiplier()).substr(2, 1), 0, 192, 0); - - // STAGE - mText.white->writeCentered(PLAY_AREA_CENTER_FIRST_QUARTER_X, SCORE_NUMBER_Y + 4, "STAGE " + std::to_string(mGame.stage[mGame.currentStage].number), 0); - - // POWER - mGame.powerMeter->setSpriteClip(256, 184, 40, 8); - mGame.powerMeter->render(); - float percent = (mGame.stage[mGame.currentStage].currentPower * 40.0f) / mGame.stage[mGame.currentStage].powerToComplete; - mGame.powerMeter->setSpriteClip(296, 184, (int)percent, 8); - mGame.powerMeter->render(); - } - else - { - mText.nokia->writeCentered(SCREEN_FIRST_QUARTER_X, SCORE_WORD_Y - 3, "A game by", -1); - mText.nokia->writeCentered(SCREEN_FIRST_QUARTER_X, SCORE_NUMBER_Y, "JailDesigner", -1); - mText.nokia->writeCentered(SCREEN_THIRD_QUARTER_X, HISCORE_WORD_Y - 3, "Intro music by", -1); - mText.nokia->writeCentered(SCREEN_THIRD_QUARTER_X, HISCORE_NUMBER_Y, "JailDoctor", -1); - } -} - -// Actualiza las variables del jugador -void GameDirector::updatePlayer() -{ - mGame.player->update(); - - // Comprueba la colisión entre el jugador y los globos - if (checkPlayerBalloonCollision()) - { - if (mGame.player->isAlive()) - { - if (mDemo.enabled) - setProgSection(PROG_SECTION_TITLE, TITLE_SECTION_INSTRUCTIONS); - else - killPlayer(); - } - } -} - -// Actualiza las variables de la fase -void GameDirector::updateStage() -{ - if (mGame.stage[mGame.currentStage].currentPower >= mGame.stage[mGame.currentStage].powerToComplete) - { - // Cambio de fase - mGame.currentStage++; - JA_PlaySound(mSound[SOUND_STAGE_CHANGE].sound); - mGame.stageBitmapCounter = 0; - mGame.enemySpeed = BALLOON_SPEED_1; - setBalloonSpeed(mGame.enemySpeed); - mGame.effect.flash = true; - mGame.effect.shake = true; - } - - if (mGame.stageBitmapCounter < STAGE_COUNTER) - { - mGame.stageBitmapCounter++; - } -} - -// Actualiza el estado de muerte -void GameDirector::updateDeath() -{ - if (!mGame.player->isAlive()) - { - if (mGame.deathCounter > 0) - { - mGame.deathCounter--; - if ((mGame.deathCounter == 250) || (mGame.deathCounter == 200) || (mGame.deathCounter == 180) || (mGame.deathCounter == 120) || (mGame.deathCounter == 60)) - { - Uint8 sound = rand() % 4; - switch (sound) - { - case 0: - JA_PlaySound(mSound[SOUND_BUBBLE1].sound, 0); - break; - case 1: - JA_PlaySound(mSound[SOUND_BUBBLE2].sound, 0); - break; - case 2: - JA_PlaySound(mSound[SOUND_BUBBLE3].sound, 0); - break; - case 3: - JA_PlaySound(mSound[SOUND_BUBBLE4].sound, 0); - break; - - default: - break; - } - } - - // Animación - if ((mGame.deathCounter / 5) % 2 == 0) - { - mGame.smartSprite[mGame.deathIndex]->setSpriteClip(0, 0, 24, 24); - } - else - { - mGame.smartSprite[mGame.deathIndex]->setSpriteClip(24, 0, 24, 24); - } - - // Rebote en los laterales - if (mGame.smartSprite[mGame.deathIndex]->getVelX() > 0) - { - if (mGame.smartSprite[mGame.deathIndex]->getPosX() > (SCREEN_WIDTH - mGame.smartSprite[mGame.deathIndex]->getWidth())) - { - mGame.smartSprite[mGame.deathIndex]->setPosX(SCREEN_WIDTH - mGame.smartSprite[mGame.deathIndex]->getWidth()); - mGame.smartSprite[mGame.deathIndex]->setVelX(mGame.smartSprite[mGame.deathIndex]->getVelX() * (-1)); - mGame.smartSprite[mGame.deathIndex]->setDestX(mGame.smartSprite[mGame.deathIndex]->getDestX() * (-1)); - } - } - else - { - if (mGame.smartSprite[mGame.deathIndex]->getPosX() < 0) - { - mGame.smartSprite[mGame.deathIndex]->setPosX(0); - mGame.smartSprite[mGame.deathIndex]->setVelX(mGame.smartSprite[mGame.deathIndex]->getVelX() * (-1)); - mGame.smartSprite[mGame.deathIndex]->setDestX(mGame.smartSprite[mGame.deathIndex]->getDestX() * (-1)); - } - } - } - else - { - mGame.section = GAME_SECTION_GAMEOVER; - } - } -} - -// Renderiza el fade final cuando se acaba la partida -void GameDirector::renderDeathFade() -{ - if (!mGame.player->isAlive() && (mGame.deathCounter < 150)) - { - // 192 / 6 = 32, 6 cuadrados de 32 pixeles - SDL_Rect rect[12]; - Uint8 h = (150 - mGame.deathCounter) / 3; - SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 255); - for (Uint8 i = 0; i < 12; i++) - { - rect[i].x = 0; - rect[i].y = i * 16; - rect[i].w = SCREEN_WIDTH; - if (i == 0) - rect[i].h = h; - else - rect[i].h = std::max(rect[i - 1].h - 3, 0); - SDL_RenderFillRect(mRenderer, &rect[i]); - } - } -} - -// Actualiza los globos -void GameDirector::updateBalloons() -{ - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - mGame.balloon[i]->update(); -} - -// Pinta en pantalla todos los globos activos -void GameDirector::renderBalloons() -{ - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - { - mGame.balloon[i]->render(); - if ((mDebug.enabled) && (mGame.balloon[i]->isPopping() == false)) - mText.white->writeCentered(mGame.balloon[i]->getPosX() + (mGame.balloon[i]->getWidth() / 2), mGame.balloon[i]->getPosY() - 8, std::to_string(i), 0); - } -} - -// Devuelve el primer indice no activo del vector de globos -Uint8 GameDirector::getBalloonFreeIndex() -{ - Uint8 index = 0; - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - if (!mGame.balloon[i]->isEnabled()) - { - index = i; - break; - } - return index; -} - -// Crea un globo nuevo en el vector de globos -Uint8 GameDirector::createNewBalloon(float x, int y, Uint8 kind, float velx, float speed, Uint16 creationtimer, LTexture *texture) -{ - Uint8 index = getBalloonFreeIndex(); - mGame.balloon[index]->init(x, y, kind, velx, speed, creationtimer, texture, mRenderer); - return index; -} - -// Crea una PowerBall -void GameDirector::createPowerBall() -{ - const int 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}; - int posX = x[rand() % 3]; - - mGame.balloon[getBalloonFreeIndex()]->init(posX, posY, POWER_BALL, BALLOON_VELX_POSITIVE * (((rand() % 2) * 2) - 1), mGame.enemySpeed, 100, mTexture[TEXTURE_BALLOON].texture, mRenderer); - mGame.powerBallEabled = true; -} - -// Establece a cero todos los valores del vector de objetos globo -void GameDirector::resetBalloons() -{ - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - { - mGame.balloon[i]->disable(); - } -} - -// Establece la velocidad de los globos -void GameDirector::setBalloonSpeed(float speed) -{ - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - { - if (mGame.balloon[i]->isEnabled()) - mGame.balloon[i]->setSpeed(speed); - } -} - -// Incrementa la velocidad de los globos -void GameDirector::incBalloonSpeed() -{ - if (mGame.enemySpeed == BALLOON_SPEED_1) - mGame.enemySpeed = BALLOON_SPEED_2; - else if (mGame.enemySpeed == BALLOON_SPEED_2) - mGame.enemySpeed = BALLOON_SPEED_3; - else if (mGame.enemySpeed == BALLOON_SPEED_3) - mGame.enemySpeed = BALLOON_SPEED_4; - else if (mGame.enemySpeed == BALLOON_SPEED_4) - mGame.enemySpeed = BALLOON_SPEED_5; - setBalloonSpeed(mGame.enemySpeed); -} - -// Decrementa la velocidad de los globos -void GameDirector::decBalloonSpeed() -{ - if (mGame.enemySpeed == BALLOON_SPEED_5) - mGame.enemySpeed = BALLOON_SPEED_4; - else if (mGame.enemySpeed == BALLOON_SPEED_4) - mGame.enemySpeed = BALLOON_SPEED_3; - else if (mGame.enemySpeed == BALLOON_SPEED_3) - mGame.enemySpeed = BALLOON_SPEED_2; - else if (mGame.enemySpeed == BALLOON_SPEED_2) - mGame.enemySpeed = BALLOON_SPEED_1; - setBalloonSpeed(mGame.enemySpeed); -} - -// Actualiza la velocidad de los globos en funcion del poder acumulado de la fase -void GameDirector::updateBalloonSpeed() -{ - float percent = (float)mGame.stage[mGame.currentStage].currentPower / (float)mGame.stage[mGame.currentStage].powerToComplete; - if (mGame.enemySpeed == BALLOON_SPEED_1) - { - if (percent > 0.2f) - incBalloonSpeed(); - } - else if (mGame.enemySpeed == BALLOON_SPEED_2) - { - if (percent > 0.4f) - incBalloonSpeed(); - } - else if (mGame.enemySpeed == BALLOON_SPEED_3) - { - if (percent > 0.6f) - incBalloonSpeed(); - } - else if (mGame.enemySpeed == BALLOON_SPEED_4) - { - if (percent > 0.8f) - incBalloonSpeed(); - } -} - -// Explosiona un globo. Lo destruye y crea otros dos si es el caso -void GameDirector::popBalloon(Uint8 index) -{ - // Otorga los puntos correspondientes al globo - mGame.player->addScore(Uint32(mGame.balloon[index]->getScore() * mGame.player->getScoreMultiplier())); - setScore(mGame.player->getScore()); - updateHiScore(); - - // Aumenta el poder de la fase - increaseStageCurrentPower(1); - mGame.balloonsPopped++; - - Uint8 kind = mGame.balloon[index]->getKind(); - Uint8 freeIndex = 0; - switch (kind) - { - // Si es del tipo más pequeño, simplemente elimina el globo - case BALLOON_1: - mGame.balloon[index]->pop(); - break; - - case HEXAGON_1: - mGame.balloon[index]->pop(); - break; - - // Si es del tipo PowerBall, destruye todos los globos - case POWER_BALL: - destroyAllBalloons(); - mGame.powerBallEabled = false; - break; - - // En cualquier otro caso, crea dos globos de un tipo inferior - default: - freeIndex = getBalloonFreeIndex(); - mGame.balloon[freeIndex]->init(0, mGame.balloon[index]->getPosY(), mGame.balloon[index]->getKind() - 1, BALLOON_VELX_NEGATIVE, mGame.enemySpeed, 0, mTexture[TEXTURE_BALLOON].texture, mRenderer); - mGame.balloon[freeIndex]->allignTo(mGame.balloon[index]->getPosX() + (mGame.balloon[index]->getWidth() / 2)); - if (mGame.balloon[freeIndex]->getClass() == BALLOON_CLASS) - mGame.balloon[freeIndex]->setVelY(-2.50f); - else if (mGame.balloon[freeIndex]->getClass() == HEXAGON_CLASS) - mGame.balloon[freeIndex]->setVelY(BALLOON_VELX_NEGATIVE); - - freeIndex = getBalloonFreeIndex(); - mGame.balloon[freeIndex]->init(0, mGame.balloon[index]->getPosY(), mGame.balloon[index]->getKind() - 1, BALLOON_VELX_POSITIVE, mGame.enemySpeed, 0, mTexture[TEXTURE_BALLOON].texture, mRenderer); - mGame.balloon[freeIndex]->allignTo(mGame.balloon[index]->getPosX() + (mGame.balloon[index]->getWidth() / 2)); - if (mGame.balloon[freeIndex]->getClass() == BALLOON_CLASS) - mGame.balloon[freeIndex]->setVelY(-2.50f); - else if (mGame.balloon[freeIndex]->getClass() == HEXAGON_CLASS) - mGame.balloon[freeIndex]->setVelY(BALLOON_VELX_NEGATIVE); - - // Elimina el globo - mGame.balloon[index]->pop(); - break; - } - - // Recalcula el nivel de amenaza - setMenace(); -} - -// Explosiona un globo. Lo destruye -void GameDirector::destroyBalloon(Uint8 index) -{ - 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 (mGame.balloon[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 - mGame.player->addScore(Uint32(score * mGame.player->getScoreMultiplier())); - setScore(mGame.player->getScore()); - updateHiScore(); - - // Aumenta el poder de la fase - increaseStageCurrentPower(power); - mGame.balloonsPopped += power; - - // Destruye el globo - mGame.balloon[index]->pop(); - - // Recalcula el nivel de amenaza - setMenace(); -} - -// Explosiona todos los globos -void GameDirector::popAllBalloons() -{ - /* - int candidate[MAX_BALLOONS]; - Uint8 j = 0; - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - { - if ((mGame.balloon[i]->isEnabled()) && (!mGame.balloon[i]->isPopping()) && (!mGame.balloon[i]->isBeingCreated())) - candidate[j] = i; - else - candidate[j] = -1; - j++; - } - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - if (candidate[i] >= 0) - popBalloon(i); - */ - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - if ((mGame.balloon[i]->isEnabled()) && (!mGame.balloon[i]->isPopping()) && (!mGame.balloon[i]->isBeingCreated())) - popBalloon(i); - - JA_PlaySound(mSound[SOUND_BALLOON].sound); -} - -// Destruye todos los globos -void GameDirector::destroyAllBalloons() -{ - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - if ((mGame.balloon[i]->isEnabled()) && (!mGame.balloon[i]->isPopping()) && (!mGame.balloon[i]->isBeingCreated())) - destroyBalloon(i); - - JA_PlaySound(mSound[SOUND_POWERBALL].sound); - mGame.effect.flash = true; - mGame.effect.shake = true; -} - -// Detiene todos los globos -void GameDirector::stopAllBalloons(Uint16 time) -{ - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - if (mGame.balloon[i]->isEnabled()) - { - mGame.balloon[i]->setStop(true); - mGame.balloon[i]->setStoppedTimer(time); - } -} - -// Pone en marcha todos los globos -void GameDirector::startAllBalloons() -{ - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - if ((mGame.balloon[i]->isEnabled()) && (!mGame.balloon[i]->isBeingCreated())) - { - mGame.balloon[i]->setStop(false); - mGame.balloon[i]->setStoppedTimer(0); - } -} - -// Obtiene el numero de globos activos -Uint8 GameDirector::countBalloons() -{ - Uint8 num = 0; - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - if (mGame.balloon[i]->isEnabled()) - if (!mGame.balloon[i]->isPopping()) - num++; - return num; -} - -// Comprueba la colisión entre el jugador y los globos activos -bool GameDirector::checkPlayerBalloonCollision() - -{ - bool result = false; - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - { - if ((mGame.balloon[i]->isEnabled()) && !(mGame.balloon[i]->isStopped()) && !(mGame.balloon[i]->isInvulnerable())) - if (checkCollision(mGame.player->getCollider(), mGame.balloon[i]->getCollider())) - { - result = true; - break; - } - } - return result; -} - -// Comprueba la colisión entre el jugador y los items -void GameDirector::checkPlayerItemCollision() -{ - if (mGame.player->isAlive()) - for (Uint8 i = 0; i < MAX_ITEMS; i++) - { - if (mGame.item[i]->isEnabled()) - { - if (checkCollision(mGame.player->getCollider(), mGame.item[i]->getCollider())) - { - switch (mGame.item[i]->getClass()) - { - case ITEM_POINTS_1_DISK: - mGame.player->addScore(1000); - setScore(mGame.player->getScore()); - updateHiScore(); - createItemScoreSprite(mGame.item[i]->getPosX() + (mGame.item[i]->getWidth() / 2) - (mGame._1000Bitmap->getWidth() / 2), mGame.player->getPosY(), mGame._1000Bitmap); - JA_PlaySound(mSound[SOUND_ITEM_PICKUP].sound); - break; - case ITEM_POINTS_2_GAVINA: - mGame.player->addScore(2500); - setScore(mGame.player->getScore()); - updateHiScore(); - createItemScoreSprite(mGame.item[i]->getPosX() + (mGame.item[i]->getWidth() / 2) - (mGame._2500Bitmap->getWidth() / 2), mGame.player->getPosY(), mGame._2500Bitmap); - JA_PlaySound(mSound[SOUND_ITEM_PICKUP].sound); - break; - case ITEM_POINTS_3_PACMAR: - mGame.player->addScore(5000); - setScore(mGame.player->getScore()); - updateHiScore(); - createItemScoreSprite(mGame.item[i]->getPosX() + (mGame.item[i]->getWidth() / 2) - (mGame._5000Bitmap->getWidth() / 2), mGame.player->getPosY(), mGame._5000Bitmap); - JA_PlaySound(mSound[SOUND_ITEM_PICKUP].sound); - break; - case ITEM_CLOCK: - enableTimeStopItem(); - JA_PlaySound(mSound[SOUND_ITEM_PICKUP].sound); - break; - case ITEM_TNT: - popAllBalloons(); - setExplosionTime(true); - JA_PlaySound(mSound[SOUND_TITLE].sound); - break; - case ITEM_COFFEE: - mGame.player->giveExtraHit(); - JA_PlaySound(mSound[SOUND_ITEM_PICKUP].sound); - break; - - default: - break; - } - mGame.item[i]->erase(); - } - } - } -} - -// Comprueba y procesa la colisión entre las balas y los globos -void GameDirector::checkBulletBalloonCollision() -{ - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - for (Uint8 j = 0; j < MAX_BULLETS; j++) - if (mGame.balloon[i]->isEnabled() && (!mGame.balloon[i]->isInvulnerable()) && mGame.bullet[j]->isActive()) - if (checkCollision(mGame.balloon[i]->getCollider(), mGame.bullet[j]->getCollider())) - { - mGame.player->incScoreMultiplier(); - popBalloon(i); - if (!mDemo.enabled) - JA_PlaySound(mSound[SOUND_BALLOON].sound); - mGame.bullet[j]->erase(); - setMenace(); - Uint8 droppeditem = dropItem(); - if ((droppeditem != NO_KIND) && !(mDemo.enabled) && !(mDemo.recording)) - { - /*if (droppeditem == ITEM_POWER_BALL) - { - createPowerBall(); - } - else*/ - { - createItem(mGame.balloon[i]->getPosX(), mGame.balloon[i]->getPosY(), droppeditem); - JA_PlaySound(mSound[SOUND_ITEM_DROP].sound); - } - } - break; - } -} - -// Mueve las balas activas -void GameDirector::moveBullets() -{ - for (Uint8 i = 0; i < MAX_BULLETS; i++) - { - if (mGame.bullet[i]->isActive()) - { - if (mGame.bullet[i]->move() == MSG_BULLET_OUT) - { - mGame.player->decScoreMultiplier(); - } - } - } -} - -// Pinta las balas activas -void GameDirector::renderBullets() -{ - for (Uint8 i = 0; i < MAX_BULLETS; i++) - { - if (mGame.bullet[i]->isActive()) - { - mGame.bullet[i]->render(); - } - } -} - -// Devuelve el primer indice no activo del vector de balas -Uint8 GameDirector::getBulletFreeIndex() -{ - Uint8 index = 0; - - for (int i = 0; i < MAX_BULLETS; i++) - { - if (mGame.bullet[i]->isActive() == false) - { - index = i; - break; - } - } - - return index; -} - -// Establece a cero todos los valores del vector de objetos bala -void GameDirector::resetBullets() -{ - for (Uint8 i = 0; i < MAX_BULLETS; i++) - { - mGame.bullet[i]->erase(); - } -} - -// Crea un objeto bala -void GameDirector::createBullet(int x, int y, Uint8 kind) -{ - mGame.bullet[getBulletFreeIndex()]->init(x, y, kind, mTexture[TEXTURE_BULLET].texture, mRenderer); -} - -// Actualiza los items -void GameDirector::updateItems() -{ - for (Uint8 i = 0; i < MAX_ITEMS; i++) - { - mGame.item[i]->update(); - } -} - -// Pinta los items activos -void GameDirector::renderItems() -{ - for (Uint8 i = 0; i < MAX_ITEMS; i++) - { - mGame.item[i]->render(); - } -} - -// Devuelve el primer indice no activo del vector de items -Uint8 GameDirector::getItemFreeIndex() -{ - Uint8 index = 0; - - for (int i = 0; i < MAX_ITEMS; i++) - { - if (mGame.item[i]->getClass() == NO_KIND) - { - index = i; - break; - } - } - - return index; -} - -// Establece a cero todos los valores del vector de objetos item -void GameDirector::resetItems() -{ - for (Uint8 i = 0; i < MAX_ITEMS; i++) - { - mGame.item[i]->erase(); - } -} - -// Devuelve un item en función del azar -Uint8 GameDirector::dropItem() -{ - //return ITEM_COFFEE; - - Uint8 luckyNumber = rand() % 99; - Uint8 item = rand() % 6; - switch (item) - { - case 0: - if (luckyNumber < 10) - return ITEM_POINTS_1_DISK; - break; - case 1: - if (luckyNumber < 6) - return ITEM_POINTS_2_GAVINA; - break; - case 2: - if (luckyNumber < 3) - return ITEM_POINTS_3_PACMAR; - break; - case 3: - if (luckyNumber < 5) - return ITEM_CLOCK; - break; - case 4: - if (luckyNumber < 5) - return NO_KIND; - break; - case 5: - if (luckyNumber < 5) - return ITEM_COFFEE; - break; - /*case 6: - if (luckyNumber < 5) - if (countBalloons() > 10) - if (!mGame.powerBallEabled) - return ITEM_POWER_BALL; - break;*/ - default: - break; - } - return NO_KIND; -} - -// Crea un objeto item -void GameDirector::createItem(int x, int y, Uint8 kind) -{ - mGame.item[getItemFreeIndex()]->init(kind, x, y, mTexture[TEXTURE_ITEMS].texture, mRenderer); -} - -// Crea un objeto SmartSprite para mostrar la puntuación al coger un objeto -void GameDirector::createItemScoreSprite(int x, int y, SmartSprite *sprite) -{ - Uint8 index = getSmartSpriteFreeIndex(); - *mGame.smartSprite[index] = *sprite; - mGame.smartSprite[index]->setPosX(x); - mGame.smartSprite[index]->setPosY(y); - mGame.smartSprite[index]->setDestX(x); - mGame.smartSprite[index]->setDestY(y - 15); - mGame.smartSprite[index]->setEnabled(true); - mGame.smartSprite[index]->setEnabledTimer(100); -} - -// Crea un objeto de bonus en función del azar -void GameDirector::dropBonus() -{ -} - -// Dibuja el efecto de flash -void GameDirector::renderFlashEffect() -{ - if (mGame.effect.flash) - { - // Pantallazo blanco - SDL_SetRenderDrawColor(mRenderer, 0xFF, 0xFF, 0xFF, 0xFF); - SDL_RenderClear(mRenderer); - - mGame.effect.flash = false; - } -} - -// Actualiza el efecto de agitar la pantalla -void GameDirector::updateShakeEffect() -{ - if (mGame.effect.shake) - { - if (mGame.effect.shakeCounter > 0) - mGame.effect.shakeCounter--; - else - mGame.effect.shake = false; - } -} - -// Crea un SmartSprite para arrojar el item café al recibir un impacto -void GameDirector::throwCoffee(int x, int y) -{ - Uint8 index = getSmartSpriteFreeIndex(); - mGame.smartSprite[index]->init(mTexture[TEXTURE_ITEMS].texture, mRenderer); - mGame.smartSprite[index]->setPosX(x - 8); - mGame.smartSprite[index]->setPosY(y - 8); - mGame.smartSprite[index]->setWidth(16); - mGame.smartSprite[index]->setHeight(16); - mGame.smartSprite[index]->setVelX(-1.0f + ((rand() % 5) * 0.5f)); - mGame.smartSprite[index]->setVelY(-4.0f); - mGame.smartSprite[index]->setAccelX(0.0f); - mGame.smartSprite[index]->setAccelY(0.2f); - mGame.smartSprite[index]->setDestX(x + (mGame.smartSprite[index]->getVelX() * 50)); - mGame.smartSprite[index]->setDestY(SCREEN_HEIGHT + 1); - mGame.smartSprite[index]->setEnabled(true); - mGame.smartSprite[index]->setEnabledTimer(1); - mGame.smartSprite[index]->setSpriteClip(80, 16, 16, 16); - mGame.smartSprite[index]->setRotate(true); - mGame.smartSprite[index]->setRotateSpeed(10); - mGame.smartSprite[index]->setRotateAmount(90.0); -} - -// Crea un SmartSprite para arrojar el item café al recibir un impacto -void GameDirector::throwPlayer(int x, int y) -{ - int sentit = ((rand() % 2) ? 1 : -1); - mGame.deathIndex = getSmartSpriteFreeIndex(); - mGame.smartSprite[mGame.deathIndex]->init(mTexture[TEXTURE_PLAYER_DEATH].texture, mRenderer); - mGame.smartSprite[mGame.deathIndex]->setPosX(x); - mGame.smartSprite[mGame.deathIndex]->setPosY(y); - mGame.smartSprite[mGame.deathIndex]->setWidth(24); - mGame.smartSprite[mGame.deathIndex]->setHeight(24); - mGame.smartSprite[mGame.deathIndex]->setVelX(2.0f * sentit); - mGame.smartSprite[mGame.deathIndex]->setVelY(-5.0f); - mGame.smartSprite[mGame.deathIndex]->setAccelX(0.0f); - mGame.smartSprite[mGame.deathIndex]->setAccelY(0.2f); - mGame.smartSprite[mGame.deathIndex]->setDestX(SCREEN_WIDTH * sentit); - mGame.smartSprite[mGame.deathIndex]->setDestY(SCREEN_HEIGHT + 1); - mGame.smartSprite[mGame.deathIndex]->setEnabled(true); - mGame.smartSprite[mGame.deathIndex]->setEnabledTimer(1); - mGame.smartSprite[mGame.deathIndex]->setSpriteClip(0, 0, 24, 24); -} - -// Actualiza los SmartSprites -void GameDirector::updateSmartSprites() -{ - for (int i = 0; i < MAX_SMART_SPRITES; i++) - { - mGame.smartSprite[i]->update(); - } -} - -// Pinta los SmartSprites activos -void GameDirector::renderSmartSprites() -{ - for (int i = 0; i < MAX_SMART_SPRITES; i++) - { - mGame.smartSprite[i]->render(); - } -} - -// Devuelve el primer indice no activo del vector de SmartSprites -Uint8 GameDirector::getSmartSpriteFreeIndex() -{ - Uint8 index = 0; - - for (int i = 0; i < MAX_SMART_SPRITES; i++) - { - if (mGame.smartSprite[i]->isEnabled() == false) - { - index = i; - break; - } - } - - return index; -} - -// Establece a cero todos los valores del vector de objetos SmafrtSprite -void GameDirector::resetSmartSprites() -{ - for (Uint8 i = 0; i < MAX_SMART_SPRITES; i++) - { - mGame.smartSprite[i]->erase(); - } -} - -#ifndef UNUSED -// Deshabilita todas las gotas de café -void GameDirector::resetCoffeeDrops() -{ - for (Uint8 i = 0; i < MAX_COFFEE_DROPS; i++) - { - mCoffeeDrop[i]->disable(); - } -} - -// Actualiza las gotas de cafe -void GameDirector::updateCoffeeDrops() -{ - for (Uint8 i = 0; i < MAX_COFFEE_DROPS; i++) - { - mCoffeeDrop[i]->update(); - } -} - -// Dibuja las gotas de cafe -void GameDirector::renderCoffeeDrops() -{ - for (Uint8 i = 0; i < MAX_COFFEE_DROPS; i++) - { - mCoffeeDrop[i]->render(); - } -} - -// Devuelve el primer indice libre del vector de CoffeeDrops -Uint8 GameDirector::getCoffeDropFreeIndex() -{ - Uint8 index = 0; - - for (Uint8 i = 0; i < MAX_COFFEE_DROPS; i++) - { - if (!(mCoffeeDrop[i]->isEnabled())) - { - index = i; - break; - } - } - return index; -} - -// Crea un numero de gotas de cafe -void GameDirector::createCoffeDrops(Uint8 num, int x, int y) -{ - for (Uint8 i = 0; i < num; i++) - { - mCoffeeDrop[getCoffeDropFreeIndex()]->init(mTexture[TEXTURE_GAME_BG].texture, mRenderer, x, y, ((rand() % 7) * 0.5f) - 1.5f, (rand() % 7) * (-0.5f) + 1.0f, PLAY_AREA_BOTTOM); - } -} -#endif - -// Acciones a realizar cuando el jugador muere -void GameDirector::killPlayer() -{ - if (!mGame.player->isInvulnerable()) - { - if (mGame.player->hasExtraHit()) - { - mGame.player->removeExtraHit(); - throwCoffee(mGame.player->getPosX() + (mGame.player->getWidth() / 2), mGame.player->getPosY() + (mGame.player->getHeight() / 2)); - JA_PlaySound(mSound[SOUND_COFFEE_OUT].sound); - } - else - { - stopAllBalloons(10); // 5000 - JA_StopMusic(); - JA_PlaySound(mSound[SOUND_PLAYER_COLLISION].sound); - shakeScreen(); - SDL_Delay(500); // 1000 - JA_PlaySound(mSound[SOUND_COFFEE_OUT].sound); - throwPlayer(mGame.player->getPosX(), mGame.player->getPosY()); - mGame.player->setAlive(false); - } - } -} - -// Obtiene el valor de la variable -Uint8 GameDirector::getSubsection() -{ - return mProg.subsection; -} - -// Calcula y establece el valor de amenaza en funcion de los globos activos -void GameDirector::setMenace() -{ - mGame.menaceCurrent = 0; - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - if (mGame.balloon[i]->isEnabled()) - mGame.menaceCurrent += mGame.balloon[i]->getMenace(); -} - -// Obtiene el valor de la variable -Uint8 GameDirector::getMenace() -{ - return mGame.menaceCurrent; -} - -// Establece el valor de la variable -void GameDirector::setTimeStopped(bool value) -{ - mGame.timeStopped = value; -} - -// Obtiene el valor de la variable -bool GameDirector::isTimeStopped() -{ - return mGame.timeStopped; -} - -// Establece el valor de la variable -void GameDirector::setTimeStoppedCounter(Uint16 value) -{ - mGame.timeStoppedCounter = value; -} - -// Incrementa el valor de la variable -void GameDirector::incTimeStoppedCounter(Uint16 value) -{ - mGame.timeStoppedCounter += value; -} - -// Actualiza y comprueba el valor de la variable -void GameDirector::updateTimeStoppedCounter() -{ - if (isTimeStopped()) - { - if (mGame.timeStoppedCounter > 0) - { - mGame.timeStoppedCounter--; - stopAllBalloons(TIME_STOPPED_COUNTER); - } - else - { - disableTimeStopItem(); - } - } -} - -// Establece el valor de la variable -void GameDirector::setExplosionTime(bool value) -{ - mGame.explosionTime = value; -} - -// Obtiene el valor de la variable -bool GameDirector::isExplosionTime() -{ - return mGame.explosionTime; -} - -// Establece el valor de la variable -void GameDirector::setRemainingExplosions(Uint8 value) -{ - mGame.remainingExplosions = value; -} - -// Actualiza y comprueba el valor de la variable -void GameDirector::updateRemainingExplosionsCounter() -{ - if (isExplosionTime()) - { - if (mGame.remainingExplosionsCounter > 0) - { - --mGame.remainingExplosionsCounter; - } - else if (mGame.remainingExplosions > 0) - { - popAllBalloons(); - --mGame.remainingExplosions; - mGame.remainingExplosionsCounter = REMAINING_EXPLOSIONS_COUNTER; - } - else - { - mGame.explosionTime = false; - mGame.remainingExplosions = REMAINING_EXPLOSIONS; - mGame.remainingExplosionsCounter = REMAINING_EXPLOSIONS_COUNTER; - } - } -} - -// Actualiza la variable EnemyDeployCounter -void GameDirector::updateEnemyDeployCounter() -{ - if (mGame.enemyDeployCounter > 0) - mGame.enemyDeployCounter--; -} - -// Actualiza el campo de juego -void GameDirector::updatePlayField() -{ - // Comprueba el teclado/mando - checkGameInput(); - - // Actualiza las variables del jugador - updatePlayer(); - - // Actualiza el fondo - updateBackground(); - - // Mueve los globos - updateBalloons(); - - // Mueve las balas - moveBullets(); - - // Actualiza los items - updateItems(); - - // Actualiza el valor de mGame.currentStage - updateStage(); - - // Actualiza el estado de muerte - updateDeath(); - - // Actualiza los SmartSprites - updateSmartSprites(); - - // Actualiza los contadores de estado y efectos - updateTimeStoppedCounter(); - updateRemainingExplosionsCounter(); - updateEnemyDeployCounter(); - updateShakeEffect(); - - // Comprueba las colisiones entre globos y balas - checkBulletBalloonCollision(); - - // Comprueba las colisiones entre elk jugador y los items - checkPlayerItemCollision(); - - // Comprueba el nivel de amenaza - updateMenace(); - - // Actualiza la velocidad de los enemigos - updateBalloonSpeed(); -} - -// Actualiza el fondo -void GameDirector::updateBackground() -{ - mGame.clouds1a->move(); - mGame.clouds1b->move(); - mGame.clouds2a->move(); - mGame.clouds2b->move(); - if (mGame.clouds1a->getPosX() < -mGame.clouds1a->getWidth()) - mGame.clouds1a->setPosX(mGame.clouds1a->getWidth()); - if (mGame.clouds1b->getPosX() < -mGame.clouds1b->getWidth()) - mGame.clouds1b->setPosX(mGame.clouds1b->getWidth()); - if (mGame.clouds2a->getPosX() < -mGame.clouds2a->getWidth()) - mGame.clouds2a->setPosX(mGame.clouds2a->getWidth()); - if (mGame.clouds2b->getPosX() < -mGame.clouds2b->getWidth()) - mGame.clouds2b->setPosX(mGame.clouds2b->getWidth()); - mGame.grass->setSpriteClip(256, 85 + (6 * (mGame.counter / 20 % 2)), SCREEN_WIDTH, 6); - if (mGame.effect.shake) - mGame.background->setPosX(((mGame.effect.shakeCounter % 2) * 2) - 1); - else - mGame.background->setPosX(0); -} - -// Dibuja el fondo -void GameDirector::renderBackground() -{ - float gradientNumber = std::min(((float)mGame.balloonsPopped / 900.0f), 3.0f); - float percent = gradientNumber - (int)gradientNumber; - int alpha = std::max((255 - (int)(255 * percent)), 0); - - // Dibuja el gradiente 2 - mGame.gradient->setSpriteClip(mGame.gradientRect[((int)gradientNumber + 1) % 4]); - mGame.gradient->render(); - - // Dibuja el gradiente 1 con una opacidad cada vez menor - mGame.gradient->setSpriteClip(mGame.gradientRect[(int)gradientNumber]); - mTexture[TEXTURE_GAME_BG].texture->setAlpha(alpha); - mGame.gradient->render(); - mTexture[TEXTURE_GAME_BG].texture->setAlpha(255); - - mGame.clouds1a->render(); - mGame.clouds1b->render(); - mGame.clouds2a->render(); - mGame.clouds2b->render(); - - mGame.background->render(); - - mGame.grass->render(); -} - -// Dibuja el campo de juego -void GameDirector::renderPlayField() -{ - renderBackground(); - renderBalloons(); - renderBullets(); - renderItems(); - renderSmartSprites(); - mGame.player->render(); - renderMessages(); - renderDeathFade(); - renderScoreBoard(); - renderFlashEffect(); -} - -// Gestiona el nivel de amenaza -void GameDirector::old_updateMenace() -{ - // Aumenta el nivel de amenaza en función de la puntuación - mGame.menaceThreshold = 7 + (4 * (mGame.score / 10000)); - - // Si el nivel de amenza es inferior al umbral - if (mGame.menaceCurrent < mGame.menaceThreshold) - { - Uint8 index = 0; - - // Obtiene el centro del jugador en el eje X - int x = mGame.player->getPosX() + (mGame.player->getWidth() / 2); - - // Crea un globo sobre el jugador en dirección hacia el centro - if (x < (PLAY_AREA_WIDTH / 2)) - { - index = createNewBalloon(0, PLAY_AREA_TOP + BLOCK - 37, BALLOON_4, BALLOON_VELX_POSITIVE, mGame.enemySpeed, 400, mTexture[TEXTURE_BALLOON].texture); - } - else - { - index = createNewBalloon(0, PLAY_AREA_TOP + BLOCK - 37, BALLOON_4, BALLOON_VELX_NEGATIVE, mGame.enemySpeed, 400, mTexture[TEXTURE_BALLOON].texture); - } - mGame.balloon[index]->allignTo(x); - - // Recalcula el nivel de amenaza con el nuevo globo - setMenace(); - } -} - -// Gestiona el nivel de amenaza -void GameDirector::updateMenace() -{ - float percent = mGame.stage[mGame.currentStage].currentPower / mGame.stage[mGame.currentStage].powerToComplete; - Uint8 difference = mGame.stage[mGame.currentStage].maxMenace - mGame.stage[mGame.currentStage].minMenace; - - // Aumenta el nivel de amenaza en función de la puntuación - mGame.menaceThreshold = mGame.stage[mGame.currentStage].minMenace + (difference * percent); - - // Si el nivel de amenza es inferior al umbral - if (mGame.menaceCurrent < mGame.menaceThreshold) - { - // Crea una formación de enemigos - deployEnemyFormation(); - - // Recalcula el nivel de amenaza con el nuevo globo - setMenace(); - } -} - -// Gestiona las entradas desde el mando de juego -bool GameDirector::checkGameController(Uint8 state) -{ - // No hay mando. Siempre devuelve falso salvo NO_INPUT que siempre es cierto - if (!mGameControllerFound) - { - if (state == NO_INPUT) - return true; - else - return false; - } - - bool success = false; - - switch (state) - { - case NO_INPUT: - success = !checkGameController(INPUT_UP) && !checkGameController(INPUT_DOWN) && !checkGameController(INPUT_LEFT) && !checkGameController(INPUT_RIGHT) && - !checkGameController(INPUT_ACCEPT) && !checkGameController(INPUT_CANCEL) && !checkGameController(INPUT_PAUSE) && - !checkGameController(INPUT_FIRE_UP) && !checkGameController(INPUT_FIRE_LEFT) && !checkGameController(INPUT_FIRE_RIGHT); - break; - case INPUT_UP: - success = (SDL_JoystickGetAxis(mGameController, 1) < -JOYSTICK_DEAD_ZONE) || (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_DPAD_UP)); - break; - case INPUT_DOWN: - success = (SDL_JoystickGetAxis(mGameController, 1) > JOYSTICK_DEAD_ZONE) || (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_DPAD_DOWN)); - break; - case INPUT_LEFT: - success = (SDL_JoystickGetAxis(mGameController, 0) < -JOYSTICK_DEAD_ZONE) || (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_DPAD_LEFT)); - break; - case INPUT_RIGHT: - success = (SDL_JoystickGetAxis(mGameController, 0) > JOYSTICK_DEAD_ZONE) || (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)); - break; - case INPUT_ACCEPT: - success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_B)); - break; - case INPUT_CANCEL: - success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_A)); - break; - case INPUT_PAUSE: - success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_START)); - break; - case INPUT_FIRE_UP: - success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_Y)); - break; - case INPUT_FIRE_LEFT: - success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_X)); - break; - case INPUT_FIRE_RIGHT: - success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_B)); - break; - - default: - break; - } - return success; -} - -// Gestiona la entrada durante el juego -void GameDirector::checkGameInput() -{ - // Obtiene el estado de las teclas pulsadas del teclado - keystates = SDL_GetKeyboardState(NULL); - - mDemo.keys.left = 0; - mDemo.keys.right = 0; - mDemo.keys.noInput = 0; - mDemo.keys.fire = 0; - mDemo.keys.fireLeft = 0; - mDemo.keys.fireRight = 0; - - // Modo Demo activo - if (mDemo.enabled) - { - if (mDemo.dataFile[mDemo.counter].left == 1) - mGame.player->setInput(INPUT_LEFT); - if (mDemo.dataFile[mDemo.counter].right == 1) - mGame.player->setInput(INPUT_RIGHT); - if (mDemo.dataFile[mDemo.counter].noInput == 1) - mGame.player->setInput(NO_INPUT); - if (mDemo.dataFile[mDemo.counter].fire == 1) - if (mGame.player->canFire()) - { - mGame.player->setInput(INPUT_FIRE_UP); - createBullet(mGame.player->getPosX() + (mGame.player->getWidth() / 2) - 4, mGame.player->getPosY() + (mGame.player->getHeight() / 2), BULLET_UP); - mGame.player->setFireCooldown(10); - } - if (mDemo.dataFile[mDemo.counter].fireLeft == 1) - if (mGame.player->canFire()) - { - mGame.player->setInput(INPUT_FIRE_LEFT); - createBullet(mGame.player->getPosX() + (mGame.player->getWidth() / 2) - 4, mGame.player->getPosY() + (mGame.player->getHeight() / 2), BULLET_UP); - mGame.player->setFireCooldown(10); - } - if (mDemo.dataFile[mDemo.counter].fireRight == 1) - if (mGame.player->canFire()) - { - mGame.player->setInput(INPUT_FIRE_RIGHT); - createBullet(mGame.player->getPosX() + (mGame.player->getWidth() / 2) - 4, mGame.player->getPosY() + (mGame.player->getHeight() / 2), BULLET_UP); - mGame.player->setFireCooldown(10); - } - - // Comprobamos la tecla o el botón de pausa/menu - if ((keystates[mProg.keyboard.accept] != 0) || (keystates[mProg.keyboard.cancel] != 0) || (checkGameController(INPUT_PAUSE)) || (checkGameController(INPUT_ACCEPT)) || (checkGameController(INPUT_CANCEL))) - { - setProgSection(PROG_SECTION_TITLE); - } - - if (mDemo.counter < TOTAL_DEMO_DATA) - mDemo.counter++; - else - setProgSection(PROG_SECTION_TITLE, TITLE_SECTION_INSTRUCTIONS); - } - // Modo Demo no activo - else if (mGame.player->isAlive()) - { - // Tecla izquierda o el mando hacia la izquierda - if ((keystates[mProg.keyboard.left] != 0) || (checkGameController(INPUT_LEFT))) - { - mGame.player->setInput(INPUT_LEFT); - mDemo.keys.left = 1; - } - else - { - // Tecla derecha o el mando hacia la derecha - if ((keystates[mProg.keyboard.right] != 0) || (checkGameController(INPUT_RIGHT))) - { - mGame.player->setInput(INPUT_RIGHT); - mDemo.keys.right = 1; - } - else - { - // Ninguna de las dos direcciones pulsadas - mGame.player->setInput(NO_INPUT); - mDemo.keys.noInput = 1; - } - } - // Comprueba la tecla o el botón de disparo central - if ((keystates[mProg.keyboard.fire] != 0) || (checkGameController(INPUT_FIRE_UP))) - { - if (mGame.player->canFire()) - { - mGame.player->setInput(INPUT_FIRE_UP); - createBullet(mGame.player->getPosX() + (mGame.player->getWidth() / 2) - 4, mGame.player->getPosY() + (mGame.player->getHeight() / 2), BULLET_UP); - mGame.player->setFireCooldown(10); - - // Reproduce el sonido de disparo - JA_PlaySound(mSound[SOUND_BULLET].sound); - - mDemo.keys.fire = 1; - } - } - - // Comprueba la tecla o el botón de disparo izquierdo - if ((keystates[mProg.keyboard.fireLeft] != 0) || (checkGameController(INPUT_FIRE_LEFT))) - { - if (mGame.player->canFire()) - { - mGame.player->setInput(INPUT_FIRE_LEFT); - createBullet(mGame.player->getPosX() + (mGame.player->getWidth() / 2) - 4, mGame.player->getPosY() + (mGame.player->getHeight() / 2), BULLET_LEFT); - mGame.player->setFireCooldown(10); - - // Reproduce el sonido de disparo - JA_PlaySound(mSound[SOUND_BULLET].sound); - - mDemo.keys.fireLeft = 1; - } - } - - // Comprueba la tecla o el botón de disparo derecho - if ((keystates[mProg.keyboard.fireRight] != 0) || (checkGameController(INPUT_FIRE_RIGHT))) - { - if (mGame.player->canFire()) - { - mGame.player->setInput(INPUT_FIRE_RIGHT); - createBullet(mGame.player->getPosX() + (mGame.player->getWidth() / 2) - 4, mGame.player->getPosY() + (mGame.player->getHeight() / 2), BULLET_RIGHT); - mGame.player->setFireCooldown(10); - - // Reproduce el sonido de disparo - JA_PlaySound(mSound[SOUND_BULLET].sound); - - mDemo.keys.fireRight = 1; - } - } - - // Para la pausa actuaremos cuando se suelte la tecla de pausa - // Comprueba la tecla o el botón de pausa/menu y su buffer - if (((keystates[mProg.keyboard.pause] != 0) || (checkGameController(INPUT_PAUSE))) && (mProg.keyboardBuffer.pause == 0)) //|| ((mGameControllerFound) && (SDL_JoystickGetButton(mGameController, BUTTON_START)))) - { - // Se acaba de pulsar la tecla. Lo anotamos en su buffer - mProg.keyboardBuffer.pause = 1; - } - else - { - // Aqui sigue la tecla pulsada, mantenemos el buffer activo - if (((keystates[mProg.keyboard.pause] != 0) || (checkGameController(INPUT_PAUSE))) && (mProg.keyboardBuffer.pause != 0)) - { - mProg.keyboardBuffer.pause = 1; - } - else - { - // Se ha soltado la tecla, procedemos a ejecutar la accion - if (((keystates[mProg.keyboard.pause] == 0) || (!checkGameController(INPUT_PAUSE))) && (mProg.keyboardBuffer.pause != 0)) - { - mGame.section = GAME_SECTION_PAUSE; - - if (JA_GetMusicState() == JA_MUSIC_PLAYING) - { - JA_PauseMusic(); - } - - mProg.keyboardBuffer.pause = 0; - } - } - } - - if (mDemo.counter < TOTAL_DEMO_DATA) - { - if (mDemo.recording) - { - mDemo.dataFile[mDemo.counter] = mDemo.keys; - } - mDemo.counter++; - } - else if (mDemo.recording) - { - mProg.quit = true; - ; - } - } -} - -// Gestiona la entrada de teclado y mando durante el menu -void GameDirector::checkMenuInput(Menu *menu) -{ - // Obtiene el estado de las teclas pulsadas del teclado - keystates = SDL_GetKeyboardState(NULL); - - if (!mMenu.keyPressed) - { - // Tecla arriba o el mando hacia arriba - if ((keystates[mProg.keyboard.up] != 0) || (checkGameController(INPUT_UP))) - { - if (menu->checkInput(INPUT_UP)) - { - mMenu.keyPressed = true; - JA_PlaySound(mSound[SOUND_MENU_MOVE].sound); - } - } - - // Tecla abajo o el mando hacia abajo - if ((keystates[mProg.keyboard.down] != 0) || (checkGameController(INPUT_DOWN))) - { - if (menu->checkInput(INPUT_DOWN)) - { - mMenu.keyPressed = true; - JA_PlaySound(mSound[SOUND_MENU_MOVE].sound); - } - } - - // Tecla o el botón de aceptar - if ((keystates[mProg.keyboard.accept] != 0) || (checkGameController(INPUT_ACCEPT))) - { - menu->checkInput(INPUT_ACCEPT); - mMenu.keyPressed = true; - } - - // Tecla o el botón de cancelar - if ((keystates[mProg.keyboard.cancel] != 0) || (checkGameController(INPUT_CANCEL))) - { - menu->checkInput(INPUT_CANCEL); - mMenu.keyPressed = true; - } - } - - // Ningún botón, libera la variable - if ((keystates[mProg.keyboard.up] == 0) && (keystates[mProg.keyboard.down] == 0) && (keystates[mProg.keyboard.accept] == 0) && - (keystates[mProg.keyboard.cancel] == 0) && (checkGameController(NO_INPUT))) - { - mMenu.keyPressed = false; - } -} - -// Obtiene el valor de la variable -Uint8 GameDirector::getProgSection() -{ - return mProg.section; -} - -// Establece el valor de la variable -void GameDirector::setProgSection(Uint8 section, Uint8 subsection) -{ - mProg.section = section; - mProg.subsection = subsection; -} - -// Pinta una transición en pantalla -void GameDirector::renderFade(Uint8 index) -{ - SDL_Rect rect1; - SDL_Rect rect2; - Uint8 R, G, B; - - // Copia el backbuffer al renderer - SDL_SetRenderTarget(mRenderer, NULL); - SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL); - SDL_RenderPresent(mRenderer); - SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL); - SDL_RenderPresent(mRenderer); - - switch (index) - { - case 0: - rect1 = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT}; - R = 0x27; - G = 0x27; - B = 0x36; - - for (int i = 0; i < 256; i += 4) - { - // Dibujamos sobre el renderizador - SDL_SetRenderTarget(mRenderer, NULL); - - // Copia el backbuffer con la imagen que había al renderizador - SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL); - - SDL_SetRenderDrawColor(mRenderer, R, G, B, i); - SDL_RenderFillRect(mRenderer, &rect1); - - // Vuelca el renderizador en pantalla - SDL_RenderPresent(mRenderer); - } - - // Deja todos los bufferes del mismo color - SDL_SetRenderTarget(mRenderer, mBackbuffer); - SDL_SetRenderDrawColor(mRenderer, R, G, B, 255); - SDL_RenderClear(mRenderer); - - SDL_SetRenderTarget(mRenderer, NULL); - SDL_SetRenderDrawColor(mRenderer, R, G, B, 255); - SDL_RenderClear(mRenderer); - break; - - case 1: - rect1 = {0, 0, SCREEN_WIDTH, 0}; - rect2 = {0, 0, SCREEN_WIDTH, 0}; - R = 0x27; - G = 0x27; - B = 0x36; - - SDL_SetRenderDrawColor(mRenderer, R, G, B, 64); - - for (Uint16 i = 0; i < (SCREEN_HEIGHT / 2); i += 4) - { - // Dibujamos sobre el backbuffer - SDL_SetRenderTarget(mRenderer, mBackbuffer); - - rect1.h = rect2.h = i; - rect2.y = SCREEN_HEIGHT - (i); - - SDL_RenderFillRect(mRenderer, &rect1); - SDL_RenderFillRect(mRenderer, &rect2); - - // Volvemos a usar el renderizador de forma normal - SDL_SetRenderTarget(mRenderer, NULL); - - // Copiamos el backbuffer al renderizador - SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL); - - // Volcamos el renderizador en pantalla - SDL_RenderPresent(mRenderer); - } - - rect1 = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT}; - - for (Uint8 i = 0; i < 32; i++) - { - // Dibujamos sobre el backbuffer - SDL_SetRenderTarget(mRenderer, mBackbuffer); - SDL_RenderFillRect(mRenderer, &rect1); - - // Volvemos a usar el renderizador de forma normal - SDL_SetRenderTarget(mRenderer, NULL); - - // Copiamos el backbuffer al renderizador - SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL); - - // Volcamos el renderizador en pantalla - SDL_RenderPresent(mRenderer); - } - break; - - case 2: - rect1 = {0, 0, 32, 32}; - - for (Uint16 i = 0; i < 50; i++) - { - // Crea un color al azar - R = 255 * (rand() % 2); - G = 255 * (rand() % 2); - B = 255 * (rand() % 2); - SDL_SetRenderDrawColor(mRenderer, R, G, B, 64); - - // Dibujamos sobre el backbuffer - SDL_SetRenderTarget(mRenderer, mBackbuffer); - - rect1.x = rand() % (SCREEN_WIDTH - rect1.w); - rect1.y = rand() % (SCREEN_HEIGHT - rect1.h); - SDL_RenderFillRect(mRenderer, &rect1); - - // Volvemos a usar el renderizador de forma normal - SDL_SetRenderTarget(mRenderer, NULL); - - // Copiamos el backbuffer al renderizador - SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL); - - // Volcamos el renderizador en pantalla - SDL_RenderPresent(mRenderer); - SDL_Delay(100); - } - break; - - default: - break; - } -} - -// Pinta diferentes mensajes en la pantalla -void GameDirector::renderMessages() -{ - // GetReady - if ((mGame.counter < STAGE_COUNTER) && (!mDemo.enabled)) - { - mGame.getReadyBitmap->setPosX((int)mGame.getReadyBitmapPath[mGame.counter]); - mGame.getReadyBitmap->render(); - } - - // Time Stopped - if (mGame.timeStopped) - { - if ((mGame.timeStoppedCounter > 100) || (mGame.timeStoppedCounter % 10 > 4)) - { - mText.black->writeCentered(PLAY_AREA_CENTER_X + 1, PLAY_AREA_FIRST_QUARTER_Y + 1, "Time Stopped: " + std::to_string(mGame.timeStoppedCounter / 10)); - mText.white->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_FIRST_QUARTER_Y, "Time Stopped: " + std::to_string(mGame.timeStoppedCounter / 10)); - } - - if (mGame.timeStoppedCounter > 100) - { - if (mGame.timeStoppedCounter % 30 == 0) - JA_PlaySound(mSound[SOUND_CLOCK].sound, false); - } - else - { - if (mGame.timeStoppedCounter % 15 == 0) - JA_PlaySound(mSound[SOUND_CLOCK].sound, false); - } - } - - // D E M O - if (mDemo.enabled) - { - if (mDemo.counter % 30 > 14) - { - mText.blackX2->writeCentered(PLAY_AREA_CENTER_X + 2, PLAY_AREA_FIRST_QUARTER_Y + 2, "D E M O"); - mText.whiteX2->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_FIRST_QUARTER_Y, "D E M O"); - } - } - - // STAGE NUMBER - if (mGame.stageBitmapCounter < STAGE_COUNTER) - { - mText.blackX2->writeCentered(PLAY_AREA_CENTER_X + 2, mGame.stageBitmapPath[mGame.stageBitmapCounter] + 2, "STAGE " + std::to_string(mGame.stage[mGame.currentStage].number)); - mText.whiteX2->writeCentered(PLAY_AREA_CENTER_X, mGame.stageBitmapPath[mGame.stageBitmapCounter], "STAGE " + std::to_string(mGame.stage[mGame.currentStage].number)); - } -} - -// Habilita el efecto del item de detener el tiempo -void GameDirector::enableTimeStopItem() -{ - stopAllBalloons(TIME_STOPPED_COUNTER); - setTimeStopped(true); - incTimeStoppedCounter(TIME_STOPPED_COUNTER); - if (JA_GetMusicState() == JA_MUSIC_PLAYING) - { - JA_PauseMusic(); - } -} - -// Deshabilita el efecto del item de detener el tiempo -void GameDirector::disableTimeStopItem() -{ - mGame.timeStopped = false; - setTimeStoppedCounter(0); - //mGame.timeStoppedCounter = TIME_STOPPED_COUNTER; - startAllBalloons(); - if (JA_GetMusicState() == JA_MUSIC_PAUSED) - { - JA_ResumeMusic(); - } -} - -// Cambia el valor de la variable de modo de pantalla completa -void GameDirector::changeFullScreenMode() -{ - switch (mOptions.fullScreenMode) - { - case 0: - mOptions.fullScreenMode = SDL_WINDOW_FULLSCREEN; - break; - case SDL_WINDOW_FULLSCREEN: - mOptions.fullScreenMode = SDL_WINDOW_FULLSCREEN_DESKTOP; - break; - case SDL_WINDOW_FULLSCREEN_DESKTOP: - mOptions.fullScreenMode = 0; - break; - - default: - mOptions.fullScreenMode = 0; - break; - } -} - -// Actualiza los elementos del menu de opciones -void GameDirector::updateOptionsMenu() -{ - switch (mOptions.fullScreenMode) - { - case 0: - mMenu.options->setItemCaption(0, "WINDOWED"); - break; - case SDL_WINDOW_FULLSCREEN: - mMenu.options->setItemCaption(0, "FULLSCREEN"); - break; - case SDL_WINDOW_FULLSCREEN_DESKTOP: - mMenu.options->setItemCaption(0, "FAKE FULLSCREEN"); - break; - - default: - mMenu.options->setItemCaption(0, "WINDOWED"); - break; - } - mMenu.options->setItemCaption(1, "WINDOWS SIZE " + std::to_string(mOptions.windowSize)); - mMenu.options->centerMenu(SCREEN_CENTER_X); - mMenu.options->centerMenuElements(); -} - -// Agita la pantalla -void GameDirector::shakeScreen() -{ - int v[] = {-1, 1, -1, 1, -1, 1, -1, 0}; - for (Uint8 n = 0; n < 8; n++) - { - // Limpia la pantalla - SDL_SetRenderDrawColor(mRenderer, 0x00, 0x00, 0x00, 0xFF); - SDL_RenderClear(mRenderer); - - // Dibuja los objetos - mGame.background->setPosX(0); - mGame.background->setWidth(1); - mGame.background->setSpriteClip(0, 0, 1, 192); - renderBackground(); - - mGame.background->setPosX(255); - mGame.background->setSpriteClip(255, 0, 1, 192); - mGame.background->render(); - - mGame.background->setPosX(v[n]); - mGame.background->setWidth(256); - mGame.background->setSpriteClip(0, 0, 256, 192); - mGame.background->render(); - - mGame.grass->render(); - renderBalloons(); - renderBullets(); - renderItems(); - mGame.player->render(); - renderScoreBoard(); - - // Actualiza la pantalla - SDL_RenderPresent(mRenderer); - SDL_Delay(50); - } -} - -// Agita la pantalla -void GameDirector::shakeScreen2() -{ - int v[] = {-1, 1, -1, 1, -1, 1, -1, 0}; - for (Uint8 n = 0; n < 8; n++) - { - // Limpia la pantalla - SDL_SetRenderDrawColor(mRenderer, 0x00, 0x00, 0x00, 0xFF); - SDL_RenderClear(mRenderer); - - // Dibuja los objetos - mGame.background->setPosX(0); - mGame.background->setWidth(1); - mGame.background->setSpriteClip(0, 0, 1, 192); - renderBackground(); - - mGame.background->setPosX(255); - mGame.background->setSpriteClip(255, 0, 1, 192); - mGame.background->render(); - - mGame.background->setPosX(v[n]); - mGame.background->setWidth(256); - mGame.background->setSpriteClip(0, 0, 256, 192); - mGame.background->render(); - - mGame.grass->render(); - renderBalloons(); - renderBullets(); - renderItems(); - mGame.player->render(); - renderScoreBoard(); - - // Actualiza la pantalla - SDL_RenderPresent(mRenderer); - SDL_Delay(50); - } -} - -// Bucle para el logo del juego -void GameDirector::runLogo() -{ - initLogo(); - - while ((mProg.section == PROG_SECTION_LOGO) && (!exit())) - { - // Comprueba los eventos que hay en la cola - while (SDL_PollEvent(mEventHandler) != 0) - { - // Evento de salida de la aplicación - if (mEventHandler->type == SDL_QUIT) - { - mProg.quit = true; - break; - } - - // Cualquier tecla pulsada - if ((mEventHandler->type == SDL_KEYDOWN) || (mEventHandler->type == SDL_JOYBUTTONDOWN)) - { - setProgSection(PROG_SECTION_TITLE); - } - } - - // Cambia el destino donde se pinta todo - SDL_SetRenderTarget(mRenderer, mBackbuffer); - - // Limpia el destino - SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 255); - SDL_RenderClear(mRenderer); - - // Dibuja los objetos - mLogo.sprite->render(); - - // Dibuja el fade - if (mLogo.counter >= 200) - { - SDL_Rect rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT}; - Uint16 alpha = mLogo.counter - 200; - if (alpha < 256) - { - SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, alpha); - } - else - { - SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 255); // alpha - 0 trans, 255 opaco - } - SDL_RenderFillRect(mRenderer, &rect); - } - - // Vuelve a usar el renderizador como destino - SDL_SetRenderTarget(mRenderer, NULL); - - // Copia el backbufer al renderizador - SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL); - - // Actualiza la pantalla - SDL_RenderPresent(mRenderer); - - // Comprueba si ha terminado el logo - if (SDL_GetTicks() - mProg.ticks > mProg.ticksSpeed) - { - // Actualiza el contador de ticks - mProg.ticks = SDL_GetTicks(); - - if (mLogo.counter == 0) - { - if (JA_GetMusicState() == JA_MUSIC_PLAYING) - { - JA_StopMusic(); - } - } - - if (mLogo.counter == 500) // minimo 200 + 255 - { - mLogo.counter = 0; - setProgSection(PROG_SECTION_INTRO); - } - else - { - mLogo.counter++; - } - } - } - - quitLogo(); -} - -// Bucle para la intro del juego -void GameDirector::runIntro() -{ - initIntro(); - - // Si la música no está sonando - if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) - { - // Reproduce la música - JA_PlayMusic(mMusic[MUSIC_INTRO].music, 0); - } - - while ((mProg.section == PROG_SECTION_INTRO) && (!exit())) - { - if (SDL_GetTicks() - mProg.ticks > mProg.ticksSpeed) - { - // Actualiza el contador de ticks - mProg.ticks = SDL_GetTicks(); - - // Comprueba los eventos que hay en la cola - while (SDL_PollEvent(mEventHandler) != 0) - { - // Evento de salida de la aplicación - if (mEventHandler->type == SDL_QUIT) - { - mProg.quit = true; - break; - } - - if ((mEventHandler->type == SDL_KEYDOWN) || (mEventHandler->type == SDL_JOYBUTTONDOWN)) - { - JA_StopMusic(); - setProgSection(PROG_SECTION_TITLE); - } - } - - // Actualiza los objetos - for (Uint8 i = 0; i < INTRO_TOTAL_BITMAPS; i++) - { - mIntro.bitmap[i]->update(); - } - for (Uint8 i = 0; i < INTRO_TOTAL_TEXTS; i++) - { - mIntro.text[i]->update(); - } - - // Guión de eventos - // Primera imagen - UPV - if (mIntro.events[BITMAP0] == EVENT_WAITING) - { - mIntro.bitmap[0]->setEnabled(true); - mIntro.events[BITMAP0] = EVENT_RUNNING; - } - - // Primer texto de la primera imagen - if ((mIntro.events[BITMAP0] == EVENT_COMPLETED) && (mIntro.events[TEXT0] == EVENT_WAITING)) - { - mIntro.text[0]->setEnabled(true); - mIntro.events[TEXT0] = EVENT_RUNNING; - } - - // Segundo texto de la primera imagen - if ((mIntro.events[TEXT0] == EVENT_COMPLETED) && (mIntro.events[TEXT1] == EVENT_WAITING)) - { - mIntro.text[0]->setEnabled(false); - mIntro.text[1]->setEnabled(true); - mIntro.events[TEXT1] = EVENT_RUNNING; - } - - // Tercer texto de la primera imagen - if ((mIntro.events[TEXT1] == EVENT_COMPLETED) && (mIntro.events[TEXT2] == EVENT_WAITING)) - { - mIntro.text[1]->setEnabled(false); - mIntro.text[2]->setEnabled(true); - mIntro.events[TEXT2] = EVENT_RUNNING; - } - - // Segunda imagen - Máquina - if ((mIntro.events[TEXT2] == EVENT_COMPLETED) && (mIntro.events[BITMAP1] == EVENT_WAITING)) - { - mIntro.bitmap[0]->setEnabled(false); - mIntro.text[2]->setEnabled(false); - mIntro.bitmap[1]->setEnabled(true); - mIntro.events[BITMAP1] = EVENT_RUNNING; - } - - // Primer texto de la segunda imagen - if ((mIntro.events[BITMAP1] == EVENT_COMPLETED) && (mIntro.events[TEXT3] == EVENT_WAITING)) - { - mIntro.text[3]->setEnabled(true); - mIntro.events[TEXT3] = EVENT_RUNNING; - } - - // Tercera imagen junto con primer texto - GRITO - if ((mIntro.events[TEXT3] == EVENT_COMPLETED) && (mIntro.events[BITMAP2] == EVENT_WAITING) && (mIntro.events[TEXT4] == EVENT_WAITING)) - { - mIntro.bitmap[1]->setEnabled(false); - mIntro.text[3]->setEnabled(false); - mIntro.bitmap[2]->setEnabled(true); - mIntro.text[4]->setEnabled(true); - mIntro.events[BITMAP2] = EVENT_RUNNING; - mIntro.events[TEXT4] = EVENT_RUNNING; - } - - // Cuarta imagen junto con primer texto - Reflexión - if ((mIntro.events[TEXT4] == EVENT_COMPLETED) && (mIntro.events[BITMAP3] == EVENT_WAITING) && (mIntro.events[TEXT5] == EVENT_WAITING)) - { - mIntro.bitmap[2]->setEnabled(false); - mIntro.text[4]->setEnabled(false); - mIntro.bitmap[3]->setEnabled(true); - mIntro.text[5]->setEnabled(true); - mIntro.events[BITMAP3] = EVENT_RUNNING; - mIntro.events[TEXT5] = EVENT_RUNNING; - } - - // Segundo texto de la cuarta imagen - if ((mIntro.events[TEXT5] == EVENT_COMPLETED) && (mIntro.events[TEXT6] == EVENT_WAITING)) - { - mIntro.text[5]->setEnabled(false); - mIntro.text[6]->setEnabled(true); - mIntro.events[TEXT6] = EVENT_RUNNING; - } - - // Quinta imagen - Patada - if ((mIntro.events[TEXT6] == EVENT_COMPLETED) && (mIntro.events[BITMAP4] == EVENT_WAITING)) - { - mIntro.bitmap[3]->setEnabled(false); - mIntro.text[6]->setEnabled(false); - mIntro.bitmap[4]->setEnabled(true); - mIntro.events[BITMAP4] = EVENT_RUNNING; - } - - // Primer texto de la quinta imagen - if ((mIntro.events[BITMAP4] == EVENT_COMPLETED) && (mIntro.events[TEXT7] == EVENT_WAITING)) - { - mIntro.text[7]->setEnabled(true); - mIntro.events[TEXT7] = EVENT_RUNNING; - } - - // Sexta imagen junto con texto - Globos de café - if ((mIntro.events[TEXT7] == EVENT_COMPLETED) && (mIntro.events[BITMAP5] == EVENT_WAITING) && (mIntro.events[TEXT8] == EVENT_WAITING)) - { - mIntro.bitmap[4]->setEnabled(false); - mIntro.text[7]->setEnabled(false); - mIntro.bitmap[5]->setEnabled(true); - mIntro.text[8]->setEnabled(true); - mIntro.events[BITMAP5] = EVENT_RUNNING; - mIntro.events[TEXT8] = EVENT_RUNNING; - } - - // Acaba el último texto - if (mIntro.events[TEXT8] == EVENT_COMPLETED) - { - mIntro.text[8]->setEnabled(false); - JA_StopMusic(); - setProgSection(PROG_SECTION_TITLE); - } - } - - // Limpia la pantalla - SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 0xFF); - SDL_RenderClear(mRenderer); - - // Dibuja los objetos - for (Uint8 i = 0; i < INTRO_TOTAL_BITMAPS; i++) - mIntro.bitmap[i]->render(); - for (Uint8 i = 0; i < INTRO_TOTAL_TEXTS; i++) - mIntro.text[i]->render(); - - // Actualiza la pantalla - SDL_RenderPresent(mRenderer); - } - - quitIntro(); -} - -// Bucle para el titulo del juego -void GameDirector::runTitle(Uint8 subsection) -{ - Uint8 R = 0x27; - Uint8 G = 0x27; - Uint8 B = 0x36; - - initTitle(subsection); - - while ((mProg.section == PROG_SECTION_TITLE) && (!exit())) - { - // Sección 1 - Titulo desplazandose - if (mTitle.section == TITLE_SECTION_1) - { - // Comprueba los eventos que hay en la cola - while (SDL_PollEvent(mEventHandler) != 0) - { - // Evento de salida de la aplicación - if (mEventHandler->type == SDL_QUIT) - { - mProg.quit = true; - break; - } - } - - // Calcula la lógica de los objetos - if (SDL_GetTicks() - mProg.ticks > mProg.ticksSpeed) - { - // Actualiza el contador de ticks - mProg.ticks = SDL_GetTicks(); - - // Actualiza los objetos - mTitle.coffeeBitmap->update(); - mTitle.crisisBitmap->update(); - } - - // Limpia la pantalla - SDL_SetRenderDrawColor(mRenderer, R, G, B, 255); - SDL_RenderClear(mRenderer); - - // Dibuja los objetos - mTitle.coffeeBitmap->render(); - mTitle.crisisBitmap->render(); - - // Actualiza la pantalla - SDL_RenderPresent(mRenderer); - - // Si los objetos han llegado a su destino, cambiamos de Sección - if ((mTitle.events[0] == EVENT_COMPLETED) && (mTitle.events[0] == EVENT_COMPLETED)) - { - mTitle.section = TITLE_SECTION_2; - - // Pantallazo blanco - SDL_SetRenderDrawColor(mRenderer, 0xFF, 0xFF, 0xFF, 0xFF); - SDL_RenderClear(mRenderer); - SDL_RenderPresent(mRenderer); - } - } - - // Sección 2 - Titulo vibrando - if (mTitle.section == TITLE_SECTION_2) - { - // Comprueba los eventos que hay en la cola - while (SDL_PollEvent(mEventHandler) != 0) - { - // Evento de salida de la aplicación - if (mEventHandler->type == SDL_QUIT) - { - mProg.quit = true; - break; - } - } - - // Reproduce el efecto sonoro - JA_PlaySound(mSound[SOUND_TITLE].sound); - - // Agita la pantalla - int v[] = {-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 0}; - int a = mTitle.coffeeBitmap->getPosX(); - int b = mTitle.crisisBitmap->getPosX(); - for (Uint8 n = 0; n < 11 * 3; n++) - { - // Limpia la pantalla - SDL_SetRenderDrawColor(mRenderer, R, G, B, 255); - SDL_RenderClear(mRenderer); - - // Dibuja los objetos - mTitle.coffeeBitmap->setPosX(a + v[n / 3]); - mTitle.crisisBitmap->setPosX(b + v[n / 3]); - mTitle.coffeeBitmap->render(); - mTitle.crisisBitmap->render(); - mTitle.dustBitmapR->animate(0); - mTitle.dustBitmapL->animate(0); - mTitle.dustBitmapR->render(); - mTitle.dustBitmapL->render(); - - // Actualiza la pantalla - SDL_RenderPresent(mRenderer); - } - - mTitle.section = 2; - } - - // Sección 3 - La pantalla de titulo con el menú y la música - if (mTitle.section == TITLE_SECTION_3) - { - if (mTitle.counter > 0) - { - // Comprueba los eventos que hay en la cola - while (SDL_PollEvent(mEventHandler) != 0) - { - // Evento de salida de la aplicación - if (mEventHandler->type == SDL_QUIT) - { - mProg.quit = true; - break; - } - - if ((mEventHandler->type == SDL_KEYUP) || (mEventHandler->type == SDL_JOYBUTTONUP)) - { - mTitle.menuVisible = true; - mTitle.counter = TITLE_COUNTER; - } - } - // Si la música no está sonando - if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) - { - // Reproduce la música - JA_PlayMusic(mMusic[MUSIC_TITLE].music, -1); - } - - // Calcula la lógica de los objetos - if (SDL_GetTicks() - mProg.ticks > mProg.ticksSpeed) - { - // Actualiza el contador de ticks - mProg.ticks = SDL_GetTicks(); - - // Actualiza la lógica del menu - mMenu.active->update(); - } - - // Cambia el destino donde se pinta todo - SDL_SetRenderTarget(mRenderer, mBackbuffer); - - // Limpia la pantalla - SDL_SetRenderDrawColor(mRenderer, R, G, B, 255); - SDL_RenderClear(mRenderer); - - // Pinta el tileado de fondo - switch (mTitle.backgroundMode) - { - case 0: // El tileado de fondo se desplaza en diagonal - mTitle.backgroundWindow.x++; - mTitle.backgroundWindow.x %= 64; - mTitle.backgroundWindow.y++; - mTitle.backgroundWindow.y %= 64; - break; - - case 1: // El tileado de fondo se desplaza en circulo - ++mTitle.backgroundCounter %= 360; - mTitle.backgroundWindow.x = 128 + (int(mSin[(mTitle.backgroundCounter + 270) % 360] * 128)); - mTitle.backgroundWindow.y = 96 + (int(mSin[(360 - mTitle.backgroundCounter) % 360] * 96)); - break; - - default: - break; - } - - SDL_RenderCopy(mRenderer, mTitleSurface, &mTitle.backgroundWindow, NULL); - - // Dibuja los objetos - mTitle.coffeeBitmap->render(); - mTitle.crisisBitmap->render(); - if (mTitle.menuVisible == true) - mMenu.active->render(); - mTitle.dustBitmapR->animate(0); - mTitle.dustBitmapL->animate(0); - mTitle.dustBitmapR->render(); - mTitle.dustBitmapL->render(); - - // PRESS ANY KEY! - if ((mTitle.counter % 50 > 14) && (mTitle.menuVisible == false)) - { - mText.black->writeCentered(SCREEN_CENTER_X + 1, PLAY_AREA_THIRD_QUARTER_Y + BLOCK + 1, "PRESS ANY KEY!", 0); - mText.white->writeCentered(SCREEN_CENTER_X, PLAY_AREA_THIRD_QUARTER_Y + BLOCK, "PRESS ANY KEY!", 0); - } - - // Texto con el copyright y versión - mText.black->writeCentered(SCREEN_CENTER_X + 1, SCREEN_HEIGHT - (BLOCK * 2) + 1, TEXT_COPYRIGHT, 0); - mText.white->writeCentered(SCREEN_CENTER_X, SCREEN_HEIGHT - (BLOCK * 2), TEXT_COPYRIGHT, 0); - - // Vuelve a usar el renderizador como destino - SDL_SetRenderTarget(mRenderer, NULL); - - // Volca el contenido de la textura en el renderizador - SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL); - - // Actualiza la pantalla - SDL_RenderPresent(mRenderer); - - // Comprueba las entradas para el menu - if (mTitle.menuVisible == true) - { - checkMenuInput(mMenu.active); - } - - // Comprueba si se ha seleccionado algún item del menú - if (mMenu.active->getName() == "TITLE") - { - switch (mMenu.active->getItemSelected()) - { - case 0: // PLAY - JA_PlaySound(mSound[SOUND_MENU_SELECT].sound); - mMenu.active->reset(); - mMenu.keyPressed = false; - setProgSection(PROG_SECTION_GAME); - renderFade(1); - JA_StopMusic(); - disableDemoMode(); - break; - case 1: // OPTIONS - JA_PlaySound(mSound[SOUND_MENU_SELECT].sound); - mMenu.active->reset(); - mMenu.keyPressed = false; - mMenu.active = mMenu.options; - mOptions.fullScreenModePrevious = mOptions.fullScreenMode; - mOptions.windowSizePrevious = mOptions.windowSize; - break; - case 2: // HOW TO PLAY - JA_PlaySound(mSound[SOUND_MENU_SELECT].sound); - mMenu.active->reset(); - mMenu.keyPressed = false; - mTitle.section = TITLE_SECTION_INSTRUCTIONS; - mTitle.instructionsMode = MODE_MANUAL; - break; - case 3: // QUIT - JA_PlaySound(mSound[SOUND_MENU_CANCEL].sound); - mMenu.active->reset(); - mMenu.keyPressed = false; - mProg.quit = true; - renderFade(1); - JA_StopMusic(); - break; - - default: - break; - } - } - - // Comprueba si se ha seleccionado algún item de opciones - if (mMenu.active->getName() == "OPTIONS") - { - switch (mMenu.active->getItemSelected()) - { - case 0: // Fullscreen mode - JA_PlaySound(mSound[SOUND_MENU_SELECT].sound); - changeFullScreenMode(); - updateOptionsMenu(); - mMenu.active->deselectItem(); - break; - case 1: // Windows size - JA_PlaySound(mSound[SOUND_MENU_SELECT].sound); - mOptions.windowSize++; - if (mOptions.windowSize == 5) - mOptions.windowSize = 1; - updateOptionsMenu(); - mMenu.active->deselectItem(); - break; - case 2: // OK - JA_PlaySound(mSound[SOUND_MENU_SELECT].sound); - SDL_SetWindowFullscreen(mWindow, mOptions.fullScreenMode); - SDL_SetWindowSize(mWindow, SCREEN_WIDTH * mOptions.windowSize, SCREEN_HEIGHT * mOptions.windowSize); - mMenu.active->reset(); - mMenu.active = mMenu.title; - break; - case 3: // CANCEL - JA_PlaySound(mSound[SOUND_MENU_CANCEL].sound); - mOptions.fullScreenMode = mOptions.fullScreenModePrevious; - mOptions.windowSize = mOptions.windowSizePrevious; - updateOptionsMenu(); - mMenu.active->reset(); - mMenu.active = mMenu.title; - break; - - default: - break; - } - } - - if (mMenu.active->getName() == "TITLE") - { - mTitle.counter--; - } - } - else if (mTitle.counter == 0) - { - mTitle.counter = TITLE_COUNTER; - setProgSection(mTitle.nextProgSection); - mMenu.active->reset(); - toogleTitleNextGS(); - renderFade(1); - enableDemoMode(); - } - } - - // Sección Instrucciones - if (mTitle.section == TITLE_SECTION_INSTRUCTIONS) - runInstructions(mTitle.instructionsMode); - } - - quitTitle(); -} - -// Bucle para el juego -void GameDirector::runGame() -{ - initGame(); - - while ((mProg.section == PROG_SECTION_GAME) && (!exit())) - { - // Sección juego en pausa - if (mGame.section == GAME_SECTION_PAUSE) - runPausedGame(); - - // Sección Game Over - if (mGame.section == GAME_SECTION_GAMEOVER) - runGameOverScreen(); - - // Sección juego jugando - if (mGame.section == GAME_SECTION_PLAY) - { - // Si la música no está sonando - if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) - { - // Reproduce la música - if (mGame.player->isAlive()) - JA_PlayMusic(mMusic[MUSIC_PLAYING].music, -1); - } - - // Comprueba que la diferencia de ticks sea mayor a la velocidad del juego - if (SDL_GetTicks() - mProg.ticks > mProg.ticksSpeed) - { - // Actualiza el contador de ticks - mProg.ticks = SDL_GetTicks(); - - // Actualiza el contador de juego - mGame.counter++; - - // Comprueba los eventos que hay en la cola - while (SDL_PollEvent(mEventHandler) != 0) - { - // Evento de salida de la aplicación - if (mEventHandler->type == SDL_QUIT) - { - mProg.quit = true; - break; - } - else if ((mEventHandler->type == SDL_KEYDOWN) && (mEventHandler->key.repeat == 0)) - { - if (mDebug.enabled) - { - switch (mEventHandler->key.keysym.scancode) - { - case SDL_SCANCODE_F: - mDebug.enemySet--; - if (mDebug.enemySet == 255) - mDebug.enemySet = 0; - break; - case SDL_SCANCODE_R: - mDebug.enemySet = std::min((int)++mDebug.enemySet, 9); - break; - case SDL_SCANCODE_T: - mProg.ticksSpeed *= 2; - break; - case SDL_SCANCODE_G: - createNewBalloon(100, 0, BALLOON_1, BALLOON_VELX_POSITIVE, 1.0F, 0, mTexture[TEXTURE_BALLOON].texture); - break; - case SDL_SCANCODE_P: - popAllBalloons(); - //mGame.balloonsPopped += 10; - break; - case SDL_SCANCODE_Z: - incBalloonSpeed(); - break; - case SDL_SCANCODE_X: - decBalloonSpeed(); - break; - case SDL_SCANCODE_C: - mDebug.gradB += 10; - break; - case SDL_SCANCODE_I: - mGame.player->setInvulnerable(true); - mGame.player->setInvulnerableCounter(65000); - break; - case SDL_SCANCODE_M: - break; - case SDL_SCANCODE_N: - break; - default: - break; - } - } - } - } - - // Actualiza la lógica del juego - updatePlayField(); - } - - // Cambia el destino donde se pinta todo - SDL_SetRenderTarget(mRenderer, mBackbuffer); - - // Limpia la pantalla - SDL_SetRenderDrawColor(mRenderer, 0x00, 0x00, 0x00, 0xFF); - SDL_RenderClear(mRenderer); - - // Dibuja los objetos - renderPlayField(); - - // Vuelve a usar el renderizador como destino - SDL_SetRenderTarget(mRenderer, NULL); - - // Volca el contenido de la textura en el renderizador - SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL); - - // Pinta la informacion de debug - renderDebugInfo(); - - // Actualiza la pantalla - SDL_RenderPresent(mRenderer); - } - } - - quitGame(); -} - -// Bucle para el menu de pausa del juego -void GameDirector::runPausedGame() -{ - while ((mGame.section == GAME_SECTION_PAUSE) && (mProg.section == PROG_SECTION_GAME) && (!exit())) - { - // Comprueba los eventos que hay en la cola - while (SDL_PollEvent(mEventHandler) != 0) - { - // Evento de salida de la aplicación - if (mEventHandler->type == SDL_QUIT) - { - mProg.quit = true; - break; - } - } - - // Calcula la lógica de los objetos - if (SDL_GetTicks() - mProg.ticks > mProg.ticksSpeed) - { - // Actualiza el contador de ticks - mProg.ticks = SDL_GetTicks(); - - // Actualiza la lógica del menu - mMenu.pause->update(); - } - - // Cambia el destino donde se pinta todo - SDL_SetRenderTarget(mRenderer, mBackbuffer); - - // Dibuja los objetos - renderBackground(); - renderBalloons(); - renderBullets(); - mGame.player->render(); - renderScoreBoard(); - mMenu.pause->render(); - - // Vuelve a usar el renderizador como destino - SDL_SetRenderTarget(mRenderer, NULL); - - // Volca el contenido de la textura en el renderizador - SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL); - - // Actualiza la pantalla - SDL_RenderPresent(mRenderer); - - // Comprueba las entradas para el menu - checkMenuInput(mMenu.pause); - - // Comprueba si se ha seleccionado algún item del menú - switch (mMenu.pause->getItemSelected()) - { - case 0: - JA_PlaySound(mSound[SOUND_MENU_SELECT].sound); - mGame.section = GAME_SECTION_PLAY; - mMenu.pause->reset(); - mMenu.keyPressed = false; - if (JA_GetMusicState() == JA_MUSIC_PAUSED) - { - JA_ResumeMusic(); - } - break; - case 1: - JA_PlaySound(mSound[SOUND_MENU_CANCEL].sound); - setProgSection(PROG_SECTION_TITLE); - mMenu.pause->reset(); - mMenu.keyPressed = false; - JA_StopMusic(); - renderFade(1); - break; - default: - break; - } - } -} - -// Bucle para la pantalla de instrucciones -void GameDirector::runInstructions(Uint8 mode) -{ - SDL_Rect window = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT}; - Sprite *sprite = new Sprite(); - SDL_Rect srcRect = {0, 0, 16, 16}; - - bool wannaExit = false; - if (mode == MODE_MANUAL) - mTitle.instructionsCounter = 0; - - const SDL_Rect destRect1 = {60, 88 + (16 * 0), 16, 16}; // Disquito - const SDL_Rect destRect2 = {60, 88 + (16 * 1), 16, 16}; // Gavineixon - const SDL_Rect destRect3 = {60, 88 + (16 * 2), 16, 16}; // Pacmar - const SDL_Rect destRect4 = {60, 88 + (16 * 3), 16, 16}; // Time Stopper - const SDL_Rect destRect5 = {60, 88 + (16 * 4), 16, 16}; // Coffee - - sprite->init(destRect1, mTexture[TEXTURE_ITEMS].texture, mRenderer); - - while ((mTitle.section == TITLE_SECTION_INSTRUCTIONS) && (!exit())) - { - // Comprueba los eventos que hay en la cola - while (SDL_PollEvent(mEventHandler) != 0) - { - // Evento de salida de la aplicación - if (mEventHandler->type == SDL_QUIT) - { - mProg.quit = true; - break; - } - - if ((mEventHandler->type == SDL_KEYDOWN) || (mEventHandler->type == SDL_JOYBUTTONDOWN)) - { - if (mode == MODE_AUTO) - { - JA_StopMusic(); - setProgSection(PROG_SECTION_TITLE); - } - else - wannaExit = true; - } - } - - // Pinta en la surface el texto y los sprites - SDL_SetRenderTarget(mRenderer, mInstructionsSurface); - SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 255); - SDL_RenderClear(mRenderer); - mText.white->writeCenteredAndColored(SCREEN_CENTER_X, 8, "OBJECTIVE", 0, 0xFF, 0x7A, 0x00); - mText.white->writeCentered(SCREEN_CENTER_X, 24, "YOU HAVE TO POP AS MANY"); - mText.white->writeCentered(SCREEN_CENTER_X, 34, "BALLOONS AS YOU CAN"); - mText.white->writeCentered(SCREEN_CENTER_X, 48, "DIFFICULTY WILL BE INCREASED"); - mText.white->writeCentered(SCREEN_CENTER_X, 58, "AS YOU SCORE POINTS"); - mText.white->writeCenteredAndColored(SCREEN_CENTER_X, 75, "ITEMS", 0, 0xFF, 0x7A, 0x00); - mText.white->write(84, 92, "1.000 POINTS", 0); - mText.white->write(84, 108, "2.500 POINTS", 0); - mText.white->write(84, 124, "5.000 POINTS", 0); - mText.white->write(84, 140, "TIME STOPPER", 0); - mText.white->write(84, 156, "EXTRA HIT", 0); - if ((mode == MODE_MANUAL) && (mTitle.instructionsCounter % 50 > 14)) - mText.white->writeCenteredAndColored(SCREEN_CENTER_X, SCREEN_HEIGHT - 12, "PRESS ANY KEY TO RETURN", 0, 0xFF, 0x7A, 0x00); - - // Disquito - sprite->init(destRect1, mTexture[TEXTURE_ITEMS].texture, mRenderer); - srcRect.x = 0; - srcRect.y = 16 * (((mTitle.instructionsCounter + 0) / 36) % 2); - sprite->setSpriteClip(srcRect); - sprite->render(); - - // Gavineixon - sprite->init(destRect2, mTexture[TEXTURE_ITEMS].texture, mRenderer); - srcRect.x += srcRect.w; - srcRect.y = 16 * (((mTitle.instructionsCounter + 3) / 36) % 2); - sprite->setSpriteClip(srcRect); - sprite->render(); - - // Pacmar - sprite->init(destRect3, mTexture[TEXTURE_ITEMS].texture, mRenderer); - srcRect.x += srcRect.w; - srcRect.y = 16 * (((mTitle.instructionsCounter + 6) / 36) % 2); - sprite->setSpriteClip(srcRect); - sprite->render(); - - // Time Stopper - sprite->init(destRect4, mTexture[TEXTURE_ITEMS].texture, mRenderer); - srcRect.x += srcRect.w; - srcRect.y = 16 * (((mTitle.instructionsCounter + 9) / 36) % 2); - sprite->setSpriteClip(srcRect); - sprite->render(); - - // Coffee - sprite->init(destRect5, mTexture[TEXTURE_ITEMS].texture, mRenderer); - srcRect.x += (srcRect.w * 2); // Se salta el icono del TNT - srcRect.y = 16 * (((mTitle.instructionsCounter + 12) / 36) % 2); - sprite->setSpriteClip(srcRect); - sprite->render(); - - // Cambia el destino de renderizado - SDL_SetRenderTarget(mRenderer, nullptr); - - // Limpia la pantalla - SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 255); - SDL_RenderClear(mRenderer); - - // Dibuja los objetos - if (mode == MODE_AUTO) - window.y = std::max(0, SCREEN_HEIGHT - (INSTRUCTIONS_COUNTER - mTitle.instructionsCounter) + 100); - else - window.y = 0; - SDL_RenderCopy(mRenderer, mInstructionsSurface, NULL, &window); - - // Muestra la pantalla - SDL_RenderPresent(mRenderer); - - // Lógica - if (SDL_GetTicks() - mProg.ticks > mProg.ticksSpeed) - { - // Actualiza el contador de ticks - mProg.ticks = SDL_GetTicks(); - - // Modo automático - if (mode == MODE_AUTO) - { - mTitle.instructionsCounter--; - - if (mTitle.instructionsCounter == 0) - { - resetTitle(TITLE_SECTION_1); - mTitle.nextProgSection = PROG_SECTION_LOGO; - } - } - // Modo manual - else - { - ++mTitle.instructionsCounter %= 60000; - - if (wannaExit) - { - resetTitle(TITLE_SECTION_1); - mTitle.section = TITLE_SECTION_3; - mTitle.nextProgSection = PROG_SECTION_LOGO; - - // Prepara las variables para la sección 3 del titulo - mTitle.dustBitmapL->setEnabled(false); - mTitle.dustBitmapR->setEnabled(false); - mTitle.menuVisible = true; - mTitle.coffeeBitmap->setPosY(11); - mTitle.crisisBitmap->setPosY(57); - mMenu.title->setSelectorPos(2); - } - } - } - } - delete sprite; -} - -// Bucle para la pantalla de game over -void GameDirector::runGameOverScreen() -{ - while ((mGame.section == GAME_SECTION_GAMEOVER) && (mProg.section == PROG_SECTION_GAME) && (!exit())) - { - // Comprueba los eventos que hay en la cola - while (SDL_PollEvent(mEventHandler) != 0) - { - // Evento de salida de la aplicación - if (mEventHandler->type == SDL_QUIT) - { - mProg.quit = true; - break; - } - } - - // Calcula la lógica de los objetos - if (SDL_GetTicks() - mProg.ticks > mProg.ticksSpeed) - { - // Actualiza el contador de ticks - mProg.ticks = SDL_GetTicks(); - - // Actualiza la lógica del menu - mMenu.gameOver->update(); - } - - // Cambia el destino donde se pinta todo - SDL_SetRenderTarget(mRenderer, mBackbuffer); - - // Limpia la pantalla - SDL_SetRenderDrawColor(mRenderer, 0x27, 0x27, 0x36, 0xFF); - SDL_RenderClear(mRenderer); - - // Dibuja los objetos - mText.whiteX2->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - (BLOCK * 4), "GAME OVER", 0); - mText.white->writeCentered(PLAY_AREA_CENTER_X, PLAY_AREA_CENTER_Y - (BLOCK * 1), "YOUR SCORE: " + std::to_string(mGame.player->getScore()), 0); - mText.white->write(PLAY_AREA_CENTER_X - (mText.white->lenght("RETRY?", 0) / 2), PLAY_AREA_CENTER_Y + BLOCK * 2, "RETRY?", 0); - mMenu.gameOver->render(); - - // Vuelve a usar el renderizador como destino - SDL_SetRenderTarget(mRenderer, NULL); - - // Volca el contenido de la textura en el renderizador - SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL); - - // Muestra la pantalla - SDL_RenderPresent(mRenderer); - - // Comprueba las entradas para el menu - checkMenuInput(mMenu.gameOver); - - // Comprueba si se ha seleccionado algún item del menú - switch (mMenu.gameOver->getItemSelected()) - { - case 0: - setProgSection(PROG_SECTION_GAME); - mGame.section = GAME_SECTION_PLAY; - mMenu.gameOver->reset(); - mMenu.keyPressed = false; - JA_PlaySound(mSound[SOUND_MENU_SELECT].sound); - JA_StopMusic(); - renderFade(1); - disableDemoMode(); - resetGame(); - break; - case 1: - setProgSection(PROG_SECTION_TITLE); - mMenu.gameOver->reset(); - mMenu.keyPressed = false; - JA_PlaySound(mSound[SOUND_MENU_CANCEL].sound); - JA_StopMusic(); - renderFade(1); - mTitle.nextProgSection = PROG_SECTION_GAME; - enableDemoMode(); - break; - default: - break; - } - } -} - -// Activa el modo Demo -void GameDirector::enableDemoMode() -{ - mDemo.enabled = true; -} - -// Desactiva el modo Demo -void GameDirector::disableDemoMode() -{ - mDemo.enabled = false; -} - -// Actualiza el proximo estado del juego despues del titulo -void GameDirector::toogleTitleNextGS() -{ - if (mTitle.nextProgSection == PROG_SECTION_LOGO) - mTitle.nextProgSection = PROG_SECTION_GAME; - else - mTitle.nextProgSection = PROG_SECTION_LOGO; -} - -// Dibuja la informacion de debug en pantalla -void GameDirector::renderDebugInfo() -{ - if (mDebug.enabled) - { - Uint8 R = 0xFF; - Uint8 G = 0x20; - Uint8 B = 0x20; - - SDL_RenderSetLogicalSize(mRenderer, SCREEN_WIDTH * 2, SCREEN_HEIGHT * 2); - - mText.white->writeShadowed(2, 2 + 0 * BLOCK, "menace(umb): " + std::to_string(mGame.menaceCurrent) + "(" + std::to_string(mGame.menaceThreshold) + ")", R, G, B); - mText.white->writeShadowed(2, 2 + 1 * BLOCK, "currentPower: " + std::to_string(mGame.stage[mGame.currentStage].currentPower), R, G, B); - mText.white->writeShadowed(2, 2 + 2 * BLOCK, "currentStage: " + std::to_string(mGame.currentStage), R, G, B); - mText.white->writeShadowed(2, 2 + 3 * BLOCK, "counter: " + std::to_string(mGame.counter), R, G, B); - mText.white->writeShadowed(2, 2 + 4 * BLOCK, "(R)enemyset: " + std::to_string(mDebug.enemySet), R, G, B); - mText.white->writeShadowed(2, 2 + 5 * BLOCK, "RGB: " + std::to_string(mDebug.gradR) + "," + std::to_string(mDebug.gradG) + "," + std::to_string(mDebug.gradB), R, G, B); - mText.white->writeShadowed(2, 2 + 6 * BLOCK, "(I)invuln : " + std::to_string(mGame.player->getInvulnerableCounter()), R, G, B); - mText.white->writeShadowed(2, 2 + 7 * BLOCK, "balloons: " + std::to_string(countBalloons()), R, G, B); - mText.white->writeShadowed(2, 2 + 8 * BLOCK, "balloonsPop: " + std::to_string(mGame.balloonsPopped), R, G, B); - mText.white->writeShadowed(2, 2 + 9 * BLOCK, "(Z-X)ballSped:" + std::to_string(mGame.enemySpeed), R, G, B); - } -} - -// Indica si se puede crear una powerball -bool GameDirector::canPowerBallBeCreated() -{ - bool success = false; - - if ((!mGame.powerBallEabled) && (calculateScreenPower() > 0)) - success = true; - else - success = false; - - return success; -} - -// Calcula el poder actual de los globos en pantalla -int GameDirector::calculateScreenPower() -{ - int power = 0; - for (Uint8 i = 0; i < MAX_BALLOONS; i++) - if (mGame.balloon[i]->isEnabled()) - power += mGame.balloon[i]->getPower(); - return power; -} \ No newline at end of file diff --git a/source/gamedirector.h b/source/gamedirector.h deleted file mode 100644 index 04e8086..0000000 --- a/source/gamedirector.h +++ /dev/null @@ -1,679 +0,0 @@ -#pragma once -#include "ifdefs.h" -#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 "text2.h" -#include "menu.h" -#include "const.h" -#include "jail_audio.h" -#include "utils.h" -#include - -#ifndef GAMEDIRECTOR_H -#define GAMEDIRECTOR_H - -// GameDirector -class GameDirector -{ -private: - SDL_Window *mWindow; // La ventana donde dibujamos - SDL_Renderer *mRenderer; // El renderizador de la ventana - SDL_Event *mEventHandler; // Manejador de eventos - - SDL_Texture *mBackbuffer; // Textura para usar como backbuffer - SDL_Texture *mTitleSurface; // Textura para dibujar el fondo de la pantalla de título - SDL_Texture *mInstructionsSurface; // Textura donde dibujar las instrucciones - - SDL_Joystick *mGameController; // Manejador para el mando 1 - SDL_Haptic *mControllerHaptic; // Manejador para el mando con vibración - bool mGameControllerFound; // Variable para saber si hay un mando conectado - -#ifndef UNUSED - CoffeeDrop *mCoffeeDrop[MAX_COFFEE_DROPS]; // Vector con todas ls gotas de café; -#endif - - struct text_t - { - Text *white; // Texto blanco de 8x8 - Text *whiteX2; // Texto blanco de 16x16 - Text *black; // Texto negro de 8x8 - Text *blackX2; // Texto negro de 16x16 - Text *nokia; // Texto de anchura variable y 10px de alto - }; - text_t mText; // Variable con todos los objetos de texto - - struct menu_t - { - Menu *title; // Menu de la pantalla de título - Menu *pause; // Menú de la pantalla de pausa - Menu *gameOver; // Menú de la pantalla de game over - Menu *options; // Menú de la pantalla de opciones - Menu *active; // Menu activo (de momento para la pantalla del titulo) - bool keyPressed; // Variable para evitar la repetición de teclas en los menus - }; - menu_t mMenu; // Variable con todos los objetos menus y sus variables - - struct intro_t - { - SmartSprite *bitmap[INTRO_TOTAL_BITMAPS]; // Vector con los sprites inteligentes para los dibujos de la intro - Text2 *text[INTRO_TOTAL_TEXTS]; // Textos de la intro - Uint8 events[INTRO_TOTAL_EVENTS]; // Vector para coordinar los eventos de la intro - }; - intro_t mIntro; // Contiene todas las variables de la sección 'Intro' - - 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[50]; // Vector con todas las inicializaciones de los enemigos de la formación - }; - enemyFormation_t mEnemyFormation[100]; // 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 game_t - { - Uint32 score; // Puntuación actual - Uint32 hiScore; // Puntuación máxima - Uint8 section; // Seccion actual dentro del juego - bool hiScoreAchieved; // Indica si se ha superado la puntuación máxima - Uint8 currentStage; // Indica la fase actual - stage_t stage[10]; // Variable con los datos de cada pantalla - Uint8 stageBitmapCounter; // Contador para el tiempo visible del texto de Stage - float stageBitmapPath[STAGE_COUNTER]; // Vector con los puntos Y por donde se desplaza el texto - float getReadyBitmapPath[STAGE_COUNTER]; // Vector con los puntos X por donde se desplaza el texto - Uint16 deathCounter; // Contador para la animación de muerte del jugador - Uint8 deathIndex; // Indice del vector de smartsprites que contiene el sprite del jugador - Uint8 menaceCurrent; // Nivel de amenaza actual - Uint8 menaceThreshold; // 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 timeStopped; // Indica si el tiempo está detenido - Uint16 timeStoppedCounter; // Temporizador para llevar la cuenta del tiempo detenido - Uint8 remainingExplosions; // Cantidad de explosiones restantes - Uint16 remainingExplosionsCounter; // Temporizador para la cantidad de explosiones restantes - bool explosionTime; // Indica si las explosiones estan en marcha - Uint32 counter; // Contador para el juego - Uint32 scoreDataFile[TOTAL_SCORE_DATA]; // Datos del fichero de puntos - Sprite *getReadyBitmap; // Sprite para el texto de GetReady del principio de la partida - SmartSprite *_1000Bitmap; // Sprite con el texto 1.000 - SmartSprite *_2500Bitmap; // Sprite con el texto 2.500 - SmartSprite *_5000Bitmap; // Sprite con el texto 5.000 - Sprite *background; // Sprite con los graficos frontales del fondo - Sprite *gradient; // Sprite con los graficos del degradado de color de fondo - SDL_Rect gradientRect[4]; // Vector con las coordenadas de los 4 gradientes - Uint16 balloonsPopped; // Lleva la cuenta de los globos explotados - MovingSprite *clouds1a; // Sprite para las nubes superiores - MovingSprite *clouds1b; // Sprite para las nubes superiores - MovingSprite *clouds2a; // Sprite para las nubes inferiores - MovingSprite *clouds2b; // Sprite para las nubes inferiores - Sprite *grass; // Sprite para la hierba - Sprite *scoreBoard; // Sprite para el fondo del marcador - Sprite *powerMeter; // Sprite para el medidor de poder de la fase - Player *player; // El jugador - Balloon *balloon[MAX_BALLOONS]; // Vector con los objetos globo - Bullet *bullet[MAX_BULLETS]; // Vector con los objetos bala - Item *item[MAX_ITEMS]; // Vector con los objetos item - SmartSprite *smartSprite[MAX_SMART_SPRITES]; // Vector para almacenar y gestionar SmartSprites - Uint8 lastEnemyDeploy; // Guarda cual ha sido la última formación desplegada para no repetir; - Uint8 enemyDeployCounter; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero - float enemySpeed; // Velocidad a la que se mueven los enemigos - effect_t effect; // Variable para gestionar los efectos visuales - bool powerBallEabled; // Indica si hay una powerball ya activa - }; - game_t mGame; // Variable con todas las variables usadas durante el juego - - struct title_t - { - Uint16 counter; // Temporizador para la pantalla de titulo - Uint16 backgroundCounter; // Temporizador para el fondo de tiles de la pantalla de titulo - Uint8 backgroundMode; // Variable para almacenar el tipo de efecto que hará el fondo de la pantalla de titulo - bool menuVisible; // Indicador para saber si se muestra el menu del titulo o la frase intermitente - Sprite *tile; // Sprite para dibujar el fondo de pantalla del título - SDL_Rect backgroundWindow; // Ventana visible para la textura de fondo del titulo - Uint8 section; // Indicador para el bucle del titulo - Uint8 nextProgSection; // Indica cual es la siguiente sección a cargar cuando termine el contador del titulo - Uint8 events[TITLE_TOTAL_EVENTS]; // Vector para coordinar los eventos de la pantalla de titulo - Uint16 instructionsCounter; // Contador para las instrucciones - Uint8 instructionsMode; // Modo en el que se van a mostrar las instrucciones - SmartSprite *coffeeBitmap; // Sprite con la palabra COFFEE para la pantalla de titulo - SmartSprite *crisisBitmap; // Sprite con la palabra CRISIS para la pantalla de titulo - AnimatedSprite *dustBitmapL; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo - AnimatedSprite *dustBitmapR; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo - }; - title_t mTitle; // Variable con todas las variables de la pantalla de titulo - - 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 options_t - { - Uint32 fullScreenMode; // Contiene el valor del modo de pantalla completa - Uint32 fullScreenModePrevious; - Uint8 windowSize; // Contiene el valor del tamaño de la ventana - Uint8 windowSizePrevious; - bool displayCoffeeDrops; // Indica si se han de mostar las gotas de cafe - }; - options_t mOptions; // Variable con todas las variables de las opciones del programa - - struct logo_t - { - Uint16 counter; // Contador - Sprite *sprite; // Sprite con la textura del logo - }; - logo_t mLogo; // Variable con las variables para el logo - - struct prog_t - { - bool quit; // Indica si hay que salir del programa - input_t keyboard; // Almacena los códigos de teclado correspondientes - input_t keyboardBuffer; // Buffer para teclas pulsadas - std::string executablePath; // Path del ejecutable - Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa - Uint8 section; // Sección actual del programa; - Uint8 subsection; // Subseccion dentro de la sección; - Uint8 ticksSpeed; // Velocidad a la que se repiten los bucles del programa - }; - prog_t mProg; // Contiene todas las variables globales del programa - - 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; - - struct resourceBinFile_t - { - std::string file; // Ruta al fichero - }; - resourceBinFile_t mBinFile[TOTAL_BINFILE]; // Todos los ficheros binarios - - struct resourceSound_t - { - std::string file; // Ruta al fichero - JA_Sound sound; // Variable con el sonido - }; - resourceSound_t mSound[TOTAL_SOUND]; // Todos los sonidos - - struct resourceMusic_t - { - std::string file; // Ruta al fichero - JA_Music music; // Variable con la música - }; - resourceMusic_t mMusic[TOTAL_MUSIC]; // Todas las músicas - - struct resourceTexture_t - { - std::string file; // Ruta al fichero - LTexture *texture; // Variable con la textura - }; - resourceTexture_t mTexture[TOTAL_TEXTURE]; // Todos los gráficos - -public: - // Constructor - GameDirector(std::string path); - - // Destructor - ~GameDirector(); - - // Inicia las variables necesarias para arrancar el programa - void initProg(); - - // Carga los recursos necesarios para el programa - bool loadMediaProg(); - - // Libera las variables del programa - void quitProg(); - - // Inicializa jail_audio - void initJailAudio(); - - // Arranca SDL y crea la ventana - bool initSDL(); - - // Inicializa el vector con los valores del seno - void initSin(); - - // Inicializa las variables que contienen puntos de ruta para mover objetos - void initPaths(); - - // Inicializa las variables necesarias para la sección 'Logo' - void initLogo(); - - // Carga los recursos necesarios para la sección 'Logo' - bool loadMediaLogo(); - - // Libera las variables necesarias para la sección 'Logo' - void quitLogo(); - - // Inicializa las variables necesarias para la sección 'Intro' - void initIntro(); - - // Carga los recursos necesarios para la sección 'Intro' - bool loadMediaIntro(); - - // Libera las variables necesarias para la sección 'Intro' - void quitIntro(); - - // Inicializa las variables necesarias para la sección 'Title' - void initTitle(Uint8 subsection = TITLE_SECTION_1); - - // Resetea las variables necesarias para la sección 'Title' - void resetTitle(Uint8 subsection = TITLE_SECTION_1); - - // Carga los recursos necesarios para la sección 'Title' - bool loadMediaTitle(); - - // Libera las variables necesarias para la sección 'Title' - void quitTitle(); - - // Inicializa las variables necesarias para la sección 'Game' - void initGame(); - - // Inicializa las variables especificas de la sección 'Game' para empezar una nueva partida - void resetGame(); - - // Carga los recursos necesarios para la sección 'Game' - bool loadMediaGame(); - - // Libera las variables necesarias para la sección 'Game' - void quitGame(); - - // Crea el indice de ficheros - void setFileList(); - - // Comprueba que todos los ficheros existen - bool checkFileList(); - - // Carga el fichero de puntos - bool loadScoreFile(); - - // Carga el fichero de configuración - bool loadConfigFile(); - - // Carga el fichero de datos para la demo - bool loadDemoFile(); - - // Guarda el fichero de puntos - bool saveScoreFile(); - - // Guarda el fichero de configuración - bool saveConfigFile(); - - // Guarda el fichero de datos para la demo - bool saveDemoFile(); - - // Carga un archivo de imagen en una textura - bool loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer); - - // Comprueba el valor de la variable 'quit' - bool exit(); - - // Establece el valor de la variable - void setExecutablePath(std::string path); - - // 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 setScore(Uint32 score); - - // 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(); - - // 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(); - - // Comprueba la colisión entre el jugador y los items - void checkPlayerItemCollision(); - - // 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); - - // 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); - - // Crea un objeto de bonus en función del azar - void dropBonus(); - - // 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); - - // 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(); - -#ifndef UNUSED - // Deshabilita todas las gotas de café - void resetCoffeeDrops(); - - // Actualiza las gotas de cafe - void updateCoffeeDrops(); - - // Dibuja las gotas de cafe - void renderCoffeeDrops(); - - // Devuelve el primer indice libre del vector de CoffeeDrops - Uint8 getCoffeDropFreeIndex(); - - // Crea un numero de gotas de cafe - void createCoffeDrops(Uint8 num, int x, int y); -#endif - // Acciones a realizar cuando el jugador muere - void killPlayer(); - - // Obtiene el valor de la variable - Uint8 getSubsection(); - - // Calcula y establece el valor de amenaza en funcion de los globos activos - void setMenace(); - - // 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 old_updateMenace(); - - // 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(); - - // Gestiona la entrada de teclado y mando durante el menu - void checkMenuInput(Menu *menu); - - // Obtiene el valor de la variable - Uint8 getProgSection(); - - // Establece el valor de la variable - void setProgSection(Uint8 section, Uint8 subsection = 0); - - // Pinta una transición en pantalla - void renderFade(Uint8 index); - - // 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(); - - // Cambia el valor de la variable de modo de pantalla completa - void changeFullScreenMode(); - - // Actualiza los elementos del menu de opciones - void updateOptionsMenu(); - - // Agita la pantalla - void shakeScreen(); - - // Agita la pantalla - void shakeScreen2(); - - // Bucle para el logo del juego - void runLogo(); - - // Bucle para la intro del juego - void runIntro(); - - // Bucle para el titulo del juego - void runTitle(Uint8 subsection = TITLE_SECTION_1); - - // Bucle para el juego - void runGame(); - - // Bucle para el menu de pausa del juego - void runPausedGame(); - - // Bucle para la pantalla de instrucciones - void runInstructions(Uint8 mode); - - // Bucle para la pantalla de game over - void runGameOverScreen(); - - // Activa el modo Demo - void enableDemoMode(); - - // Desactiva el modo Demo - void disableDemoMode(); - - // Intercambia el proximo estado del juego despues del titulo - void toogleTitleNextGS(); - - // 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(); -}; - -#endif diff --git a/source/item.cpp b/source/item.cpp index c6ddf86..b5f5e2f 100644 --- a/source/item.cpp +++ b/source/item.cpp @@ -54,30 +54,32 @@ void Item::init(Uint8 value, float x, float y, LTexture *texture, SDL_Renderer * mVelX = 0; mVelY = 0; break; + case ITEM_POINTS_1_DISK: mSprite->setAnimationFrames(0, 0, 16 * 0, 16 * 0, mWidth, mHeight); mSprite->setAnimationFrames(0, 1, 16 * 0, 16 * 1, mWidth, mHeight); break; + case ITEM_POINTS_2_GAVINA: mSprite->setAnimationFrames(0, 0, 16 * 1, 16 * 0, mWidth, mHeight); mSprite->setAnimationFrames(0, 1, 16 * 1, 16 * 1, mWidth, mHeight); break; + case ITEM_POINTS_3_PACMAR: mSprite->setAnimationFrames(0, 0, 16 * 2, 16 * 0, mWidth, mHeight); mSprite->setAnimationFrames(0, 1, 16 * 2, 16 * 1, mWidth, mHeight); break; + case ITEM_CLOCK: mSprite->setAnimationFrames(0, 0, 16 * 3, 16 * 0, mWidth, mHeight); mSprite->setAnimationFrames(0, 1, 16 * 3, 16 * 1, mWidth, mHeight); break; - case ITEM_TNT: - mSprite->setAnimationFrames(0, 0, 16 * 4, 16 * 0, mWidth, mHeight); - mSprite->setAnimationFrames(0, 1, 16 * 4, 16 * 1, mWidth, mHeight); - break; + case ITEM_COFFEE: mSprite->setAnimationFrames(0, 0, 16 * 5, 16 * 0, mWidth, mHeight); mSprite->setAnimationFrames(0, 1, 16 * 5, 16 * 1, mWidth, mHeight); break; + default: break; } @@ -195,7 +197,7 @@ void Item::updateTimeToLive() { if (mTimeToLive > 0) { - --mTimeToLive; + mTimeToLive--; } } @@ -203,9 +205,7 @@ void Item::updateTimeToLive() void Item::checkTimeToLive() { if (mTimeToLive == 0) - { erase(); - } } // Obtiene del valor de la variable diff --git a/source/main.cpp b/source/main.cpp index 24f7ec3..52c0ba4 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -17,11 +17,11 @@ A continuación tenemos las clases enfocadas a la lógica del juego, la clase pl 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 -gamedirector es la que realiza toda la lógica y se encarga de hacer interactuar +mDirector es la que realiza toda la lógica y se encarga de hacer interactuar al resto de objetos entre si. -El objeto gamedirector tiene tres estados: titulo, juego y pausa. Segun su estado -el bucle que recorre es distinto. En el bucle juego, el objeto gamedirector +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 @@ -36,10 +36,7 @@ En los vectores que contienen objetos, se considera activos los objetos que tien un tipo asociado diferente a NO_KIND */ -#include "ifdefs.h" -#include "const.h" -#include "gamedirector.h" -#include +#include "director.h" #include #include @@ -48,33 +45,16 @@ int main(int argc, char *args[]) // Inicia el generador de numeros aleatorios srand(time(nullptr)); - // Crea el objeto gameDirector - GameDirector *gameDirector = new GameDirector(args[0]); + // Crea el objeto mDirector + Director *mDirector = new Director(args[0]); printf("Starting the game...\n\n"); - // Mientras no se quiera salir del juego - while (!(gameDirector->exit())) - { - switch (gameDirector->getProgSection()) - { - case PROG_SECTION_LOGO: - gameDirector->runLogo(); - break; - case PROG_SECTION_INTRO: - gameDirector->runIntro(); - break; - case PROG_SECTION_TITLE: - gameDirector->runTitle(gameDirector->getSubsection()); - break; - case PROG_SECTION_GAME: - gameDirector->runGame(); - break; - } - } + // Bucle principal + mDirector->run(); // Libera todos los recursos y cierra SDL - delete gameDirector; - gameDirector = nullptr; + delete mDirector; + mDirector = nullptr; printf("Shutting down the game...\n"); return 0; diff --git a/source/menu.cpp b/source/menu.cpp index a7eefc2..e05d9cb 100644 --- a/source/menu.cpp +++ b/source/menu.cpp @@ -4,20 +4,26 @@ #include "menu.h" // Constructor -Menu::Menu() +Menu::Menu(SDL_Renderer *renderer, Text *text, Input *input, std::string *fileList) { - init("", 0, 0, 0, nullptr, nullptr, nullptr); + mRenderer = renderer; + mText = text; + mInput = input; + mFileList = fileList; } Menu::~Menu() { mRenderer = nullptr; mText = nullptr; + mInput = nullptr; } // Inicializador -void Menu::init(std::string name, int x, int y, int backgroundType, LTexture *texture, SDL_Renderer *renderer, Text *text) +void Menu::init(std::string name, int x, int y, int backgroundType) { + loadMedia(); + // Inicia variables mName = name; mSelector.index = 0; @@ -42,8 +48,6 @@ void Menu::init(std::string name, int x, int y, int backgroundType, LTexture *te mSelector.b = 0; mSelector.a = 255; mBackgroundType = backgroundType; - mText = text; - mRenderer = renderer; mIsCentered = false; mAreElementsCentered = false; mCenter = x + ((SCREEN_WIDTH - x) / 2); @@ -82,6 +86,20 @@ void Menu::init(std::string name, int x, int y, int backgroundType, LTexture *te //moveSelectorSprite(mSelector.index); } +// Carga los recursos necesarios para la sección 'Title' +bool Menu::loadMedia() +{ + // Indicador de éxito en la carga + bool success = true; + + // Sonidos + mSoundMove = JA_LoadSound(mFileList[17].c_str()); + mSoundAccept = JA_LoadSound(mFileList[18].c_str()); + mSoundCancel = JA_LoadSound(mFileList[16].c_str()); + + return success; +} + // Obtiene el nombre del menu std::string Menu::getName() { @@ -91,7 +109,9 @@ std::string Menu::getName() // Obtiene el valor de la variable Uint8 Menu::getItemSelected() { - return mItemSelected; + const int temp = mItemSelected; + mItemSelected = MENU_NO_OPTION; + return temp; } // Mueve el grafico del selector al elemento seleccionado @@ -159,7 +179,7 @@ Uint16 Menu::getWidestItem() Uint16 result = 0; // Obtenemos la anchura del item mas ancho - for (Uint8 i = 0; i < mTotalItems; i++) + for (int i = 0; i < mTotalItems; i++) { if (mItem[i].w > result) { @@ -232,30 +252,6 @@ bool Menu::decreaseSelectorIndex() return success; } -// Comprueba la entrada (teclado, gamepad) y actua en consecuencia -bool Menu::checkInput(Uint8 input) -{ - bool success = false; - switch (input) - { - case INPUT_UP: - success = decreaseSelectorIndex(); - //moveSelectorSprite(mSelector.index); - break; - case INPUT_DOWN: - success = increaseSelectorIndex(); - //moveSelectorSprite(mSelector.index); - break; - case INPUT_ACCEPT: - mItemSelected = mSelector.index; - break; - case INPUT_CANCEL: - mItemSelected = mDefaultActionWhenCancel; - break; - } - return success; -} - // Actualiza la logica del menu void Menu::update() { @@ -280,11 +276,12 @@ void Menu::render() //mSelectorSprite.render(); // Renderitza el text - for (Uint8 i = 0; i < mTotalItems; i++) + for (int i = 0; i < mTotalItems; i++) { if (i == mSelector.index) { - mText->writeColored(mItem[i].x, mItem[i].y, mItem[i].label, mSelector.itemR, mSelector.itemG, mSelector.itemB); + const color_t color = {mSelector.itemR, mSelector.itemG, mSelector.itemB}; + mText->writeColored(mItem[i].x, mItem[i].y, mItem[i].label, color); } else { @@ -378,7 +375,7 @@ void Menu::centerMenu(int value) mPosX = (value) - (mWidestItem / 2); // Reposiciona los elementos del menu - for (Uint8 i = 0; i < 10; i++) + for (int i = 0; i < 10; i++) { mItem[i].x = mPosX; } @@ -397,7 +394,7 @@ void Menu::centerMenuElements() { mAreElementsCentered = true; - for (Uint8 i = 0; i < mTotalItems; i++) + for (int i = 0; i < mTotalItems; i++) { //mItem[i].x = (mCenter - ((mText->lenght(mItem[i].label, 0)) / 2)); mItem[i].x = (mCenter - (mItem[i].w / 2)); @@ -453,3 +450,31 @@ void Menu::setDefaultActionWhenCancel(Uint8 item) { mDefaultActionWhenCancel = item; } + +// Gestiona la entrada de teclado y mando durante el menu +void Menu::checkInput() +{ + if (mInput->checkInput(INPUT_UP, REPEAT_FALSE)) + { + if (decreaseSelectorIndex()) + JA_PlaySound(mSoundMove); + } + + if (mInput->checkInput(INPUT_DOWN, REPEAT_FALSE)) + { + if (increaseSelectorIndex()) + JA_PlaySound(mSoundMove); + } + + if (mInput->checkInput(INPUT_ACCEPT, REPEAT_FALSE)) + { + mItemSelected = mSelector.index; + JA_PlaySound(mSoundAccept); + } + + if (mInput->checkInput(INPUT_CANCEL, REPEAT_FALSE)) + { + mItemSelected = mDefaultActionWhenCancel; + JA_PlaySound(mSoundCancel); + } +} \ No newline at end of file diff --git a/source/menu.h b/source/menu.h index 25e6df4..a859cd1 100644 --- a/source/menu.h +++ b/source/menu.h @@ -1,6 +1,8 @@ #pragma once #include "sprite.h" #include "text.h" +#include "input.h" +#include "jail_audio.h" #ifndef MENU_H #define MENU_H @@ -8,65 +10,73 @@ // Clase menu class Menu { -public: - // Constructor - Menu(); - - // Destructor - ~Menu(); - - // Inicializador - void init(std::string name, int x, int y, int backgroundType, LTexture *texture, SDL_Renderer *renderer, Text *text); - - // Obtiene el nombre del menu - std::string getName(); - - // Obtiene el valor de la variable - Uint8 getItemSelected(); - - // Deja el menu apuntando al primer elemento - void reset(); - - // Deja el menu sin elemento seleccionado - void deselectItem(); - - // Comprueba la entrada (teclado, gamepad) y actua en consecuencia - bool checkInput(Uint8 input); - - // Actualiza la logica del menu - void update(); - - // Pinta el menu en pantalla - void render(); - - // Establece el color del rectangulo de fondo - void setBackgroundColor(int r, int g, int b, int alpha); - - // Establece el color del rectangulo del selector - void setSelectorColor(int r, int g, int b, int alpha); - - // Establece el color del texto del selector - void setSelectorTextColor(int r, int g, int b); - - // Centra el menu respecto a un punto - void centerMenu(int value); - - // Centra los elementos del menu - void centerMenuElements(); - - // Añade un item al menu - void addItem(std::string text, const Uint8 hPaddingUp = 0, const Uint8 hPaddingDown = 0); - - // Cambia el texto de un item - void setItemCaption(Uint8 index, std::string text); - - // Establece el indice del item que se usará por defecto al cancelar el menu - void setDefaultActionWhenCancel(Uint8 item); - - // Coloca el selector en una posición específica - void setSelectorPos(Uint8 index); - private: + int mPosX; // Posición en el eje X de la primera letra del primer elemento + int mPosY; // Posición en el eje Y de la primera letra del primer elemento + std::string mName; // Nombre del menu + Uint8 mTotalItems; // Numero total de items del menu + int mItemSelected; // Índice del item del menu que ha sido seleccionado + Uint8 mDefaultActionWhenCancel; // Indice del item del menu que se selecciona cuando se cancela el menu + Uint8 mVerticalPadding; // Espacio de separacion entre items + Uint8 mBackgroundType; // Tipo de fondo para el menu + Sprite *mSelectorSprite; // Sprite con los graficos del selector + Text *mText; // Texto para poder escribir los items del menu + SDL_Renderer *mRenderer; // Puntero al renderizador de la ventana + std::string *mFileList; // Lista de ficheros + bool mIsCentered; // Variable para saber si el menu debe estar centrado respecto a un punto + int mCenter; // Centro del menu + bool mAreElementsCentered; // Variable para saber si los elementos van centrados + Uint16 mWidestItem; // Anchura del elemento más ancho + JA_Sound mSoundAccept; // Sonido al aceptar o elegir una opción del menu + JA_Sound mSoundCancel; // Sonido al cancelar el menu + JA_Sound mSoundMove; // Sonido al mover el selector + Input *mInput; // Gestor de eventos de entrada de teclado o gamepad + + struct rectangle + { + SDL_Rect rect; // Rectangulo + Uint8 r; // Rojo + Uint8 g; // Verde + Uint8 b; // Azul + Uint8 a; // Transparencia + }; + rectangle mRectBG; // Rectangulo de fondo del menu + + struct item + { + std::string label; // Texto + int x; // Posición en el eje X de la primera letra del elemento + int y; // Posición en el eje Y de la primera letra del elemento + Uint8 w; // Ancho del elemento + Uint8 h; // Alto del elemento + Uint8 hPaddingUp; // Espaciado sobre el elemento + Uint8 hPaddingDown; // Espaciado bajo el elemento + }; + item mItem[10]; // Estructura para cada elemento del menu + + struct selector + { + double origin; // Coordenada de origen + double target; // Coordenada de destino + double y; // Coordenada actual + Uint8 numJumps; // Numero de pasos preestablecido para llegar al destino + double despY; // Cantidad de pixeles que se desplaza el selector en cada salto: (target - origin) / numJumps + bool moving; // Indica si el selector está avanzando hacia el destino + Uint8 index; // Elemento del menu que tiene el foco + SDL_Rect rect; // Rectangulo del selector + Uint8 r; // Cantidad de color rojo para el rectangulo del selector + Uint8 g; // Cantidad de color verde para el rectangulo del selector + Uint8 b; // Cantidad de color azul para el rectangulo del selector + Uint8 a; // Cantidad de transparencia para el rectangulo del selector + Uint8 itemR; // Cantidad de color rojo para el texto del elemento seleccionado + Uint8 itemG; // Cantidad de color verde para el texto del elemento seleccionado + Uint8 itemB; // Cantidad de color azul para el texto del elemento seleccionado + }; + selector mSelector; // Variables para pintar el selector del menu + + // Carga los recursos necesarios para la sección 'Title' + bool loadMedia(); + // Establece el valor de la variable void setTotalItems(int num); @@ -97,94 +107,66 @@ private: // Obtiene la anchura del elemento más ancho del menu Uint16 getWidestItem(); - // Posicion X/Y del texto del primer elemento del menu - int mPosX; // En esta posición se pinta la primera letra del primer elemento - int mPosY; + // Gestiona la entrada de teclado y mando durante el menu + void checkMenuInput(Menu *menu); - // Nombre del menu - std::string mName; +public: + // Constructor + Menu(SDL_Renderer *renderer, Text *text, Input *input, std::string *fileList); - // Numero de items del menu - Uint8 mTotalItems; + // Destructor + ~Menu(); - // Item del menu que ha sido seleccionado - Uint8 mItemSelected; + // Inicializador + void init(std::string name, int x, int y, int backgroundType); - // Item del menu seleccionado cuando se cancela el menu - Uint8 mDefaultActionWhenCancel; + // Obtiene el nombre del menu + std::string getName(); - // Espacio de separacion entre items - Uint8 mVerticalPadding; + // Obtiene el valor de la variable + Uint8 getItemSelected(); - // Tipo de fondo para el menu - Uint8 mBackgroundType; + // Deja el menu apuntando al primer elemento + void reset(); - // Sprite con los graficos del selector - //Sprite mSelectorSprite; + // Deja el menu sin elemento seleccionado + void deselectItem(); - struct rectangle - { - SDL_Rect rect; - Uint8 r; // Rojo - Uint8 g; // Verde - Uint8 b; // Azul - Uint8 a; // Transparencia - }; + // Gestiona la entrada de teclado y mando durante el menu + void checkInput(); - rectangle mRectBG; // Rectangulo de fondo del menu + // Actualiza la logica del menu + void update(); - // Estructura para cada elemento del menu - struct item - { - std::string label; - int x; - int y; - Uint8 w; - Uint8 h; - Uint8 hPaddingUp; - Uint8 hPaddingDown; - }; + // Pinta el menu en pantalla + void render(); - item mItem[10]; + // Establece el color del rectangulo de fondo + void setBackgroundColor(int r, int g, int b, int alpha); - // Texto para poder escribir los items del menu - Text *mText; + // Establece el color del rectangulo del selector + void setSelectorColor(int r, int g, int b, int alpha); - // Puntero al renderizador de la ventana - SDL_Renderer *mRenderer; + // Establece el color del texto del selector + void setSelectorTextColor(int r, int g, int b); - // Variable para saber si el menu debe estar centrado respecto a un punto - bool mIsCentered; + // Centra el menu respecto a un punto + void centerMenu(int value); - // Centro del menu - int mCenter; + // Centra los elementos del menu + void centerMenuElements(); - // Variable para saber si los elementos van centrados - bool mAreElementsCentered; + // Añade un item al menu + void addItem(std::string text, const Uint8 hPaddingUp = 0, const Uint8 hPaddingDown = 0); - // Anchura del elemento más ancho - Uint16 mWidestItem; + // Cambia el texto de un item + void setItemCaption(Uint8 index, std::string text); - struct selector - { - double origin; // Coordenada de origen - double target; // Coordenada de destino - double y; // Coordenada actual - Uint8 numJumps; // Numero de pasos preestablecido para llegar al destino - double despY; // (target - origin) / numJumps - bool moving; // Indica si el selector está avanzando hacia el destino - Uint8 index; // Elemento del menu que tiene el foco - SDL_Rect rect; - Uint8 r; // Rojo - Uint8 g; // Verde - Uint8 b; // Azul - Uint8 a; // Transparencia - Uint8 itemR; // Rojo - Uint8 itemG; // Verde - Uint8 itemB; // Azul - }; + // Establece el indice del item que se usará por defecto al cancelar el menu + void setDefaultActionWhenCancel(Uint8 item); - selector mSelector; + // Coloca el selector en una posición específica + void setSelectorPos(Uint8 index); }; #endif diff --git a/source/player.cpp b/source/player.cpp index 836815d..96f9682 100644 --- a/source/player.cpp +++ b/source/player.cpp @@ -281,7 +281,7 @@ void Player::setFiringStatus(Uint8 status) void Player::setAnimation() { // Actualiza los frames de la animación en función del número de cafes - for (Uint8 i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT, i, mWidth * i, mHeight * (0 + (6 * mCoffees)), mWidth, mHeight); mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT, i, mWidth * i, mHeight * (1 + (6 * mCoffees)), mWidth, mHeight); diff --git a/source/player.h b/source/player.h index 8681590..c35c7ad 100644 --- a/source/player.h +++ b/source/player.h @@ -1,5 +1,6 @@ #pragma once #include "utils.h" +#include "input.h" #include "animatedsprite.h" #ifndef PLAYER_H diff --git a/source/text.cpp b/source/text.cpp index 93666cd..f0a7deb 100644 --- a/source/text.cpp +++ b/source/text.cpp @@ -2,10 +2,11 @@ #include "text.h" // Constructor -Text::Text() +Text::Text(LTexture *texture, SDL_Renderer *renderer) { mSprite = new Sprite(); - init(nullptr, nullptr, 0, 0); + mSprite->setTexture(texture); + mSprite->setRenderer(renderer); } // Destructor @@ -15,7 +16,7 @@ Text::~Text() } // Inicializador -void Text::init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size) +void Text::init(Uint8 type, Uint8 size) { // Inicializa variables mType = type; @@ -26,15 +27,13 @@ void Text::init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 siz mSprite->setHeight(size); mSprite->setPosX(0); mSprite->setPosY(0); - mSprite->setTexture(texture); - mSprite->setRenderer(renderer); mSprite->setSpriteClip(0, 0, mSprite->getWidth(), mSprite->getHeight()); // Cadena con los caracteres ascii que se van a inicializar - std::string text = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ{\\[]]^_`abcdefghijklmnopqrstuvwxyz"; + const std::string text = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ{\\[]]^_`abcdefghijklmnopqrstuvwxyz"; // Inicializa a cero el vector con las coordenadas - for (Uint8 i = 0; i < 255; i++) + for (int i = 0; i < 255; i++) { mOffset[i].x = 0; mOffset[i].y = 0; @@ -42,14 +41,12 @@ void Text::init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 siz } // Establece las coordenadas para cada caracter ascii de la cadena y su ancho - for (Uint8 i = 0; i < text.length(); ++i) + for (int i = 0; i < text.length(); ++i) { mOffset[int(text[i])].x = ((int(text[i]) - 32) % 15) * mSprite->getWidth(); mOffset[int(text[i])].y = ((int(text[i]) - 32) / 15) * mSprite->getHeight(); if (type == TEXT_FIXED) - { mOffset[int(text[i])].w = size; - } } // Establece el ancho de cada caracter @@ -133,25 +130,15 @@ void Text::init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 siz } } -// Escribe el texto en pantalla -void Text::write(int x, int y, std::string text) +// Escribe texto en pantalla +void Text::write(int x, int y, std::string text, int kerning, Uint8 lenght) { Uint16 shift = 0; - for (Uint8 i = 0; i < text.length(); ++i) - { - mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight()); - mSprite->setPosX(x + shift); - mSprite->setPosY(y); - mSprite->render(); - shift += (mOffset[int(text[i])].w); - } -} -// Escribe el texto en pantalla con kerning -void Text::write(int x, int y, std::string text, int kerning) -{ - Uint16 shift = 0; - for (Uint8 i = 0; i < text.length(); ++i) + if (lenght == 0) + lenght = text.length(); + + for (int i = 0; i < lenght; ++i) { mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight()); mSprite->setPosX(x + shift); @@ -161,88 +148,57 @@ void Text::write(int x, int y, std::string text, int kerning) } } -// Escribe una cantidad determinada de caracteres del texto en pantalla -void Text::write(int x, int y, std::string text, int kerning, Uint8 lenght) -{ - Uint16 shift = 0; - for (Uint8 i = 0; i < lenght; ++i) - { - if (text[i] == '*') - { - shift = 0; - y += mSize; - } - else - { - mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight()); - mSprite->setPosX(x + shift); - mSprite->setPosY(y); - mSprite->render(); - shift += (mOffset[int(text[i])].w + kerning); - } - } -} - // Escribe el texto con colores -void Text::writeColored(int x, int y, std::string text, Uint8 R, Uint8 G, Uint8 B) +void Text::writeColored(int x, int y, std::string text, color_t color, int kerning, Uint8 lenght) { - mSprite->getTexture()->setColor(R, G, B); - write(x, y, text); + mSprite->getTexture()->setColor(color.r, color.g, color.b); + write(x, y, text, kerning, lenght); mSprite->getTexture()->setColor(255, 255, 255); } // Escribe el texto con sombra -void Text::writeShadowed(int x, int y, std::string text, Uint8 R, Uint8 G, Uint8 B) +void Text::writeShadowed(int x, int y, std::string text, color_t color, Uint8 shadowDistance, int kerning, Uint8 lenght) { - mSprite->getTexture()->setColor(R, G, B); - write(x+1, y+1, text); + mSprite->getTexture()->setColor(color.r, color.g, color.b); + write(x + shadowDistance, y + shadowDistance, text, kerning, lenght); mSprite->getTexture()->setColor(255, 255, 255); - write(x, y, text); + write(x, y, text, kerning, lenght); } -// Escribe el texto centrado en un punto x y con kerning -void Text::writeCentered(int x, int y, std::string text, int kerning) +// Escribe el texto centrado en un punto x +void Text::writeCentered(int x, int y, std::string text, int kerning, Uint8 lenght) { - // Uint16 lenght = Text::lenght(text, kerning); - x = x - (Text::lenght(text, kerning) / 2); - Uint16 shift = 0; - for (Uint8 i = 0; i < text.length(); ++i) - { - mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight()); - mSprite->setPosX(x + shift); - mSprite->setPosY(y); - mSprite->render(); - shift += (mOffset[int(text[i])].w + kerning); - } + x -= (Text::lenght(text, kerning) / 2); + write(x, y, text, kerning, lenght); } -// Escribe el texto centrado en un punto x y con kerning -void Text::writeCenteredAndColored(int x, int y, std::string text, int kerning, Uint8 R, Uint8 G, Uint8 B) +// Escribe texto con extras +void Text::writeDX(Uint8 flags, int x, int y, std::string text, int kerning, color_t textColor, Uint8 shadowDistance, color_t shadowColor, Uint8 lenght) { - mSprite->getTexture()->setColor(R, G, B); + const bool centered = ((flags & TXT_CENTER) == TXT_CENTER); + const bool shadowed = ((flags & TXT_SHADOW) == TXT_SHADOW); + const bool colored = ((flags & TXT_COLOR) == TXT_COLOR); - x = x - (Text::lenght(text, kerning) / 2); - Uint16 shift = 0; - for (Uint8 i = 0; i < text.length(); ++i) - { - mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight()); - mSprite->setPosX(x + shift); - mSprite->setPosY(y); - mSprite->render(); - shift += (mOffset[int(text[i])].w + kerning); - } + if (centered) + x -= (Text::lenght(text, kerning) / 2); - mSprite->getTexture()->setColor(255, 255, 255); + if (shadowed) + writeColored(x + shadowDistance, y + shadowDistance, text, shadowColor, kerning, lenght); + + if (colored) + writeColored(x, y, text, textColor, kerning, lenght); + else + write(x, y, text, kerning, lenght); } // Obtiene la longitud en pixels de una cadena Uint16 Text::lenght(std::string text, int kerning) { Uint16 shift = 0; - for (Uint8 i = 0; i < text.length(); ++i) - { + + for (int i = 0; i < text.length(); ++i) shift += (mOffset[int(text[i])].w + kerning); - } + return shift; } diff --git a/source/text.h b/source/text.h index 22a2ad7..4c4cb8a 100644 --- a/source/text.h +++ b/source/text.h @@ -1,9 +1,14 @@ #pragma once #include "sprite.h" +#include "utils.h" #ifndef TEXT_H #define TEXT_H +#define TXT_COLOR 1 +#define TXT_SHADOW 2 +#define TXT_CENTER 4 + // Clase texto. Pinta texto en pantalla a partir de un bitmap class Text { @@ -23,30 +28,28 @@ private: public: // Constructor - Text(); + Text(LTexture *texture, SDL_Renderer *renderer); // Destructor ~Text(); // Inicializador - void init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size); + void init(Uint8 type, Uint8 size); // Escribe el texto en pantalla - void write(int x, int y, std::string text); - void write(int x, int y, std::string text, int kerning); - void write(int x, int y, std::string text, int kerning, Uint8 lenght); + void write(int x, int y, std::string text, int kerning = 0, Uint8 lenght = 0); // Escribe el texto con colores - void writeColored(int x, int y, std::string text, Uint8 R, Uint8 G, Uint8 B); + void writeColored(int x, int y, std::string text, color_t color, int kerning = 0, Uint8 lenght = 0); // Escribe el texto con sombra - void writeShadowed(int x, int y, std::string text, Uint8 R, Uint8 G, Uint8 B); + void writeShadowed(int x, int y, std::string text, color_t color, Uint8 shadowDistance = 1, int kerning = 0, Uint8 lenght = 0); // Escribe el texto centrado en un punto x y con kerning - void writeCentered(int x, int y, std::string text, int kerning = 0); + void writeCentered(int x, int y, std::string text, int kerning = 0, Uint8 lenght = 0); - // Escribe el texto centrado en un punto x y con kerning - void writeCenteredAndColored(int x, int y, std::string text, int kerning = 0, Uint8 R = 255, Uint8 G = 255, Uint8 B = 255); + // Escribe texto con extras + void writeDX(Uint8 flags, int x, int y, std::string text, int kerning = 0, color_t textColor = {255, 255, 255}, Uint8 shadowDistance = 1, color_t shadowColor = {0, 0, 0}, Uint8 lenght = 0); // Obtiene la longitud en pixels de una cadena Uint16 lenght(std::string text, int kerning); diff --git a/source/text2.cpp b/source/text2.cpp index 6b9586c..02a2974 100644 --- a/source/text2.cpp +++ b/source/text2.cpp @@ -2,21 +2,19 @@ #include "text2.h" // Constructor -Text2::Text2() +Text2::Text2(LTexture *texture, SDL_Renderer *renderer) : Text(texture, renderer) { - init(nullptr, nullptr, 0, 0); } // Destructor Text2::~Text2() { - init(nullptr, nullptr, 0, 0); } // Inicializador -void Text2::init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size) +void Text2::init(Uint8 type, Uint8 size) { - Text::init(texture, renderer, type, size); + Text::init(type, size); mPosX = 0; mPosY = 0; mKerning = 0; diff --git a/source/text2.h b/source/text2.h index 9366d61..8275bcf 100644 --- a/source/text2.h +++ b/source/text2.h @@ -10,13 +10,13 @@ class Text2 : public Text { public: // Constructor - Text2(); + Text2(LTexture *texture, SDL_Renderer *renderer); // Destructor ~Text2(); // Inicializador - void init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size); + void init(Uint8 type, Uint8 size); // Establece el valor de la variable void setPosX(int value); diff --git a/source/utils.cpp b/source/utils.cpp index c6cb741..2b28c40 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -109,4 +109,16 @@ bool checkCollision(SDL_Rect &a, SDL_Rect &b) //If none of the sides from A are outside B return true; +} + +// Carga un archivo de imagen en una textura +bool loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer) +{ + bool success = true; + if (!texture->loadFromFile(path, renderer)) + { + printf("Failed to load %s texture!\n", path.c_str()); + success = false; + } + return success; } \ No newline at end of file diff --git a/source/utils.h b/source/utils.h index 8b188eb..da026d0 100644 --- a/source/utils.h +++ b/source/utils.h @@ -1,5 +1,6 @@ #pragma once #include "ifdefs.h" +#include "ltexture.h" #ifndef UTILS_H #define UTILS_H @@ -12,20 +13,19 @@ struct circle_t Uint8 r; }; -// Estructura para definir todas las entradas que aceptará el programa -struct input_t +// Estructura para definir un color +struct color_t { - Uint8 up; - Uint8 down; - Uint8 left; - Uint8 right; - Uint8 escape; - Uint8 pause; - Uint8 fire; - Uint8 fireLeft; - Uint8 fireRight; - Uint8 accept; - Uint8 cancel; + Uint8 r; + Uint8 g; + Uint8 b; +}; + +// Estructura para saber la seccion y subseccion del programa +struct section_t +{ + Uint8 name; + Uint8 subsection; }; // Estructura para mapear el teclado usado en la demo @@ -39,6 +39,15 @@ struct demoKeys_t Uint8 fireRight; }; +// Estructura con todas las opciones de configuración del programa +struct options_t +{ + Uint32 fullScreenMode; // Contiene el valor del modo de pantalla completa + Uint32 fullScreenModePrevious; // Usado por si se cancelan los cambios en el menu de opciones + Uint8 windowSize; // Contiene el valor del tamaño de la ventana + Uint8 windowSizePrevious; // Usado por si se cancelan los cambios en el menu de opciones +}; + // Calcula el cuadrado de la distancia entre dos puntos double distanceSquared(int x1, int y1, int x2, int y2); @@ -51,4 +60,7 @@ bool checkCollision(circle_t &a, SDL_Rect &b); // Detector de colisiones entre un dos rectangulos bool checkCollision(SDL_Rect a, SDL_Rect b); +// Carga un archivo de imagen en una textura +bool loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer); + #endif \ No newline at end of file