diff --git a/source/background.cpp b/source/background.cpp index a93b0b0..9ad7daf 100644 --- a/source/background.cpp +++ b/source/background.cpp @@ -6,35 +6,36 @@ #include "moving_sprite.h" // for MovingSprite #include "param.h" // for param #include "resource.h" // for Resource -#include "sprite.h" // for Sprite -#include "texture.h" // for Texture +#include "screen.h" +#include "sprite.h" // for Sprite +#include "texture.h" // for Texture // Constructor -Background::Background(SDL_Renderer *renderer) - : renderer_(renderer), +Background::Background() + : renderer_(Screen::get()->getRenderer()), + buildings_texture_(Resource::get()->getTexture("game_buildings.png")), top_clouds_texture_(Resource::get()->getTexture("game_clouds1.png")), bottom_clouds_texture_(Resource::get()->getTexture("game_clouds2.png")), grass_texture_(Resource::get()->getTexture("game_grass.png")), - gradients_texture_(Resource::get()->getTexture("game_sky_colors.png")) + gradients_texture_(Resource::get()->getTexture("game_sky_colors.png")), + + gradient_number_(0), + alpha_(0), + clouds_speed_(0), + transition_(0), + counter_(0), + rect_({0, 0, gradients_texture_->getWidth() / 2, gradients_texture_->getHeight() / 2}), + src_rect_({0, 0, 320, 240}), + dst_rect_({0, 0, 320, 240}), + base_(rect_.h), + color_({param.background.attenuate_color.r, param.background.attenuate_color.g, param.background.attenuate_color.b}), + alpha_color_text_(param.background.attenuate_alpha), + alpha_color_text_temp_(param.background.attenuate_alpha) { // Inicializa variables { - gradient_number_ = 0; - alpha_ = 0; - clouds_speed_ = 0; - transition_ = 0; - counter_ = 0; - - rect_ = {0, 0, gradients_texture_->getWidth() / 2, gradients_texture_->getHeight() / 2}; - src_rect_ = {0, 0, 320, 240}; - dst_rect_ = {0, 0, 320, 240}; - - base_ = rect_.h; - color_ = {param.background.attenuate_color.r, param.background.attenuate_color.g, param.background.attenuate_color.b}; - alpha_color_text_ = alpha_color_text_temp_ = param.background.attenuate_alpha; - gradient_rect_[0] = {0, 0, rect_.w, rect_.h}; gradient_rect_[1] = {rect_.w, 0, rect_.w, rect_.h}; gradient_rect_[2] = {0, rect_.h, rect_.w, rect_.h}; @@ -87,11 +88,11 @@ Background::Background(SDL_Renderer *renderer) } // Crea la textura para componer el fondo - canvas_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h); + canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h); SDL_SetTextureBlendMode(canvas_, SDL_BLENDMODE_BLEND); // Crea la textura para atenuar el fondo - color_texture_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h); + color_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h); SDL_SetTextureBlendMode(color_texture_, SDL_BLENDMODE_BLEND); setColor(color_); SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_); @@ -120,7 +121,7 @@ void Background::update() alpha_ = std::max((255 - (int)(255 * transition_)), 0); // Incrementa el contador - counter_++; + ++counter_; // Compone todos los elementos del fondo en la textura fillCanvas(); diff --git a/source/background.h b/source/background.h index addf56c..7b64ee7 100644 --- a/source/background.h +++ b/source/background.h @@ -107,7 +107,7 @@ private: public: // Constructor - explicit Background(SDL_Renderer *renderer); + Background(); // Destructor ~Background(); diff --git a/source/game.cpp b/source/game.cpp index 74d012a..39e7f64 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -55,11 +55,11 @@ Game::Game(int player_id, int current_stage, bool demo) difficulty_ = options.game.difficulty; // Crea los objetos - Scoreboard::init(renderer_); + Scoreboard::init(); scoreboard_ = Scoreboard::get(); fade_ = std::make_unique(); - background_ = std::make_unique(renderer_); + background_ = std::make_unique(); explosions_ = std::make_unique(); balloon_formations_ = std::make_unique(); @@ -69,10 +69,10 @@ Game::Game(int player_id, int current_stage, bool demo) // Inicializa los vectores con los datos para la demo if (demo_.enabled) { // Aleatoriza la asignación del fichero - const auto index1 = rand() % 2; - const auto index2 = (index1 + 1) % 2; - loadDemoFile(asset_->get("demo1.bin"), &this->demo_.data_file[index1]); - loadDemoFile(asset_->get("demo2.bin"), &this->demo_.data_file[index2]); + const std::string demo1 = rand() % 2 == 0 ? "demo1.bin" : "demo2.bin"; + const std::string demo2 = (demo1 == "demo1.bin") ? "demo2.bin" : "demo1.bin"; + demo_.data.emplace_back(loadDemoDataFromFile(asset_->get(demo1))); + demo_.data.emplace_back(loadDemoDataFromFile(asset_->get(demo2))); } background_->setPos(param.game.play_area.rect); @@ -98,7 +98,7 @@ Game::~Game() manager->saveToFile(asset_->get("score.bin")); } #ifdef RECORDING - saveDemoFile(asset->get("demo1.bin")); + saveDemoFile(Asset::get()->get("demo1.bin")); #endif // Elimina todos los objetos contenidos en vectores @@ -115,9 +115,6 @@ Game::~Game() // Inicializa las variables necesarias para la sección 'Game' void Game::init(int player_id) { - ticks_ = 0; - ticks_speed_ = 15; - // Elimina qualquier jugador que hubiese antes de crear los nuevos players_.clear(); @@ -192,6 +189,7 @@ void Game::init(int player_id) scoreboard_->setMode(SCOREBOARD_CENTER_PANEL, ScoreboardMode::STAGE_INFO); // Resto de variables + ticks_ = 0; hi_score_.score = options.game.hi_score_table[0].score; hi_score_.name = options.game.hi_score_table[0].name; paused_ = false; @@ -203,8 +201,8 @@ void Game::init(int player_id) menace_current_ = 0; menace_threshold_ = 0; hi_score_achieved_ = false; - stage_bitmap_counter_ = STAGE_COUNTER; - game_over_counter_ = GAME_OVER_COUNTER; + stage_bitmap_counter_ = STAGE_COUNTER_; + game_over_counter_ = GAME_OVER_COUNTER_; time_stopped_ = false; time_stopped_counter_ = 0; counter_ = 0; @@ -214,13 +212,13 @@ void Game::init(int player_id) helper_.need_coffee = false; helper_.need_coffee_machine = false; helper_.need_power_ball = false; - helper_.counter = HELP_COUNTER; - helper_.item_disk_odds = ITEM_POINTS_1_DISK_ODDS; - helper_.item_gavina_odds = ITEM_POINTS_2_GAVINA_ODDS; - helper_.item_pacmar_odds = ITEM_POINTS_3_PACMAR_ODDS; - helper_.item_clock_odds = ITEM_CLOCK_ODDS; - helper_.item_coffee_odds = ITEM_COFFEE_ODDS; - helper_.item_coffee_machine_odds = ITEM_COFFEE_MACHINE_ODDS; + helper_.counter = HELP_COUNTER_; + helper_.item_disk_odds = ITEM_POINTS_1_DISK_ODDS_; + helper_.item_gavina_odds = ITEM_POINTS_2_GAVINA_ODDS_; + helper_.item_pacmar_odds = ITEM_POINTS_3_PACMAR_ODDS_; + helper_.item_clock_odds = ITEM_CLOCK_ODDS_; + helper_.item_coffee_odds = ITEM_COFFEE_ODDS_; + helper_.item_coffee_machine_odds = ITEM_COFFEE_MACHINE_ODDS_; power_ball_enabled_ = false; power_ball_counter_ = 0; coffee_machine_enabled_ = false; @@ -282,7 +280,7 @@ void Game::init(int player_id) // Modo grabar demo #ifdef RECORDING - demo.recording = true; + demo_.recording = true; #else demo_.recording = false; #endif @@ -422,10 +420,11 @@ void Game::unloadMedia() } // Carga el fichero de datos para la demo -bool Game::loadDemoFile(const std::string &file_path, DemoKeys (*data_file)[TOTAL_DEMO_DATA]) +DemoData Game::loadDemoDataFromFile(const std::string &file_path) { + DemoData dd; + // Indicador de éxito en la carga - auto success = true; const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1); auto file = SDL_RWFromFile(file_path.c_str(), "r+b"); if (!file) @@ -443,14 +442,8 @@ bool Game::loadDemoFile(const std::string &file_path, DemoKeys (*data_file)[TOTA // Inicializas los datos y los guarda en el fichero for (int i = 0; i < TOTAL_DEMO_DATA; ++i) { - DemoKeys dk; - dk.left = 0; - dk.right = 0; - dk.no_input = 0; - dk.fire = 0; - dk.fire_left = 0; - dk.fire_right = 0; - (*data_file)[i] = dk; + DemoKeys dk = DemoKeys(); + dd.push_back(dk); SDL_RWwrite(file, &dk, sizeof(DemoKeys), 1); } @@ -460,7 +453,6 @@ bool Game::loadDemoFile(const std::string &file_path, DemoKeys (*data_file)[TOTA else { // Si no puede crear el fichero std::cout << "Error: Unable to create file " << file_name.c_str() << std::endl; - success = false; } } // El fichero existe @@ -472,16 +464,16 @@ bool Game::loadDemoFile(const std::string &file_path, DemoKeys (*data_file)[TOTA // Lee todos los datos del fichero y los deja en el destino for (int i = 0; i < TOTAL_DEMO_DATA; ++i) { - DemoKeys tmp; - SDL_RWread(file, &tmp, sizeof(DemoKeys), 1); - (*data_file)[i] = tmp; + DemoKeys dk = DemoKeys(); + SDL_RWread(file, &dk, sizeof(DemoKeys), 1); + dd.push_back(dk); } // Cierra el fichero SDL_RWclose(file); } - return success; + return dd; } #ifdef RECORDING @@ -497,7 +489,7 @@ bool Game::saveDemoFile(const std::string &file_path) // Guarda los datos for (int i = 0; i < TOTAL_DEMO_DATA; ++i) { - SDL_RWwrite(file, &demo.dataFile[0][i], sizeof(DemoKeys), 1); + SDL_RWwrite(file, &demo_.data[0][i], sizeof(DemoKeys), 1); } std::cout << "Writing file " << file_name.c_str() << std::endl; @@ -669,7 +661,7 @@ void Game::updateStage() } // Incrementa el contador del bitmap que aparece mostrando el cambio de fase - if (stage_bitmap_counter_ < STAGE_COUNTER) + if (stage_bitmap_counter_ < STAGE_COUNTER_) { stage_bitmap_counter_++; } @@ -1195,8 +1187,6 @@ void Game::renderItems() // Devuelve un item al azar y luego segun sus probabilidades ItemType Game::dropItem() { - return ItemType::COFFEE_MACHINE; - const auto lucky_number = rand() % 100; const auto item = rand() % 6; @@ -1233,7 +1223,7 @@ ItemType Game::dropItem() case 4: if (lucky_number < helper_.item_coffee_odds) { - helper_.item_coffee_odds = ITEM_COFFEE_ODDS; + helper_.item_coffee_odds = ITEM_COFFEE_ODDS_; return ItemType::COFFEE; } else @@ -1248,7 +1238,7 @@ ItemType Game::dropItem() case 5: if (lucky_number < helper_.item_coffee_machine_odds) { - helper_.item_coffee_machine_odds = ITEM_COFFEE_MACHINE_ODDS; + helper_.item_coffee_machine_odds = ITEM_COFFEE_MACHINE_ODDS_; if (!coffee_machine_enabled_ && helper_.need_coffee_machine) { return ItemType::COFFEE_MACHINE; @@ -1447,7 +1437,7 @@ void Game::updateTimeStoppedCounter() if (time_stopped_counter_ > 0) { time_stopped_counter_--; - stopAllBalloons(TIME_STOPPED_COUNTER); + stopAllBalloons(TIME_STOPPED_COUNTER_); } else { @@ -1469,7 +1459,7 @@ void Game::updateBalloonDeployCounter() void Game::update() { // Comprueba que la diferencia de ticks sea mayor a la velocidad del juego - if (SDL_GetTicks() - ticks_ > ticks_speed_) + if (SDL_GetTicks() - ticks_ > TICKS_SPEED_) { // Actualiza el contador de ticks ticks_ = SDL_GetTicks(); @@ -1505,9 +1495,9 @@ void Game::update() checkInput(); // Incrementa el contador de la demo - if (demo.counter < TOTAL_DEMO_DATA) + if (demo_.counter < TOTAL_DEMO_DATA) { - demo.counter++; + demo_.counter++; } // Si se ha llenado el vector con datos, sale del programa @@ -1695,7 +1685,7 @@ void Game::updateMenace() void Game::renderMessages() { // GetReady - if (counter_ < STAGE_COUNTER && !demo_.enabled) + if (counter_ < STAGE_COUNTER_ && !demo_.enabled) { text_nokia2_big_->write((int)get_ready_bitmap_path_[counter_], param.game.play_area.center_y - 8, lang::getText(75), -2); } @@ -1725,7 +1715,7 @@ void Game::renderMessages() } // STAGE NUMBER - if (stage_bitmap_counter_ < STAGE_COUNTER) + if (stage_bitmap_counter_ < STAGE_COUNTER_) { const auto stage_number = balloon_formations_->getStage(current_stage_).number; std::string text; @@ -1755,9 +1745,9 @@ void Game::renderMessages() // Habilita el efecto del item de detener el tiempo void Game::enableTimeStopItem() { - stopAllBalloons(TIME_STOPPED_COUNTER); + stopAllBalloons(TIME_STOPPED_COUNTER_); setTimeStopped(true); - incTimeStoppedCounter(TIME_STOPPED_COUNTER); + incTimeStoppedCounter(TIME_STOPPED_COUNTER_); if (JA_GetMusicState() == JA_MUSIC_PLAYING && !demo_.enabled) { JA_PauseMusic(); @@ -1828,8 +1818,8 @@ void Game::initPaths() } // Letrero de STAGE # - constexpr auto first_part = STAGE_COUNTER / 4; // 50 - constexpr auto second_part = first_part * 3; // 150 + constexpr auto first_part = STAGE_COUNTER_ / 4; // 50 + constexpr auto second_part = first_part * 3; // 150 const auto center_point = param.game.play_area.center_y - (BLOCK * 2); const auto distance = (param.game.play_area.rect.h) - (param.game.play_area.center_y - 16); @@ -1843,7 +1833,7 @@ void Game::initPaths() stage_bitmap_path_[i] = (int)center_point; } - for (int i = second_part; i < STAGE_COUNTER; ++i) + for (int i = second_part; i < STAGE_COUNTER_; ++i) { stage_bitmap_path_[i] = (sin[(int)(((i - 149) * 1.8f) + 90)] * (center_point + 17) - 17); } @@ -1870,7 +1860,7 @@ void Game::initPaths() get_ready_bitmap_path_[i] = (int)finish1; } - for (int i = second_part; i < STAGE_COUNTER; ++i) + for (int i = second_part; i < STAGE_COUNTER_; ++i) { get_ready_bitmap_path_[i] = sin[(int)((i - second_part) * 1.8f)]; get_ready_bitmap_path_[i] *= distance2; @@ -1886,7 +1876,7 @@ void Game::updateGameCompleted() game_completed_counter_++; } - if (game_completed_counter_ == GAME_COMPLETED_END) + if (game_completed_counter_ == GAME_COMPLETED_END_) { section::name = section::Name::TITLE; section::options = section::Options::TITLE_1; @@ -2034,20 +2024,6 @@ void Game::checkEvents() break; } - // Ralentiza mucho la lógica - case SDLK_4: - { - ticks_speed_ *= 10; - break; - } - - // Acelera mucho la lógica - case SDLK_5: - { - ticks_speed_ /= 10; - break; - } - default: break; } @@ -2247,7 +2223,7 @@ void Game::handleDemoMode() // Incluye movimientos (izquierda, derecha, sin movimiento) y disparos automáticos. void Game::handleDemoPlayerInput(const std::shared_ptr &player, int index) { - const auto &demoData = demo_.data_file[index][demo_.counter]; + const auto &demoData = demo_.data[index][demo_.counter]; if (demoData.left == 1) player->setInput(InputType::LEFT); @@ -2307,21 +2283,21 @@ void Game::handleNormalPlayerInput(const std::shared_ptr &player) { player->setInput(InputType::LEFT); #ifdef RECORDING - demo.keys.left = 1; + demo_.keys.left = 1; #endif } else if (input_->checkInput(InputType::RIGHT, INPUT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) { player->setInput(InputType::RIGHT); #ifdef RECORDING - demo.keys.right = 1; + demo_.keys.right = 1; #endif } else { player->setInput(InputType::NONE); #ifdef RECORDING - demo.keys.no_input = 1; + demo_.keys.no_input = 1; #endif } @@ -2335,21 +2311,21 @@ void Game::handleFireInputs(const std::shared_ptr &player, bool autofire { handleFireInput(player, BulletType::UP); #ifdef RECORDING - demo.keys.fire = 1; + demo_.keys.fire = 1; #endif } else if (input_->checkInput(InputType::FIRE_LEFT, autofire, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) { handleFireInput(player, BulletType::LEFT); #ifdef RECORDING - demo.keys.fire_left = 1; + demo_.keys.fire_left = 1; #endif } else if (input_->checkInput(InputType::FIRE_RIGHT, autofire, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) { handleFireInput(player, BulletType::RIGHT); #ifdef RECORDING - demo.keys.fire_right = 1; + demo_.keys.fire_right = 1; #endif } } diff --git a/source/game.h b/source/game.h index 5549d03..feddd2e 100644 --- a/source/game.h +++ b/source/game.h @@ -34,25 +34,6 @@ constexpr bool GAME_MODE_DEMO_ON = true; constexpr int TOTAL_SCORE_DATA = 3; constexpr int TOTAL_DEMO_DATA = 2000; -// Contadores -constexpr int STAGE_COUNTER = 200; -constexpr int HELP_COUNTER = 1000; -constexpr int GAME_COMPLETED_START_FADE = 500; -constexpr int GAME_COMPLETED_END = 700; -constexpr int GAME_OVER_COUNTER = 350; - -// Porcentaje de aparición de los objetos -constexpr int ITEM_POINTS_1_DISK_ODDS = 10; -constexpr int ITEM_POINTS_2_GAVINA_ODDS = 6; -constexpr int ITEM_POINTS_3_PACMAR_ODDS = 3; -constexpr int ITEM_CLOCK_ODDS = 5; -constexpr int ITEM_COFFEE_ODDS = 5; -constexpr int ITEM_POWER_BALL_ODDS = 0; -constexpr int ITEM_COFFEE_MACHINE_ODDS = 4; - -// Valores para las variables asociadas a los objetos -constexpr int TIME_STOPPED_COUNTER = 300; - /* Esta clase gestiona un estado del programa. Se encarga de toda la parte en la que se está jugando. @@ -79,10 +60,22 @@ constexpr int TIME_STOPPED_COUNTER = 300; puntuación mínima. */ +using DemoData = std::vector; + +struct Demo +{ + bool enabled; // Indica si está activo el modo demo + bool recording; // Indica si está activado el modo para grabar la demo + int counter; // Contador para el modo demo + DemoKeys keys; // Variable con las pulsaciones de teclas del modo demo + std::vector data; // Vector con diferentes sets de datos con los movimientos para la demo +}; + // Clase Game class Game { private: + // Estructuras struct Helper { bool need_coffee; // Indica si se necesitan cafes @@ -97,14 +90,25 @@ private: int item_coffee_machine_odds; // Probabilidad de aparición del objeto }; - struct Demo - { - bool enabled; // Indica si está activo el modo demo - bool recording; // Indica si está activado el modo para grabar la demo - int counter; // Contador para el modo demo - DemoKeys keys; // Variable con las pulsaciones de teclas del modo demo - DemoKeys data_file[2][TOTAL_DEMO_DATA]; // Vector con diferentes sets de datos con los movimientos para la demo - }; + // Constantes + + // Contadores + static constexpr int STAGE_COUNTER_ = 200; + static constexpr int HELP_COUNTER_ = 1000; + static constexpr int GAME_COMPLETED_START_FADE_ = 500; + static constexpr int GAME_COMPLETED_END_ = 700; + static constexpr int GAME_OVER_COUNTER_ = 350; + static constexpr int TIME_STOPPED_COUNTER_ = 300; + static constexpr int TICKS_SPEED_ = 15; + + // Porcentaje de aparición de los objetos + static constexpr int ITEM_POINTS_1_DISK_ODDS_ = 10; + static constexpr int ITEM_POINTS_2_GAVINA_ODDS_ = 6; + static constexpr int ITEM_POINTS_3_PACMAR_ODDS_ = 3; + static constexpr int ITEM_CLOCK_ODDS_ = 5; + static constexpr int ITEM_COFFEE_ODDS_ = 5; + static constexpr int ITEM_POWER_BALL_ODDS_ = 0; + static constexpr int ITEM_COFFEE_MACHINE_ODDS_ = 4; // Objetos y punteros SDL_Renderer *renderer_; // El renderizador de la ventana @@ -146,39 +150,38 @@ private: std::unique_ptr fade_; // Objeto para renderizar fades // Variables - Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa - Uint32 ticks_speed_; // Velocidad a la que se repiten los bucles del programa - bool hi_score_achieved_; // Indica si se ha superado la puntuación máxima - HiScoreEntry hi_score_; // Máxima puntuación y nombre de quien la ostenta - int current_stage_; // Indica la fase actual - int stage_bitmap_counter_; // Contador para el tiempo visible del texto de Stage - float stage_bitmap_path_[STAGE_COUNTER]; // Vector con los puntos Y por donde se desplaza el texto - float get_ready_bitmap_path_[STAGE_COUNTER]; // Vector con los puntos X por donde se desplaza el texto - int game_over_counter_; // Contador para el estado de fin de partida - int menace_current_; // Nivel de amenaza actual - int menace_threshold_; // 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 número de globos - bool time_stopped_; // Indica si el tiempo está detenido - int time_stopped_counter_; // Temporizador para llevar la cuenta del tiempo detenido - int counter_; // Contador para el juego - int balloons_popped_; // Lleva la cuenta de los globos explotados - int last_ballon_deploy_; // Guarda cual ha sido la última formación desplegada para no repetir; - int balloon_deploy_counter_; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero - float balloon_speed_; // Velocidad a la que se mueven los enemigos - float default_balloon_speed_; // Velocidad base de los enemigos, sin incrementar - Helper helper_; // Variable para gestionar las ayudas - bool power_ball_enabled_; // Indica si hay una powerball ya activa - int power_ball_counter_; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra - bool coffee_machine_enabled_; // Indica si hay una máquina de café en el terreno de juego - bool game_completed_; // Indica si se ha completado la partida, llegando al final de la ultima pantalla - int game_completed_counter_; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos - GameDifficulty difficulty_; // Dificultad del juego - float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad - Color difficulty_color_; // Color asociado a la dificultad - int last_stage_reached_; // Contiene el número de la última pantalla que se ha alcanzado - Demo demo_; // Variable con todas las variables relacionadas con el modo demo - int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases - bool paused_; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade) - int current_power_; // Poder actual almacenado para completar la fase + Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa + bool hi_score_achieved_; // Indica si se ha superado la puntuación máxima + HiScoreEntry hi_score_; // Máxima puntuación y nombre de quien la ostenta + int current_stage_; // Indica la fase actual + int stage_bitmap_counter_; // Contador para el tiempo visible del texto de Stage + float stage_bitmap_path_[STAGE_COUNTER_]; // Vector con los puntos Y por donde se desplaza el texto + float get_ready_bitmap_path_[STAGE_COUNTER_]; // Vector con los puntos X por donde se desplaza el texto + int game_over_counter_; // Contador para el estado de fin de partida + int menace_current_; // Nivel de amenaza actual + int menace_threshold_; // 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 número de globos + bool time_stopped_; // Indica si el tiempo está detenido + int time_stopped_counter_; // Temporizador para llevar la cuenta del tiempo detenido + int counter_; // Contador para el juego + int balloons_popped_; // Lleva la cuenta de los globos explotados + int last_ballon_deploy_; // Guarda cual ha sido la última formación desplegada para no repetir; + int balloon_deploy_counter_; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero + float balloon_speed_; // Velocidad a la que se mueven los enemigos + float default_balloon_speed_; // Velocidad base de los enemigos, sin incrementar + Helper helper_; // Variable para gestionar las ayudas + bool power_ball_enabled_; // Indica si hay una powerball ya activa + int power_ball_counter_; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra + bool coffee_machine_enabled_; // Indica si hay una máquina de café en el terreno de juego + bool game_completed_; // Indica si se ha completado la partida, llegando al final de la ultima pantalla + int game_completed_counter_; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos + GameDifficulty difficulty_; // Dificultad del juego + float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad + Color difficulty_color_; // Color asociado a la dificultad + int last_stage_reached_; // Contiene el número de la última pantalla que se ha alcanzado + Demo demo_; // Variable con todas las variables relacionadas con el modo demo + int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases + bool paused_; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade) + int current_power_; // Poder actual almacenado para completar la fase #ifdef DEBUG bool auto_pop_balloons_; // Si es true, incrementa automaticamente los globos explotados #endif @@ -202,7 +205,7 @@ private: void unloadMedia(); // Carga el fichero de datos para la demo - bool loadDemoFile(const std::string &file_path, DemoKeys (*data_file)[TOTAL_DEMO_DATA]); + DemoData loadDemoDataFromFile(const std::string &file_path); #ifdef RECORDING // Guarda el fichero de datos para la demo bool saveDemoFile(const std::string &file_path); diff --git a/source/hiscore_table.cpp b/source/hiscore_table.cpp index 812a11b..f7572c1 100644 --- a/source/hiscore_table.cpp +++ b/source/hiscore_table.cpp @@ -23,29 +23,21 @@ // Constructor HiScoreTable::HiScoreTable() + : renderer_(Screen::get()->getRenderer()), + backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), + fade_(std::make_unique()), + background_(std::make_unique()), + text_(std::make_unique(Resource::get()->getTexture("smb2.gif"), Resource::get()->getTextFile("smb2.txt"))), + counter_(0), + ticks_(0), + view_area_({0, 0, param.game.width, param.game.height}), + fade_mode_(FadeMode::IN) { - // Copia punteros - renderer_ = Screen::get()->getRenderer(); - - // Objetos - fade_ = std::make_unique(); - background_ = std::make_unique(renderer_); - text_ = std::make_unique(Resource::get()->getTexture("smb2.gif"), Resource::get()->getTextFile("smb2.txt")); - - // Crea un backbuffer para el renderizador - backbuffer_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height); - SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND); - - // Inicializa variables + // Inicializa el resto de variables section::name = section::Name::HI_SCORE_TABLE; - ticks_ = 0; - ticks_speed_ = 15; - counter_ = 0; - counter_end_ = 800; - view_area_ = {0, 0, param.game.width, param.game.height}; - fade_mode_ = FadeMode::IN; // Inicializa objetos + SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND); background_->setPos(param.game.game_area.rect); background_->setCloudsSpeed(-0.1f); background_->setGradientNumber(1); @@ -70,7 +62,7 @@ HiScoreTable::~HiScoreTable() void HiScoreTable::update() { // Actualiza las variables - if (SDL_GetTicks() - ticks_ > ticks_speed_) + if (SDL_GetTicks() - ticks_ > TICKS_SPEED_) { // Actualiza el contador de ticks ticks_ = SDL_GetTicks(); @@ -99,7 +91,7 @@ void HiScoreTable::update() background_->setAlpha(96); } - if (counter_ == counter_end_) + if (counter_ == COUNTER_END_) { fade_->activate(); } diff --git a/source/hiscore_table.h b/source/hiscore_table.h index 594683a..faa3a10 100644 --- a/source/hiscore_table.h +++ b/source/hiscore_table.h @@ -24,6 +24,10 @@ enum class FadeMode : Uint8; // lines 11-11 class HiScoreTable { private: + // Constantes + static constexpr Uint16 COUNTER_END_ = 800; // Valor final para el contador + static constexpr Uint32 TICKS_SPEED_ = 15; // Velocidad a la que se repiten los bucles del programa + // Objetos y punteros SDL_Renderer *renderer_; // El renderizador de la ventana SDL_Texture *backbuffer_; // Textura para usar como backbuffer @@ -34,9 +38,7 @@ private: // Variables Uint16 counter_; // Contador - Uint16 counter_end_; // Valor final para el contador Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa - Uint32 ticks_speed_; // Velocidad a la que se repiten los bucles del programa SDL_Rect view_area_; // Parte de la textura que se muestra en pantalla FadeMode fade_mode_; // Modo de fade a utilizar diff --git a/source/resource.cpp b/source/resource.cpp index af76e8d..67de36e 100644 --- a/source/resource.cpp +++ b/source/resource.cpp @@ -33,11 +33,9 @@ Resource::Resource() loadTextures(); loadTextFiles(); loadAnimations(); + addPalettes(); std::cout << "\n** RESOURCES LOADED" << std::endl; - std::cout << "\n** ADD PALETTES" << std::endl; - addPalettes(); - std::cout << "\n** PALETTES ADDED" << std::endl; } // Destructor @@ -229,18 +227,16 @@ void Resource::loadAnimations() void Resource::addPalettes() { // Jugador 1 - std::cout << "\n>> PLAYER1" << std::endl; + std::cout << "\n>> PALETTES" << std::endl; getTexture("player1.gif")->addPaletteFromFile(Asset::get()->get("player1_one_coffee_palette.pal")); getTexture("player1.gif")->addPaletteFromFile(Asset::get()->get("player1_two_coffee_palette.pal")); getTexture("player1.gif")->addPaletteFromFile(Asset::get()->get("player1_all_white_palette.pal")); // Jugador 2 - std::cout << "\n>> PLAYER2" << std::endl; getTexture("player2.gif")->addPaletteFromFile(Asset::get()->get("player2_one_coffee_palette.pal")); getTexture("player2.gif")->addPaletteFromFile(Asset::get()->get("player2_two_coffee_palette.pal")); getTexture("player2.gif")->addPaletteFromFile(Asset::get()->get("player2_all_white_palette.pal")); // Fuentes - std::cout << "\n>> FONTS" << std::endl; getTexture("smb2.gif")->addPaletteFromFile(Asset::get()->get("smb2_palette1.pal")); } \ No newline at end of file diff --git a/source/scoreboard.cpp b/source/scoreboard.cpp index 14e0046..585117d 100644 --- a/source/scoreboard.cpp +++ b/source/scoreboard.cpp @@ -8,17 +8,18 @@ #include "asset.h" // for Asset #include "lang.h" // for getText #include "resource.h" // for Resource -#include "sprite.h" // for Sprite -#include "text.h" // for Text -#include "texture.h" // for Texture +#include "screen.h" +#include "sprite.h" // for Sprite +#include "text.h" // for Text +#include "texture.h" // for Texture // [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado Scoreboard *Scoreboard::scoreboard_ = nullptr; // [SINGLETON] Crearemos el objeto score_board con esta función estática -void Scoreboard::init(SDL_Renderer *renderer) +void Scoreboard::init() { - Scoreboard::scoreboard_ = new Scoreboard(renderer); + Scoreboard::scoreboard_ = new Scoreboard(); } // [SINGLETON] Destruiremos el objeto score_board con esta función estática @@ -34,8 +35,8 @@ Scoreboard *Scoreboard::get() } // Constructor -Scoreboard::Scoreboard(SDL_Renderer *renderer) - : renderer_(renderer), +Scoreboard::Scoreboard() + : renderer_(Screen::get()->getRenderer()), game_power_meter_texture_(Resource::get()->getTexture("game_power_meter.png")), power_meter_sprite_(std::make_unique(game_power_meter_texture_)), @@ -107,7 +108,7 @@ std::string Scoreboard::updateScoreText(int num) // Actualiza el contador void Scoreboard::updateCounter() { - if (SDL_GetTicks() - ticks_ > SCOREBOARD_TICK_SPEED) + if (SDL_GetTicks() - ticks_ > SCOREBOARD_TICK_SPEED_) { ticks_ = SDL_GetTicks(); counter_++; diff --git a/source/scoreboard.h b/source/scoreboard.h index fd6560f..f1e152b 100644 --- a/source/scoreboard.h +++ b/source/scoreboard.h @@ -1,12 +1,12 @@ #pragma once -#include // for SDL_Point, SDL_Rect -#include // for SDL_Renderer, SDL_Texture -#include // for Uint32 -#include // for unique_ptr, shared_ptr -#include // for string -#include // for vector -#include "utils.h" // for Color +#include // for SDL_Point, SDL_Rect +#include // for SDL_Renderer, SDL_Texture +#include // for Uint32 +#include // for unique_ptr, shared_ptr +#include // for string +#include // for vector +#include "utils.h" // for Color class Sprite; class Text; class Texture; @@ -16,7 +16,6 @@ constexpr int SCOREBOARD_LEFT_PANEL = 0; constexpr int SCOREBOARD_CENTER_PANEL = 1; constexpr int SCOREBOARD_RIGHT_PANEL = 2; constexpr int SCOREBOARD_MAX_PANELS = 3; -constexpr int SCOREBOARD_TICK_SPEED = 100; // Enums enum class ScoreboardMode : int @@ -42,6 +41,9 @@ struct Panel class Scoreboard { private: + // Constantes + static constexpr int SCOREBOARD_TICK_SPEED_ = 100; + // [SINGLETON] Objeto scoreboard privado para Don Melitón static Scoreboard *scoreboard_; @@ -103,14 +105,14 @@ private: // [SINGLETON] Ahora el constructor y el destructor son privados // Constructor - explicit Scoreboard(SDL_Renderer *renderer); + Scoreboard(); // Destructor ~Scoreboard(); public: // [SINGLETON] Crearemos el objeto scoreboard con esta función estática - static void init(SDL_Renderer *renderer); + static void init(); // [SINGLETON] Destruiremos el objeto scoreboard con esta función estática static void destroy(); diff --git a/source/utils.h b/source/utils.h index f20b526..8f0fbd4 100644 --- a/source/utils.h +++ b/source/utils.h @@ -58,7 +58,6 @@ struct HiScoreEntry int score; // Puntuación }; -// Estructura para mapear el teclado usado en la demo struct DemoKeys { Uint8 left; @@ -67,6 +66,10 @@ struct DemoKeys Uint8 fire; Uint8 fire_left; Uint8 fire_right; + + // Constructor que inicializa todos los campos + DemoKeys(Uint8 l = 0, Uint8 r = 0, Uint8 ni = 0, Uint8 f = 0, Uint8 fl = 0, Uint8 fr = 0) + : left(l), right(r), no_input(ni), fire(f), fire_left(fl), fire_right(fr) {} }; // Estructura para las opciones de la ventana @@ -215,7 +218,6 @@ struct Param ParamNotification notification; // Opciones para las notificaciones }; - // Calcula el cuadrado de la distancia entre dos puntos double distanceSquared(int x1, int y1, int x2, int y2);