#pragma once #include #include #include "core/rendering/effects/scan_reveal.hpp" #include "core/rendering/transitions/fade_to_black.hpp" #include "core/scene/scene.hpp" class Surface; // Escena del logotip de l'editora. Timeline lineal en 7 fases visibles // (durades configurables des de `logo.timeline.*` al YAML, excepte SCAN // que la marca `logo.scan.duration_ms` + `tail_glitch_ms` + `flash_ms`): // // `BLACK_INTRO` — negre pur abans d'arrencar res. // `SCAN` — revelat scanline CRT amb glitch tail. So // `logoGlitchSound` es dispara just al començar // aquesta fase (no al constructor). // `HOLD_SILENT` — logo estable, en silenci, marge entre el final // del glitch i l'arrencada de la música. // `HOLD_MUSIC` — logo estable amb la música del títol sonant. // `FADE_OUT` — fade lineal a negre. // `BLACK_OUTRO` — negre amb la música encara sonant. TitleScene // continuarà la pista de manera idempotent (Audio // detecta same-track + same-loop i no reinicia). // `DONE` — terminal; dispara la transició cap a TITLE. // // Skip: qualsevol tecla no reservada salta directament a la transició // (sense fade-out) — el TitleScene té el seu propi `intro.fade_in_ms`, // així que la transició queda visualment continua igualment. class LogoScene : public Scene { public: explicit LogoScene(std::shared_ptr logo); ~LogoScene() override; void update(int delta_ms) override; void render() override; private: enum class Phase : std::uint8_t { BLACK_INTRO, SCAN, HOLD_SILENT, HOLD_MUSIC, FADE_OUT, BLACK_OUTRO, DONE }; void enterScan(); void enterHoldSilent(); void enterHoldMusic(); void enterFadeOut(); void enterBlackOutro(); void enterDone(); [[nodiscard]] static auto wantsSkip() -> bool; std::shared_ptr logo_; Phase phase_{Phase::BLACK_INTRO}; int phase_elapsed_ms_{0}; Transitions::FadeToBlack fade_; Effects::ScanReveal scan_; };