diff --git a/source/game/game.cpp b/source/game/game.cpp index bce537e..4d1066a 100644 --- a/source/game/game.cpp +++ b/source/game/game.cpp @@ -2977,10 +2977,10 @@ void Game::iterate() { switch (section_->subsection) { case SUBSECTION_GAME_PAUSE: - iteratePaused(); + iteratePaused(DELTA_TIME_S); break; case SUBSECTION_GAME_GAMEOVER: - iterateGameOver(); + iterateGameOver(DELTA_TIME_S); break; case SUBSECTION_GAME_PLAY_1P: case SUBSECTION_GAME_PLAY_2P: @@ -2992,16 +2992,16 @@ void Game::iterate() { } // Rama de iterate(): pause -void Game::iteratePaused() { +void Game::iteratePaused(float dt_s) { if (!pause_initialized_) { enterPausedGame(); } - updatePausedGame(); + updatePausedGame(dt_s); renderPausedGame(); } // Rama de iterate(): game over -void Game::iterateGameOver() { +void Game::iterateGameOver(float dt_s) { if (!game_over_initialized_) { enterGameOverScreen(); } - updateGameOverScreen(); + updateGameOverScreen(dt_s); renderGameOverScreen(); } @@ -3074,6 +3074,17 @@ void Game::updatePausedGame() { } } +// Actualiza el menu de pausa (time-based) +void Game::updatePausedGame(float dt_s) { + GlobalInputs::handle(); + + if (leaving_pause_menu_) { + updateLeavingPauseMenu(dt_s); + } else { + updatePauseMenuUI(dt_s); + } +} + // Rama de updatePausedGame: cuenta atrás de salida y vuelta al juego void Game::updateLeavingPauseMenu() { if (pause_counter_ > 0) { // El contador está descendiendo @@ -3096,7 +3107,69 @@ void Game::updateLeavingPauseMenu() { } } -// Rama de updatePausedGame: lógica del menú de pausa +// Cuenta atrás de salida (time-based). Decrementa pause_counter_ a 60Hz exactes +// amb un acumulador de fase, per a mantenir els sons de rellotge als llindars +// originals (90, 60, 30 frames = 1.5s, 1.0s, 0.5s restants). +void Game::updateLeavingPauseMenu(float dt_s) { + if (pause_counter_ <= 0) { + section_->name = SECTION_PROG_GAME; + section_->subsection = num_players_ == 1 ? SUBSECTION_GAME_PLAY_1P : SUBSECTION_GAME_PLAY_2P; + if (Audio::getRealMusicState() == Audio::MusicState::PAUSED) { + Audio::get()->resumeMusic(); + } + return; + } + + constexpr float STEP_S = 1.0F / 60.0F; + pause_counter_phase_s_ += dt_s; + while (pause_counter_phase_s_ >= STEP_S && pause_counter_ > 0) { + pause_counter_phase_s_ -= STEP_S; + if (pause_counter_ == 90 || pause_counter_ == 60 || pause_counter_ == 30) { + Audio::get()->playSound(clock_sound_); + } + pause_counter_--; + } +} + +// Lógica del menú de pausa (time-based) +void Game::updatePauseMenuUI(float dt_s) { + pause_menu_->update(); + pause_menu_->checkInput(); + + if (Input::get()->checkInput(Input::Action::PAUSE, Input::Repeat::OFF)) { + leaving_pause_menu_ = true; + pause_counter_phase_s_ = 0.0F; + if (!Options::gameplay.pause_countdown) { + pause_counter_ = 0; + } + return; + } + + switch (pause_menu_->getItemSelected()) { + case 1: + leaving_pause_menu_ = true; + pause_counter_phase_s_ = 0.0F; + if (!Options::gameplay.pause_countdown) { + pause_counter_ = 0; + } + break; + case 2: + fade_->setFadeType(Fade::Type::CENTER); + fade_->activateFade(); + break; + default: + break; + } + + fade_->update(dt_s); + if (fade_->hasEnded()) { + section_->name = SECTION_PROG_TITLE; + section_->subsection = SUBSECTION_TITLE_1; + Audio::get()->stopMusic(); + } +} + +// Rama de updatePausedGame: lógica del menú de pausa (frame-based) void Game::updatePauseMenuUI() { pause_menu_->update(); pause_menu_->checkInput(); @@ -3254,6 +3327,47 @@ void Game::updateGameOverScreen() { } } +// Actualiza los elementos de la pantalla de game over (time-based) +void Game::updateGameOverScreen(float dt_s) { + GlobalInputs::handle(); + + game_over_menu_->update(); + fade_->update(dt_s); + + if (fade_->hasEnded()) { + switch (game_over_post_fade_) { + case 0: // YES + section_->name = SECTION_PROG_GAME; + deleteAllVectorObjects(); + init(); + section_->subsection = num_players_ == 1 ? SUBSECTION_GAME_PLAY_1P : SUBSECTION_GAME_PLAY_2P; + break; + case 1: // NO + section_->name = SECTION_PROG_TITLE; + section_->subsection = SUBSECTION_TITLE_1; + break; + default: + break; + } + } + + if (!game_completed_) { + game_over_menu_->checkInput(); + switch (game_over_menu_->getItemSelected()) { + case 0: // YES + game_over_post_fade_ = 0; + fade_->activateFade(); + break; + case 1: // NO + game_over_post_fade_ = 1; + fade_->activateFade(); + break; + default: + break; + } + } +} + // Dibuja los elementos de la pantalla de game over void Game::renderGameOverScreen() { // Prepara para empezar a dibujar en la textura de juego diff --git a/source/game/game.h b/source/game/game.h index 30e0fbb..4b3fc8e 100644 --- a/source/game/game.h +++ b/source/game/game.h @@ -39,8 +39,8 @@ class Game { private: // Branques de iterate() — separades per a reduir la complexitat cognitiva - void iteratePaused(); - void iterateGameOver(); + void iteratePaused(float dt_s); + void iterateGameOver(float dt_s); void iteratePlaying(float dt_s); // Cantidad de elementos a escribir en los ficheros de datos @@ -258,15 +258,19 @@ class Game { [[nodiscard]] auto isDeathShaking() const -> bool; // Indica si el efecto de agitación intensa está activo void updateDeathSequence(); // Actualiza la secuencia de muerte del jugador - void updatePausedGame(); // Actualiza las variables del menu de pausa del juego - void updateLeavingPauseMenu(); // Helper de updatePausedGame - void updatePauseMenuUI(); // Helper de updatePausedGame - void renderPausedGame(); // Dibuja el menu de pausa del juego - void enterPausedGame(); // Inicializa el estado de pausa del juego + void updatePausedGame(); // Actualiza el menu de pausa (frame-based) + void updatePausedGame(float dt_s); // Actualiza el menu de pausa (time-based) + void updateLeavingPauseMenu(); // Helper (frame-based) + void updateLeavingPauseMenu(float dt_s); // Helper (time-based) + void updatePauseMenuUI(); // Helper (frame-based) + void updatePauseMenuUI(float dt_s); // Helper (time-based) + void renderPausedGame(); // Dibuja el menu de pausa del juego + void enterPausedGame(); // Inicializa el estado de pausa del juego - void updateGameOverScreen(); // Actualiza los elementos de la pantalla de game over - void renderGameOverScreen(); // Dibuja los elementos de la pantalla de game over - void enterGameOverScreen(); // Inicializa el estado de game over + void updateGameOverScreen(); // Actualiza game over (frame-based) + void updateGameOverScreen(float dt_s); // Actualiza game over (time-based) + void renderGameOverScreen(); // Dibuja los elementos de la pantalla de game over + void enterGameOverScreen(); // Inicializa el estado de game over auto canPowerBallBeCreated() -> bool; // Indica si se puede crear una powerball auto calculateScreenPower() -> int; // Calcula el poder actual de los globos en pantalla @@ -407,7 +411,8 @@ class Game { 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 int clouds_speed_{0}; // Velocidad a la que se desplazan las nubes - int pause_counter_; // Contador para salir del menu de pausa y volver al juego + int pause_counter_; // Contador per a sortir del menu de pausa (frame-based, frames) + float pause_counter_phase_s_{0.0F}; // Acumulador de fase per decrementar pause_counter_ a 60Hz (time-based) bool leaving_pause_menu_; // Indica si esta saliendo del menu de pausa para volver al juego bool pause_initialized_; // Indica si la pausa ha sido inicializada bool game_over_initialized_; // Indica si el game over ha sido inicializado