// continue_system.cpp - Implementación de la pantalla de continue #include "game/systems/continue_system.hpp" #include #include "core/audio/audio.hpp" #include "core/defaults.hpp" #include "core/input/input.hpp" #include "core/input/input_types.hpp" #include "game/scenes/game_scene.hpp" // GameOverState (definición completa) namespace Systems::ContinueScreen { namespace { // Si el countdown ha bajado de 0, transiciona a GAME_OVER con su timer. void checkAndApplyTimeout(Context& ctx) { if (ctx.counter < 0) { ctx.state = GameOverState::GAME_OVER; ctx.game_over_timer = Defaults::Game::GAME_OVER_DURATION; } } void revivePlayer(Context& ctx, uint8_t player_id) { ctx.score_per_player[player_id] = 0; ctx.lives_per_player[player_id] = Defaults::Game::STARTING_LIVES; ctx.hit_timer_per_player[player_id] = 0.0F; if (player_id == 0) { ctx.match_config.player1_active = true; } else { ctx.match_config.player2_active = true; } const Vec2 SPAWN = ctx.get_spawn_point(player_id); ctx.ships[player_id].init(&SPAWN, /*activar_invulnerabilitat=*/true); } } // namespace void update(Context& ctx, float delta_time) { ctx.tick_timer -= delta_time; if (ctx.tick_timer > 0.0F) { return; } ctx.counter--; ctx.tick_timer = Defaults::Game::CONTINUE_TICK_DURATION; checkAndApplyTimeout(ctx); // Solo pita el tick si seguimos en CONTINUE (no transitamos a GAME_OVER) if (ctx.state == GameOverState::CONTINUE) { Audio::get()->playSound(Defaults::Sound::CONTINUE, Audio::Group::GAME); } } void processInput(Context& ctx) { auto* input = Input::get(); const bool P1_START = input->checkActionPlayer1(InputAction::START, Input::DO_NOT_ALLOW_REPEAT); const bool P2_START = input->checkActionPlayer2(InputAction::START, Input::DO_NOT_ALLOW_REPEAT); if (P1_START || P2_START) { // ¿Quedan continues? if (!Defaults::Game::INFINITE_CONTINUES && ctx.continues_used >= Defaults::Game::MAX_CONTINUES) { ctx.state = GameOverState::GAME_OVER; ctx.game_over_timer = Defaults::Game::GAME_OVER_DURATION; return; } if (!Defaults::Game::INFINITE_CONTINUES) { ctx.continues_used++; } const uint8_t PRIMARY = P1_START ? 0 : 1; revivePlayer(ctx, PRIMARY); // Si ambos pulsan START, revivimos a los dos. if (P1_START && P2_START) { revivePlayer(ctx, 1); } // Reanudar partida. ctx.state = GameOverState::NONE; ctx.counter = 0; ctx.tick_timer = 0.0F; Audio::get()->playSound(Defaults::Sound::START, Audio::Group::GAME); return; } // THRUST/SHOOT acelera el countdown manualmente. const bool ACCEL = input->checkActionPlayer1(InputAction::THRUST, Input::DO_NOT_ALLOW_REPEAT) || input->checkActionPlayer2(InputAction::THRUST, Input::DO_NOT_ALLOW_REPEAT) || input->checkActionPlayer1(InputAction::SHOOT, Input::DO_NOT_ALLOW_REPEAT) || input->checkActionPlayer2(InputAction::SHOOT, Input::DO_NOT_ALLOW_REPEAT); if (ACCEL) { ctx.counter--; checkAndApplyTimeout(ctx); if (ctx.state == GameOverState::CONTINUE) { Audio::get()->playSound(Defaults::Sound::CONTINUE, Audio::Group::GAME); } ctx.tick_timer = Defaults::Game::CONTINUE_TICK_DURATION; } } } // namespace Systems::ContinueScreen