diff --git a/source/moving_sprite.cpp b/source/moving_sprite.cpp index b605dea..901244a 100644 --- a/source/moving_sprite.cpp +++ b/source/moving_sprite.cpp @@ -93,7 +93,9 @@ void MovingSprite::update(float deltaTime) { } // Muestra el sprite por pantalla -void MovingSprite::render() { getTexture()->render(pos_.x, pos_.y, &sprite_clip_, horizontal_zoom_, vertical_zoom_, rotate_.angle, &rotate_.center, flip_); } +void MovingSprite::render() { + getTexture()->render(pos_.x, pos_.y, &sprite_clip_, horizontal_zoom_, vertical_zoom_, rotate_.angle, &rotate_.center, flip_); +} // Establece la rotacion (frame-based) void MovingSprite::rotate() { diff --git a/source/sections/game.cpp b/source/sections/game.cpp index d6a92b1..5af2486 100644 --- a/source/sections/game.cpp +++ b/source/sections/game.cpp @@ -210,7 +210,6 @@ void Game::updateHiScore() { } } - // Actualiza las variables del jugador void Game::updatePlayers(float deltaTime) { for (auto &player : players_) { @@ -223,7 +222,7 @@ void Game::updatePlayers(float deltaTime) { // Si hay colisión if (balloon) { // Si el globo está parado y el temporizador activo, lo explota - if (balloon->isStopped() && time_stopped_counter_ > 0) { + if (balloon->isStopped() && time_stopped_timer_ > 0) { balloon_manager_->popBalloon(balloon); } // En caso contrario, el jugador ha sido golpeado por un globo activo @@ -328,17 +327,13 @@ void Game::updateGameStateGameOver(float deltaTime) { checkBulletCollision(); cleanVectors(); - if (game_over_timer_ > 0) { - if (game_over_timer_ >= GAME_OVER_DURATION_MS) { - createMessage({paths_.at(2), paths_.at(3)}, Resource::get()->getTexture("game_text_game_over")); - Audio::get()->fadeOutMusic(1000); - balloon_manager_->setBouncingSounds(true); - } + if (game_over_timer_ < GAME_OVER_DURATION_MS) { + handleGameOverEvents(); // Maneja eventos al inicio - game_over_timer_ -= deltaTime; // Decremento time-based + game_over_timer_ += deltaTime; // Incremento time-based - constexpr float FADE_TRIGGER_MS = 150.0f * (1000.0f / 60.0f); // 150 frames = 2500ms - if (game_over_timer_ <= FADE_TRIGGER_MS && !fade_out_->isEnabled()) { + constexpr float FADE_TRIGGER_MS = GAME_OVER_DURATION_MS - (150.0f * (1000.0f / 60.0f)); // 2500ms antes del final + if (game_over_timer_ >= FADE_TRIGGER_MS && !fade_out_->isEnabled()) { fade_out_->activate(); } } @@ -351,7 +346,7 @@ void Game::updateGameStateGameOver(float deltaTime) { } if (fade_out_->hasEnded()) { - if (game_completed_counter_ > 0) { + if (game_completed_timer_ > 0) { Section::name = Section::Name::CREDITS; // Los jugadores han completado el juego } else { Section::name = Section::Name::HI_SCORE_TABLE; // La partida ha terminado con la derrota de los jugadores @@ -366,9 +361,6 @@ void Game::updateGameStateGameOver(float deltaTime) { // Gestiona eventos para el estado del final del juego void Game::updateGameStateCompleted(float deltaTime) { - constexpr int START_CELEBRATIONS = 400; - constexpr int END_CELEBRATIONS = START_CELEBRATIONS + 300; - updatePlayers(deltaTime); updateScoreboard(); updateBackground(); @@ -380,40 +372,16 @@ void Game::updateGameStateCompleted(float deltaTime) { updatePathSprites(); cleanVectors(); - // Comienza las celebraciones - // Muestra el mensaje de felicitación y da los puntos a los jugadores - if (game_completed_counter_ == START_CELEBRATIONS) { - createMessage({paths_.at(4), paths_.at(5)}, Resource::get()->getTexture("game_text_congratulations")); - createMessage({paths_.at(6), paths_.at(7)}, Resource::get()->getTexture("game_text_1000000_points")); - - for (auto &player : players_) { - if (player->isPlaying()) { - player->addScore(1000000, Options::settings.hi_score_table.back().score); - player->setPlayingState(Player::State::CELEBRATING); - } else { - player->setPlayingState(Player::State::GAME_OVER); - } - } - - updateHiScore(); - } - - // Termina las celebraciones - if (game_completed_counter_ == END_CELEBRATIONS) { - for (auto &player : players_) { - if (player->isCelebrating()) { - player->setPlayingState(player->qualifiesForHighScore() ? Player::State::ENTERING_NAME_GAME_COMPLETED : Player::State::LEAVING_SCREEN); - } - } - } + // Maneja eventos del juego completado + handleGameCompletedEvents(); // Si los jugadores ya no estan y no quedan mensajes en pantalla if (allPlayersAreGameOver() && path_sprites_.empty()) { setState(State::GAME_OVER); } - // Incrementa el contador al final - ++game_completed_counter_; + // Incrementa el acumulador al final + game_completed_timer_ += deltaTime; } // Comprueba el estado del juego @@ -891,15 +859,15 @@ void Game::handlePlayerCollision(std::shared_ptr &player, std::shared_pt // Actualiza el estado del tiempo detenido void Game::updateTimeStopped(float deltaTime) { - static constexpr float WARNING_THRESHOLD_MS = 2000.0f; // 120 frames a 60fps - static constexpr float CLOCK_SOUND_INTERVAL_MS = 500.0f; // 30 frames a 60fps - static constexpr float COLOR_FLASH_INTERVAL_MS = 250.0f; // 15 frames a 60fps + static constexpr float WARNING_THRESHOLD_MS = 2000.0f; // 120 frames a 60fps + static constexpr float CLOCK_SOUND_INTERVAL_MS = 500.0f; // 30 frames a 60fps + static constexpr float COLOR_FLASH_INTERVAL_MS = 250.0f; // 15 frames a 60fps - if (time_stopped_counter_ > 0) { - time_stopped_counter_ -= deltaTime; + if (time_stopped_timer_ > 0) { + time_stopped_timer_ -= deltaTime; // Fase de advertencia (últimos 2 segundos) - if (time_stopped_counter_ <= WARNING_THRESHOLD_MS) { + if (time_stopped_timer_ <= WARNING_THRESHOLD_MS) { static float last_sound_time = 0.0f; last_sound_time += deltaTime; @@ -925,7 +893,6 @@ void Game::updateTimeStopped(float deltaTime) { } } - // Actualiza toda la lógica del juego void Game::update(float deltaTime) { screen_->update(); @@ -1011,12 +978,12 @@ void Game::fillCanvas() { void Game::enableTimeStopItem() { balloon_manager_->stopAllBalloons(); balloon_manager_->reverseColorsToAllBalloons(); - time_stopped_counter_ = TIME_STOPPED_DURATION_MS; + time_stopped_timer_ = TIME_STOPPED_DURATION_MS; } // Deshabilita el efecto del item de detener el tiempo void Game::disableTimeStopItem() { - time_stopped_counter_ = 0; + time_stopped_timer_ = 0; balloon_manager_->startAllBalloons(); balloon_manager_->normalColorsToAllBalloons(); } @@ -1355,7 +1322,7 @@ void Game::handleFireInput(const std::shared_ptr &player, BulletType bul cant_fire_counter = NORMAL_COOLDOWN; } - player->startFiringSystem(cant_fire_counter); // Sistema de disparo de dos líneas + player->startFiringSystem(cant_fire_counter); // Sistema de disparo de dos líneas } } @@ -1926,6 +1893,55 @@ void Game::onPauseStateChanged(bool is_paused) { tabe_->pauseTimer(is_paused); } +// Maneja eventos del juego completado usando flags para triggers únicos +void Game::handleGameCompletedEvents() { + constexpr float START_CELEBRATIONS_MS = 6667.0f; // 400 frames a 60fps + constexpr float END_CELEBRATIONS_MS = 11667.0f; // 700 frames a 60fps + + // Inicio de celebraciones + static bool start_celebrations_triggered = false; + if (!start_celebrations_triggered && game_completed_timer_ >= START_CELEBRATIONS_MS) { + createMessage({paths_.at(4), paths_.at(5)}, Resource::get()->getTexture("game_text_congratulations")); + createMessage({paths_.at(6), paths_.at(7)}, Resource::get()->getTexture("game_text_1000000_points")); + + for (auto &player : players_) { + if (player->isPlaying()) { + player->addScore(1000000, Options::settings.hi_score_table.back().score); + player->setPlayingState(Player::State::CELEBRATING); + } else { + player->setPlayingState(Player::State::GAME_OVER); + } + } + + updateHiScore(); + start_celebrations_triggered = true; + } + + // Fin de celebraciones + static bool end_celebrations_triggered = false; + if (!end_celebrations_triggered && game_completed_timer_ >= END_CELEBRATIONS_MS) { + for (auto &player : players_) { + if (player->isCelebrating()) { + player->setPlayingState(player->qualifiesForHighScore() ? Player::State::ENTERING_NAME_GAME_COMPLETED : Player::State::LEAVING_SCREEN); + } + } + + fade_out_->activate(); + end_celebrations_triggered = true; + } +} + +// Maneja eventos de game over usando flag para trigger único +void Game::handleGameOverEvents() { + static bool game_over_triggered = false; + if (!game_over_triggered && game_over_timer_ == 0.0f) { + createMessage({paths_.at(2), paths_.at(3)}, Resource::get()->getTexture("game_text_game_over")); + Audio::get()->fadeOutMusic(1000); + balloon_manager_->setBouncingSounds(true); + game_over_triggered = true; + } +} + #ifdef _DEBUG // Comprueba los eventos en el modo DEBUG void Game::handleDebugEvents(const SDL_Event &event) { @@ -2002,53 +2018,4 @@ void Game::handleDebugEvents(const SDL_Event &event) { } } } - -// Maneja eventos del juego completado usando flags para triggers únicos -void Game::handleGameCompletedEvents() { - constexpr float START_CELEBRATIONS_MS = 6667.0f; // 400 frames a 60fps - constexpr float END_CELEBRATIONS_MS = 11667.0f; // 700 frames a 60fps - - // Inicio de celebraciones - static bool start_celebrations_triggered = false; - if (!start_celebrations_triggered && game_completed_counter_ >= START_CELEBRATIONS_MS) { - createMessage({paths_.at(4), paths_.at(5)}, Resource::get()->getTexture("game_text_congratulations")); - createMessage({paths_.at(6), paths_.at(7)}, Resource::get()->getTexture("game_text_1000000_points")); - - for (auto &player : players_) { - if (player->isPlaying()) { - player->addScore(1000000, Options::settings.hi_score_table.back().score); - player->setPlayingState(Player::State::CELEBRATING); - } else { - player->setPlayingState(Player::State::GAME_OVER); - } - } - - updateHiScore(); - start_celebrations_triggered = true; - } - - // Fin de celebraciones - static bool end_celebrations_triggered = false; - if (!end_celebrations_triggered && game_completed_counter_ >= END_CELEBRATIONS_MS) { - for (auto &player : players_) { - if (player->isCelebrating()) { - player->setPlayingState(player->qualifiesForHighScore() ? Player::State::ENTERING_NAME_GAME_COMPLETED : Player::State::LEAVING_SCREEN); - } - } - - fade_out_->activate(); - end_celebrations_triggered = true; - } -} - -// Maneja eventos de game over usando flag para trigger único -void Game::handleGameOverEvents() { - static bool game_over_triggered = false; - if (!game_over_triggered && game_over_timer_ >= GAME_OVER_DURATION_MS) { - createMessage({paths_.at(2), paths_.at(3)}, Resource::get()->getTexture("game_text_game_over")); - Audio::get()->fadeOutMusic(1000); - balloon_manager_->setBouncingSounds(true); - game_over_triggered = true; - } -} #endif \ No newline at end of file diff --git a/source/sections/game.h b/source/sections/game.h index 19393be..65420c3 100644 --- a/source/sections/game.h +++ b/source/sections/game.h @@ -75,11 +75,11 @@ class Game { // --- Constantes de tiempo (en milisegundos) --- static constexpr float HELP_COUNTER_MS = 16667.0f; // Contador de ayuda (1000 frames a 60fps) - static constexpr float GAME_COMPLETED_START_FADE_MS = 8333.0f; // Inicio del fade al completar (500 frames) - static constexpr float GAME_COMPLETED_END_MS = 11667.0f; // Fin del juego completado (700 frames) - static constexpr float GAME_OVER_DURATION_MS = 5833.0f; // Duración game over (350 frames) - static constexpr float TIME_STOPPED_DURATION_MS = 6000.0f; // Duración del tiempo detenido (360 frames) - static constexpr int DEMO_FADE_PRE_DURATION_MS = 500; // Pre-duración del fade en modo demo + static constexpr float GAME_COMPLETED_START_FADE_MS = 8333.0f; // Inicio del fade al completar (500 frames) + static constexpr float GAME_COMPLETED_END_MS = 11667.0f; // Fin del juego completado (700 frames) + static constexpr float GAME_OVER_DURATION_MS = 5833.0f; // Duración game over (350 frames) + static constexpr float TIME_STOPPED_DURATION_MS = 6000.0f; // Duración del tiempo detenido (360 frames) + static constexpr int DEMO_FADE_PRE_DURATION_MS = 500; // Pre-duración del fade en modo demo 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; @@ -153,11 +153,11 @@ class Game { Uint64 last_time_ = 0; // Último tiempo registrado para deltaTime bool coffee_machine_enabled_ = false; // Indica si hay una máquina de café en el terreno de juego bool hi_score_achieved_ = false; // Indica si se ha superado la puntuación máxima - float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad - float counter_ = 0; // Contador para el juego - float game_completed_counter_ = 0; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más globos - float game_over_timer_ = GAME_OVER_DURATION_MS; // Timer para el estado de fin de partida (milisegundos) - float time_stopped_counter_ = 0; // Temporizador para llevar la cuenta del tiempo detenido + float difficulty_score_multiplier_ = 1.0f; // Multiplicador de puntos en función de la dificultad + float counter_ = 0.0f; // Contador para el juego + float game_completed_timer_ = 0.0f; // Acumulador de tiempo para el tramo final (milisegundos) + float game_over_timer_ = 0.0f; // Timer para el estado de fin de partida (milisegundos) + float time_stopped_timer_ = 0.0f; // Temporizador para llevar la cuenta del tiempo detenido int menace_ = 0; // Nivel de amenaza actual int menace_threshold_ = 0; // 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 State state_ = State::FADE_IN; // Estado @@ -170,22 +170,22 @@ class Game { #endif // --- Ciclo principal del juego --- - void update(float deltaTime); // Actualiza la lógica principal del juego - auto calculateDeltaTime() -> float; // Calcula el deltatime - void render(); // Renderiza todos los elementos del juego - void handleEvents(); // Procesa los eventos del sistema en cola - void checkState(); // Verifica y actualiza el estado actual del juego - void setState(State state); // Cambia el estado del juego - void cleanVectors(); // Limpia vectores de elementos deshabilitados + void update(float deltaTime); // Actualiza la lógica principal del juego + auto calculateDeltaTime() -> float; // Calcula el deltatime + void render(); // Renderiza todos los elementos del juego + void handleEvents(); // Procesa los eventos del sistema en cola + void checkState(); // Verifica y actualiza el estado actual del juego + void setState(State state); // Cambia el estado del juego + void cleanVectors(); // Limpia vectores de elementos deshabilitados // --- Gestión de estados del juego --- - void updateGameStates(float deltaTime); // Actualiza todos los estados del juego - void updateGameStateFadeIn(); // Gestiona el estado de transición de entrada - void updateGameStateEnteringPlayer(float deltaTime); // Gestiona el estado de entrada de jugador - void updateGameStateShowingGetReadyMessage(float deltaTime); // Gestiona el estado de mensaje "preparado" - void updateGameStatePlaying(float deltaTime); // Gestiona el estado de juego activo - void updateGameStateCompleted(float deltaTime); // Gestiona el estado de juego completado - void updateGameStateGameOver(float deltaTime); // Gestiona el estado de fin de partida + void updateGameStates(float deltaTime); // Actualiza todos los estados del juego + void updateGameStateFadeIn(); // Gestiona el estado de transición de entrada + void updateGameStateEnteringPlayer(float deltaTime); // Gestiona el estado de entrada de jugador + void updateGameStateShowingGetReadyMessage(float deltaTime); // Gestiona el estado de mensaje "preparado" + void updateGameStatePlaying(float deltaTime); // Gestiona el estado de juego activo + void updateGameStateCompleted(float deltaTime); // Gestiona el estado de juego completado + void updateGameStateGameOver(float deltaTime); // Gestiona el estado de fin de partida // --- Gestión de jugadores --- void initPlayers(Player::Id player_id); // Inicializa los datos de los jugadores @@ -246,12 +246,12 @@ class Game { void destroyAllItems(); // Elimina todos los ítems activos de la pantalla // --- ítems especiales --- - void enableTimeStopItem(); // Activa el efecto de detener el tiempo - void disableTimeStopItem(); // Desactiva el efecto de detener el tiempo - void updateTimeStopped(float deltaTime); // Actualiza el estado del tiempo detenido - void handleGameCompletedEvents(); // Maneja eventos del juego completado - void handleGameOverEvents(); // Maneja eventos de game over - void throwCoffee(int x, int y); // Crea efecto de café arrojado al ser golpeado + void enableTimeStopItem(); // Activa el efecto de detener el tiempo + void disableTimeStopItem(); // Desactiva el efecto de detener el tiempo + void updateTimeStopped(float deltaTime); // Actualiza el estado del tiempo detenido + void handleGameCompletedEvents(); // Maneja eventos del juego completado + void handleGameOverEvents(); // Maneja eventos de game over + void throwCoffee(int x, int y); // Crea efecto de café arrojado al ser golpeado // --- Gestión de caída de ítems --- void handleItemDrop(const std::shared_ptr &balloon, const std::shared_ptr &player); // Gestiona caída de ítem desde globo