#pragma once #include // Para SDL_Keycode, SDL_Event, Uint64 #include // Para uint8_t #include // Para shared_ptr, unique_ptr #include // Para string_view #include // Para vector #include "color.hpp" // for Color #include "player.hpp" // for Player #include "section.hpp" // for Options, Name (ptr only) class Fade; class GameLogo; class Sprite; class Text; class TiledBG; namespace Options { struct Gamepad; } // namespace Options // --- Clase Title: pantalla de título y menú principal del juego --- // // Esta clase gestiona la pantalla de título del juego, incluyendo el menú principal // y la transición entre diferentes modos de juego. // // Funcionalidades principales: // • Logo animado: muestra y anima el logotipo principal del juego // • Selección de jugadores: permite iniciar partidas de 1 o 2 jugadores // • Modo attract: cicla automáticamente entre título y demo // • Efectos visuales: parpadeos, transiciones y efectos de fondo // • Gestión de controles: soporte para teclado y múltiples gamepads // • Timeouts automáticos: transición automática si no hay interacción // • Debug de colores: herramientas de depuración para ajustes visuales // // La clase utiliza un sistema de tiempo basado en segundos para garantizar // comportamiento consistente independientemente del framerate. class Title { public: // --- Constructor y destructor --- Title(); ~Title(); // --- Bucle principal --- void run(); private: // --- Constantes de tiempo (en segundos) --- static constexpr float START_PRESSED_DELAY_S = 1666.67F / 1000.0F; // Tiempo antes de fade tras pulsar start (100 frames a 60fps) static constexpr int MUSIC_FADE_OUT_LONG_MS = 1500; // Fade out largo de música static constexpr int MUSIC_FADE_OUT_SHORT_MS = 300; // Fade out corto de música // --- Constantes de parpadeo (en segundos) --- static constexpr float LOGO_BLINK_PERIOD_S = 833.0F / 1000.0F; // Período de parpadeo del logo (833ms) static constexpr float LOGO_BLINK_ON_TIME_S = 583.0F / 1000.0F; // Tiempo encendido del logo (583ms) static constexpr float START_BLINK_PERIOD_S = 167.0F / 1000.0F; // Período de parpadeo del start (167ms) static constexpr float START_BLINK_ON_TIME_S = 83.0F / 1000.0F; // Tiempo encendido del start (83ms) // --- Constantes de layout --- static constexpr int MINI_LOGO_Y_DIVISOR = 5; // Divisor para posición Y del mini logo static constexpr int MINI_LOGO_Y_FACTOR = 4; // Factor para posición Y del mini logo static constexpr int COPYRIGHT_TEXT_SPACING = 3; // Espaciado del texto de copyright // --- Constantes de texto y configuración --- static constexpr std::string_view TEXT_COPYRIGHT = "@2020,2025 JailDesigner"; // Texto de copyright static constexpr bool ALLOW_TITLE_ANIMATION_SKIP = false; // Permite saltar la animación del título // --- Enums --- enum class State { LOGO_ANIMATING, // El logo está animándose LOGO_FINISHED, // El logo ha terminado de animarse START_HAS_BEEN_PRESSED, // Se ha pulsado el botón de start }; // --- Estructuras privadas --- struct Anchor { int mini_logo; // Ancla del logo mini int copyright_text; // Ancla del texto de copyright }; // --- Objetos y punteros --- std::shared_ptr text_; // Objeto de texto para escribir en pantalla std::unique_ptr fade_; // Fundido en pantalla std::unique_ptr tiled_bg_; // Fondo animado de tiles std::unique_ptr game_logo_; // Logo del juego std::unique_ptr mini_logo_sprite_; // Logo JailGames mini std::vector> players_; // Vector de jugadores // --- Variables de estado --- Anchor anchor_; // Anclas para definir la posición de los elementos del título Section::Name next_section_; // Siguiente sección a cargar Section::Options selection_ = Section::Options::TITLE_TIME_OUT; // Opción elegida en el título State state_; // Estado actual de la sección Uint64 last_time_ = 0; // Último timestamp para calcular delta-time float counter_time_ = 0.0F; // Temporizador para la pantalla de título (en segundos) float blink_accumulator_ = 0.0F; // Acumulador para el parpadeo (en segundos) int num_controllers_; // Número de mandos conectados bool should_render_start_prompt_ = false; // Indica si se muestra el texto de PRESS START BUTTON TO PLAY bool player1_start_pressed_ = false; // Indica si se ha pulsado el botón de empezar para el jugador 1 bool player2_start_pressed_ = false; // Indica si se ha pulsado el botón de empezar para el jugador 2 #ifdef _DEBUG Color debug_color_; // Color para depuración en modo debug #endif // --- Ciclo de vida del título --- void update(float delta_time); // Actualiza las variables del objeto auto calculateDeltaTime() -> float; // Calcula el tiempo transcurrido desde el último frame void updateState(float delta_time); // Actualiza el estado actual del título void setState(State state); // Cambia el estado del título void resetCounter(); // Reinicia el contador interno // --- Entrada de usuario --- void checkEvents(); // Comprueba los eventos void checkInput(); // Comprueba las entradas void handleKeyDownEvent(const SDL_Event& event); // Maneja el evento de tecla presionada void processKeyboardStart(); // Procesa las entradas del teclado void processControllerInputs(); // Procesa las entradas de los mandos [[nodiscard]] static auto isStartButtonPressed(const Options::Gamepad* controller) -> bool; // Comprueba si se ha pulsado el botón Start void handleStartButtonPress(const Options::Gamepad* controller); // Maneja la pulsación del botón Start [[nodiscard]] auto canProcessStartButton() const -> bool; // Verifica si se puede procesar la pulsación del botón Start void processPlayer1Start(); // Procesa el inicio del jugador 1 void processPlayer2Start(); // Procesa el inicio del jugador 2 void activatePlayerAndSetState(Player::Id player_id); // Activa al jugador y cambia el estado del título // --- Gestión de jugadores --- void initPlayers(); // Inicializa los jugadores void updatePlayers(float delta_time); // Actualiza los jugadores void renderPlayers(); // Renderiza los jugadores auto getPlayer(Player::Id id) -> std::shared_ptr; // Obtiene un jugador a partir de su "id" // --- Visualización / Renderizado --- void render(); // Dibuja el objeto en pantalla void updateFade(); // Actualiza el efecto de fundido (fade in/out) void updateStartPrompt(float delta_time); // Actualiza el mensaje de "Pulsa Start" void renderStartPrompt(); // Dibuja el mensaje de "Pulsa Start" en pantalla void renderCopyright(); // Dibuja el aviso de copyright // --- Utilidades estáticas --- static void swapControllers(); // Intercambia la asignación de mandos a los jugadores static void swapKeyboard(); // Intercambia el teclado de jugador static void showControllers(); // Muestra información sobre los controles y los jugadores // --- Depuración (solo en modo DEBUG) --- #ifdef _DEBUG void handleDebugColorKeys(SDL_Keycode key); // Maneja las teclas de depuración para colores static void adjustColorComponent(SDL_Keycode key, Color& color); // Ajusta un componente del color según la tecla static void incrementColorComponent(uint8_t& component); // Incrementa un componente de color static void decrementColorComponent(uint8_t& component); // Decrementa un componente de color static void incrementAllComponents(Color& color); // Incrementa todos los componentes del color static void decrementAllComponents(Color& color); // Decrementa todos los componentes del color static void printColorValue(const Color& color); // Imprime el valor actual del color en consola #endif };