// logo_scene.hpp - Pantalla de start del juego // Muestra logo JAILGAMES animat con zoom i salta al juego // © 2026 JailDesigner #pragma once #include #include #include #include #include #include "core/defaults.hpp" #include "core/graphics/shape.hpp" #include "core/rendering/sdl_manager.hpp" #include "core/system/scene.hpp" #include "core/system/scene_context.hpp" #include "core/types.hpp" #include "game/effects/debris_manager.hpp" class LogoScene final : public Scene { public: explicit LogoScene(SDLManager& sdl, SceneManager::SceneContext& context); ~LogoScene() override; // Destructor per aturar sons // Scene interface void handleEvent(const SDL_Event& event) override; void update(float delta_time) override; void draw() override; [[nodiscard]] auto isFinished() const -> bool override; private: // Màquina de estats per l'animación enum class AnimationState : std::uint8_t { PRE_ANIMATION, // Pantalla negra inicial ANIMATION, // Animación de zoom de lletres POST_ANIMATION, // Logo complet visible EXPLOSION, // Explosión seqüencial de lletres POST_EXPLOSION // Espera después de l'última explosión }; SDLManager& sdl_; SceneManager::SceneContext& context_; AnimationState current_state_{AnimationState::PRE_ANIMATION}; // Estat actual de la màquina float temps_current_state_{0.0F}; // Temps en l'state actual (reset en cada transición) // Gestor de fragments de explosions std::unique_ptr debris_manager_; // Seguiment de explosions seqüencials size_t letter_explosion_index_{0}; // Índex de la següent letter a explode float time_since_last_explosion_{0.0F}; // Temps desde l'última explosión std::vector explosion_order_; // Ordre aleatori de índexs de lletres // Estructura para cada letter del logo struct LogoLetter { std::shared_ptr shape; Vec2 position; // Posición final en pantalla float width; // Ancho del bounding box float center_offset; // Distancia de min_x a shape_centre.x }; std::vector letters_; // 9 lletres: J-A-I-L-G-A-M-E-S // Seguiment de sons de lletres (evitar reproduccions repetides) std::array sound_played_; // Track si cada letter ya ha reproduit el so // Cicle d'atracció: si en entrar al logo ja hi ha música sonant (venim de la // demo amb title.ogg en marxa), el logo no ha d'emetre sons ni reiniciar la // música — només repintar-se en silenci. bool attract_silent_{false}; // Constants de animación static constexpr float DURATION_PRE = 1.5F; // Duració PRE_ANIMATION (pantalla negra) static constexpr float DURATION_ZOOM = 4.0F; // Duració del zoom (segons) static constexpr float DURATION_POST_ANIMATION = 3.0F; // Duració POST_ANIMATION (logo complet) static constexpr float DURATION_POST_EXPLOSION = 3.0F; // Duració POST_EXPLOSION (espera final) static constexpr float DELAY_ENTRE_EXPLOSIONS = 0.1F; // Temps entre explosions de lletres static constexpr float SPEED_EXPLOSIO = 240.0F; // Velocidad base fragments (px/s) static constexpr float INITIAL_SCALE = 0.1F; // Escala inicial (10%) static constexpr float FINAL_SCALE = 0.8F; // Escala final (80%) static constexpr float LETTER_SPACING = 10.0F; // Espaiat entre lletres // Constants de animación seqüencial static constexpr float LETTER_THRESHOLD = 0.6F; // Umbral per activar següent letter (0.0-1.0) static constexpr float ZOOM_ORIGIN_X = Defaults::Game::WIDTH * 0.5F; // Vec2 inicial X del zoom static constexpr float ZOOM_ORIGIN_Y = Defaults::Game::HEIGHT * 0.4F; // Vec2 inicial Y del zoom // Métodos privats void initLetters(); void updateExplosions(float delta_time); // Estático: solo consulta Input (singleton), no estado de la escena. static auto checkSkipButtonPressed() -> bool; // Métodos de gestió de estats void changeState(AnimationState nou_estat); [[nodiscard]] auto allLettersComplete() const -> bool; };