diff --git a/source/core/input/input.cpp b/source/core/input/input.cpp index ec1927d..3685a8c 100644 --- a/source/core/input/input.cpp +++ b/source/core/input/input.cpp @@ -490,6 +490,7 @@ void Input::applyPlayer1BindingsFromOptions() { player1_keyboard_bindings_[Action::RIGHT].scancode = Options::player1.keyboard.key_right; player1_keyboard_bindings_[Action::THRUST].scancode = Options::player1.keyboard.key_thrust; player1_keyboard_bindings_[Action::SHOOT].scancode = Options::player1.keyboard.key_shoot; + player1_keyboard_bindings_[Action::START].scancode = Options::player1.keyboard.key_start; // 2. Encontrar gamepad por nombre (o usar primer gamepad como fallback) std::shared_ptr gamepad = nullptr; @@ -523,6 +524,7 @@ void Input::applyPlayer2BindingsFromOptions() { player2_keyboard_bindings_[Action::RIGHT].scancode = Options::player2.keyboard.key_right; player2_keyboard_bindings_[Action::THRUST].scancode = Options::player2.keyboard.key_thrust; player2_keyboard_bindings_[Action::SHOOT].scancode = Options::player2.keyboard.key_shoot; + player2_keyboard_bindings_[Action::START].scancode = Options::player2.keyboard.key_start; // 2. Encontrar gamepad por nombre (o usar segundo gamepad como fallback) std::shared_ptr gamepad = nullptr; diff --git a/source/core/input/input_types.hpp b/source/core/input/input_types.hpp index e23a8df..c07a7e4 100644 --- a/source/core/input/input_types.hpp +++ b/source/core/input/input_types.hpp @@ -12,6 +12,7 @@ enum class InputAction : int { // Acciones de entrada posibles en el juego RIGHT, // Rotar derecha THRUST, // Acelerar SHOOT, // Disparar + START, // Empezar partida // Inputs de sistema (globales) WINDOW_INC_ZOOM, // F2 diff --git a/source/game/escenes/escena_titol.cpp b/source/game/escenes/escena_titol.cpp index 84c7025..33908c2 100644 --- a/source/game/escenes/escena_titol.cpp +++ b/source/game/escenes/escena_titol.cpp @@ -371,23 +371,10 @@ void EscenaTitol::actualitzar(float delta_time) { // Continuar animació orbital durant la transició actualitzar_animacio_logo(delta_time); - // [NOU] Continuar comprovant si l'altre jugador vol unir-se durant la transició - auto* input = Input::get(); - for (auto action : SKIP_BUTTONS_TITOL) { - if (input->checkActionPlayer1(action, Input::DO_NOT_ALLOW_REPEAT)) { - if (!config_partida_.jugador1_actiu) { - config_partida_.jugador1_actiu = true; - context_.set_config_partida(config_partida_); - std::cout << "[EscenaTitol] P1 s'ha unit durant la transició!\n"; - } - } - if (input->checkActionPlayer2(action, Input::DO_NOT_ALLOW_REPEAT)) { - if (!config_partida_.jugador2_actiu) { - config_partida_.jugador2_actiu = true; - context_.set_config_partida(config_partida_); - std::cout << "[EscenaTitol] P2 s'ha unit durant la transició!\n"; - } - } + // [NOU] Continuar comprovant si l'altre jugador vol unir-se durant la transició ("late join") + if (checkStartGameButtonPressed()) { + // Updates config_partida_ if pressed, logs are in the method + context_.set_config_partida(config_partida_); } if (temps_acumulat_ >= DURACIO_TRANSITION) { @@ -397,42 +384,32 @@ void EscenaTitol::actualitzar(float delta_time) { break; } - // Verificar botones de skip (SHOOT P1/P2) - if (checkSkipButtonPressed()) { - switch (estat_actual_) { - case EstatTitol::STARFIELD_FADE_IN: - // Saltar fade-in, ir a MAIN - estat_actual_ = EstatTitol::MAIN; - starfield_->set_brightness(BRIGHTNESS_STARFIELD); - temps_estat_main_ = 0.0f; - break; + // Verificar botones de skip (FIRE/THRUST/START) para saltar escenas ANTES de MAIN + if (estat_actual_ == EstatTitol::STARFIELD_FADE_IN || estat_actual_ == EstatTitol::STARFIELD) { + if (checkSkipButtonPressed()) { + // Saltar a MAIN + estat_actual_ = EstatTitol::MAIN; + starfield_->set_brightness(BRIGHTNESS_STARFIELD); + temps_estat_main_ = 0.0f; + } + } - case EstatTitol::STARFIELD: - // Saltar starfield, ir a MAIN - estat_actual_ = EstatTitol::MAIN; - temps_estat_main_ = 0.0f; - break; + // Verificar boton START para iniciar partida desde MAIN + if (estat_actual_ == EstatTitol::MAIN) { + if (checkStartGameButtonPressed()) { + // Configurar partida abans de canviar d'escena + context_.set_config_partida(config_partida_); + std::cout << "[EscenaTitol] Configuració de partida - P1: " + << (config_partida_.jugador1_actiu ? "ACTIU" : "INACTIU") + << ", P2: " + << (config_partida_.jugador2_actiu ? "ACTIU" : "INACTIU") + << std::endl; - case EstatTitol::MAIN: - // Iniciar partida (transición a JOC) - // Configurar partida abans de canviar d'escena - context_.set_config_partida(config_partida_); - std::cout << "[EscenaTitol] Configuració de partida - P1: " - << (config_partida_.jugador1_actiu ? "ACTIU" : "INACTIU") - << ", P2: " - << (config_partida_.jugador2_actiu ? "ACTIU" : "INACTIU") - << std::endl; - - context_.canviar_escena(Escena::JOC); - estat_actual_ = EstatTitol::TRANSITION_TO_GAME; - temps_acumulat_ = 0.0f; - Audio::get()->fadeOutMusic(MUSIC_FADE); - Audio::get()->playSound(Defaults::Sound::LASER, Audio::Group::GAME); - break; - - case EstatTitol::TRANSITION_TO_GAME: - // Ignorar inputs durante transición - break; + context_.canviar_escena(Escena::JOC); + estat_actual_ = EstatTitol::TRANSITION_TO_GAME; + temps_acumulat_ = 0.0f; + Audio::get()->fadeOutMusic(MUSIC_FADE); + Audio::get()->playSound(Defaults::Sound::LASER, Audio::Group::GAME); } } } @@ -561,7 +538,7 @@ void EscenaTitol::dibuixar() { ); } - // === Text "PRESS BUTTON TO PLAY" === + // === Text "PRESS START TO PLAY" === // En estat MAIN: sempre visible // En estat TRANSITION: parpellejant (blink amb sinusoide) @@ -575,7 +552,7 @@ void EscenaTitol::dibuixar() { } if (mostrar_text) { - const std::string main_text = "PRESS BUTTON TO PLAY"; + const std::string main_text = "PRESS START TO PLAY"; const float escala_main = 1.0f; float text_width = text_.get_text_width(main_text, escala_main, spacing); @@ -609,21 +586,39 @@ void EscenaTitol::dibuixar() { auto EscenaTitol::checkSkipButtonPressed() -> bool { auto* input = Input::get(); - bool p1_pressed = false; - bool p2_pressed = false; for (auto action : SKIP_BUTTONS_TITOL) { - if (input->checkActionPlayer1(action, Input::DO_NOT_ALLOW_REPEAT)) { - p1_pressed = true; - config_partida_.jugador1_actiu = true; // Marcar P1 com a actiu - } - if (input->checkActionPlayer2(action, Input::DO_NOT_ALLOW_REPEAT)) { - p2_pressed = true; - config_partida_.jugador2_actiu = true; // Marcar P2 com a actiu + if (input->checkActionPlayer1(action, Input::DO_NOT_ALLOW_REPEAT) || + input->checkActionPlayer2(action, Input::DO_NOT_ALLOW_REPEAT)) { + return true; // Don't track players here, just skip } } - return p1_pressed || p2_pressed; + return false; +} + +auto EscenaTitol::checkStartGameButtonPressed() -> bool { + auto* input = Input::get(); + bool any_pressed = false; + + for (auto action : START_GAME_BUTTONS) { + if (input->checkActionPlayer1(action, Input::DO_NOT_ALLOW_REPEAT)) { + if (!config_partida_.jugador1_actiu) { + config_partida_.jugador1_actiu = true; + any_pressed = true; + std::cout << "[EscenaTitol] P1 pressed START\n"; + } + } + if (input->checkActionPlayer2(action, Input::DO_NOT_ALLOW_REPEAT)) { + if (!config_partida_.jugador2_actiu) { + config_partida_.jugador2_actiu = true; + any_pressed = true; + std::cout << "[EscenaTitol] P2 pressed START\n"; + } + } + } + + return any_pressed; } void EscenaTitol::processar_events(const SDL_Event& event) { diff --git a/source/game/escenes/escena_titol.hpp b/source/game/escenes/escena_titol.hpp index a2ec97d..ff53a3a 100644 --- a/source/game/escenes/escena_titol.hpp +++ b/source/game/escenes/escena_titol.hpp @@ -20,9 +20,16 @@ #include "core/system/game_config.hpp" #include "core/types.hpp" -// Botones que permiten saltar/avanzar la escena (extensible) -static constexpr std::array SKIP_BUTTONS_TITOL = { - InputAction::SHOOT +// Botones que permiten saltar/avanzar escenas ANTES de MAIN (extensible) +static constexpr std::array SKIP_BUTTONS_TITOL = { + InputAction::SHOOT, // FIRE + InputAction::THRUST, // THRUST + InputAction::START // START +}; + +// Botones para INICIAR PARTIDA desde MAIN (solo START) +static constexpr std::array START_GAME_BUTTONS = { + InputAction::START }; class EscenaTitol { @@ -107,5 +114,6 @@ class EscenaTitol { void dibuixar(); void processar_events(const SDL_Event& event); auto checkSkipButtonPressed() -> bool; + auto checkStartGameButtonPressed() -> bool; void inicialitzar_titol(); // Carrega i posiciona les lletres del títol }; diff --git a/source/game/options.hpp b/source/game/options.hpp index 0ed6c06..a21d2c1 100644 --- a/source/game/options.hpp +++ b/source/game/options.hpp @@ -57,6 +57,7 @@ struct KeyboardControls { SDL_Scancode key_right{SDL_SCANCODE_RIGHT}; SDL_Scancode key_thrust{SDL_SCANCODE_UP}; SDL_Scancode key_shoot{SDL_SCANCODE_SPACE}; + SDL_Scancode key_start{SDL_SCANCODE_1}; }; struct GamepadControls { @@ -88,7 +89,8 @@ inline PlayerControls player1{ {.key_left = SDL_SCANCODE_LEFT, .key_right = SDL_SCANCODE_RIGHT, .key_thrust = SDL_SCANCODE_UP, - .key_shoot = SDL_SCANCODE_SPACE}, + .key_shoot = SDL_SCANCODE_SPACE, + .key_start = SDL_SCANCODE_1}, .gamepad_name = "" // Primer gamepad disponible }; @@ -97,7 +99,8 @@ inline PlayerControls player2{ {.key_left = SDL_SCANCODE_A, .key_right = SDL_SCANCODE_D, .key_thrust = SDL_SCANCODE_W, - .key_shoot = SDL_SCANCODE_LSHIFT}, + .key_shoot = SDL_SCANCODE_LSHIFT, + .key_start = SDL_SCANCODE_2}, .gamepad_name = "" // Segon gamepad disponible };