From 2caaa29124af18d1389d6ad1415c2f2fda83a3df Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Thu, 4 Dec 2025 08:24:08 +0100 Subject: [PATCH] afegit fade in al starfield de TITOL --- source/game/escenes/escena_titol.cpp | 73 +++++++++++++++++----------- source/game/escenes/escena_titol.hpp | 41 ++++++++-------- 2 files changed, 67 insertions(+), 47 deletions(-) diff --git a/source/game/escenes/escena_titol.cpp b/source/game/escenes/escena_titol.cpp index 23ab711..474104f 100644 --- a/source/game/escenes/escena_titol.cpp +++ b/source/game/escenes/escena_titol.cpp @@ -16,15 +16,10 @@ #include "core/system/global_events.hpp" #include "project.h" -namespace { -// Brightness del starfield (1.0 = default, >1.0 més brillant, <1.0 menys brillant) -constexpr float BRIGHTNESS_STARFIELD = 1.2f; -} // namespace - EscenaTitol::EscenaTitol(SDLManager& sdl) : sdl_(sdl), text_(sdl.obte_renderer()), - estat_actual_(EstatTitol::INIT), + estat_actual_(EstatTitol::STARFIELD_FADE_IN), temps_acumulat_(0.0f), temps_animacio_(0.0f), temps_estat_main_(0.0f), @@ -50,8 +45,8 @@ EscenaTitol::EscenaTitol(SDLManager& sdl) 150 // densitat: 150 estrelles (50 per capa) ); - // Configurar brightness del starfield - starfield_->set_brightness(BRIGHTNESS_STARFIELD); + // Iniciar amb brightness 0.0 per al fade-in + starfield_->set_brightness(0.0f); // Inicialitzar lletres del títol "ORNI ATTACK!" inicialitzar_titol(); @@ -286,13 +281,32 @@ void EscenaTitol::actualitzar(float delta_time) { } switch (estat_actual_) { - case EstatTitol::INIT: + case EstatTitol::STARFIELD_FADE_IN: { + temps_acumulat_ += delta_time; + + // Calcular progrés del fade (0.0 → 1.0) + float progress = std::min(1.0f, temps_acumulat_ / DURACIO_FADE_IN); + + // Lerp brightness de 0.0 a BRIGHTNESS_STARFIELD + float brightness_actual = progress * BRIGHTNESS_STARFIELD; + starfield_->set_brightness(brightness_actual); + + // Transició a STARFIELD quan el fade es completa + if (temps_acumulat_ >= DURACIO_FADE_IN) { + estat_actual_ = EstatTitol::STARFIELD; + temps_acumulat_ = 0.0f; // Reset timer per al següent estat + starfield_->set_brightness(BRIGHTNESS_STARFIELD); // Assegurar valor final + } + break; + } + + case EstatTitol::STARFIELD: temps_acumulat_ += delta_time; if (temps_acumulat_ >= DURACIO_INIT) { estat_actual_ = EstatTitol::MAIN; - temps_estat_main_ = 0.0f; // Reset timer al entrar a MAIN - animacio_activa_ = false; // Comença estàtic - factor_lerp_ = 0.0f; // Sense animació encara + temps_estat_main_ = 0.0f; // Reset timer al entrar a MAIN + animacio_activa_ = false; // Comença estàtic + factor_lerp_ = 0.0f; // Sense animació encara } break; @@ -345,7 +359,7 @@ void EscenaTitol::actualitzar(float delta_time) { break; } - case EstatTitol::TRANSITION: + case EstatTitol::TRANSITION_TO_GAME: temps_acumulat_ += delta_time; if (temps_acumulat_ >= DURACIO_TRANSITION) { // Transició a JOC (la música ja s'ha parat en el fade) @@ -361,13 +375,13 @@ void EscenaTitol::dibuixar() { starfield_->dibuixar(); } - // En l'estat INIT, només mostrar starfield (sense text) - if (estat_actual_ == EstatTitol::INIT) { + // En els estats STARFIELD_FADE_IN i STARFIELD, només mostrar starfield (sense text) + if (estat_actual_ == EstatTitol::STARFIELD_FADE_IN || estat_actual_ == EstatTitol::STARFIELD) { return; } // Estat MAIN i TRANSITION: Dibuixar títol i text (sobre el starfield) - if (estat_actual_ == EstatTitol::MAIN || estat_actual_ == EstatTitol::TRANSITION) { + if (estat_actual_ == EstatTitol::MAIN || estat_actual_ == EstatTitol::TRANSITION_TO_GAME) { // === Calcular i renderitzar ombra (només si animació activa) === if (animacio_activa_) { float temps_shadow = temps_animacio_ - SHADOW_DELAY; @@ -380,10 +394,8 @@ void EscenaTitol::dibuixar() { float frequency_y_shadow = ORBIT_FREQUENCY_Y; // Calcular offset de l'ombra - float shadow_offset_x = amplitude_x_shadow * std::sin(2.0f * Defaults::Math::PI * frequency_x_shadow * temps_shadow) - + SHADOW_OFFSET_X; - float shadow_offset_y = amplitude_y_shadow * std::sin(2.0f * Defaults::Math::PI * frequency_y_shadow * temps_shadow + ORBIT_PHASE_OFFSET) - + SHADOW_OFFSET_Y; + float shadow_offset_x = amplitude_x_shadow * std::sin(2.0f * Defaults::Math::PI * frequency_x_shadow * temps_shadow) + SHADOW_OFFSET_X; + float shadow_offset_y = amplitude_y_shadow * std::sin(2.0f * Defaults::Math::PI * frequency_y_shadow * temps_shadow + ORBIT_PHASE_OFFSET) + SHADOW_OFFSET_Y; // === RENDERITZAR OMBRA PRIMER (darrera del logo principal) === @@ -418,9 +430,8 @@ void EscenaTitol::dibuixar() { 0.0f, ESCALA_TITULO, true, - 1.0f, // progress = 1.0 (totalment visible) - SHADOW_BRIGHTNESS - ); + 1.0f, // progress = 1.0 (totalment visible) + SHADOW_BRIGHTNESS); } } @@ -459,7 +470,7 @@ void EscenaTitol::dibuixar() { const float spacing = 2.0f; // Espai entre caràcters (usat també per copyright) bool mostrar_text = true; - if (estat_actual_ == EstatTitol::TRANSITION) { + if (estat_actual_ == EstatTitol::TRANSITION_TO_GAME) { // Parpelleig: sin oscil·la entre -1 i 1, volem ON quan > 0 float fase = temps_acumulat_ * BLINK_FREQUENCY * 2.0f * 3.14159f; // 2π × freq × temps mostrar_text = (std::sin(fase) > 0.0f); @@ -503,19 +514,25 @@ void EscenaTitol::processar_events(const SDL_Event& event) { if (event.type == SDL_EVENT_KEY_DOWN || event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) { switch (estat_actual_) { - case EstatTitol::INIT: + case EstatTitol::STARFIELD_FADE_IN: + // Saltar directament a MAIN (ometre fade-in i starfield) + estat_actual_ = EstatTitol::MAIN; + starfield_->set_brightness(BRIGHTNESS_STARFIELD); // Assegurar brightness final + break; + + case EstatTitol::STARFIELD: // Saltar a MAIN estat_actual_ = EstatTitol::MAIN; break; case EstatTitol::MAIN: // Iniciar transició amb fade-out de música - estat_actual_ = EstatTitol::TRANSITION; - temps_acumulat_ = 0.0f; // Reset del comptador + estat_actual_ = EstatTitol::TRANSITION_TO_GAME; + temps_acumulat_ = 0.0f; // Reset del comptador Audio::get()->fadeOutMusic(MUSIC_FADE); // Fade de 300ms break; - case EstatTitol::TRANSITION: + case EstatTitol::TRANSITION_TO_GAME: // Ignorar inputs durant la transició break; } diff --git a/source/game/escenes/escena_titol.hpp b/source/game/escenes/escena_titol.hpp index c1cf089..0956d51 100644 --- a/source/game/escenes/escena_titol.hpp +++ b/source/game/escenes/escena_titol.hpp @@ -25,9 +25,10 @@ class EscenaTitol { private: // Màquina d'estats per la pantalla de títol enum class EstatTitol { - INIT, // Pantalla negra inicial (2 segons) - MAIN, // Pantalla de títol amb text - TRANSITION // Transició amb fade-out de música i text parpellejant + STARFIELD_FADE_IN, // Fade-in del starfield (1.5s) + STARFIELD, // Pantalla con el campo de estrellas + MAIN, // Pantalla de títol amb text + TRANSITION_TO_GAME // Transició amb fade-out de música i text parpellejant }; // Estructura per emmagatzemar informació de cada lletra del títol @@ -51,16 +52,18 @@ class EscenaTitol { float y_attack_dinamica_; // Posició Y calculada dinàmicament per "ATTACK!" // Estat d'animació del logo - float temps_animacio_; // Temps acumulat per animació orbital - std::vector posicions_originals_orni_; // Posicions originals de "ORNI" - std::vector posicions_originals_attack_; // Posicions originals de "ATTACK!" + float temps_animacio_; // Temps acumulat per animació orbital + std::vector posicions_originals_orni_; // Posicions originals de "ORNI" + std::vector posicions_originals_attack_; // Posicions originals de "ATTACK!" // Estat d'arrencada de l'animació - float temps_estat_main_; // Temps acumulat en estat MAIN - bool animacio_activa_; // Flag: true quan animació està activa - float factor_lerp_; // Factor de lerp actual (0.0 → 1.0) + float temps_estat_main_; // Temps acumulat en estat MAIN + bool animacio_activa_; // Flag: true quan animació està activa + float factor_lerp_; // Factor de lerp actual (0.0 → 1.0) // Constants + static constexpr float BRIGHTNESS_STARFIELD = 1.2f; // Brightness del starfield (>1.0 = més brillant) + static constexpr float DURACIO_FADE_IN = 3.0f; // Duració del fade-in del starfield (1.5 segons) static constexpr float DURACIO_INIT = 4.0f; // Duració de l'estat INIT (2 segons) static constexpr float DURACIO_TRANSITION = 1.5f; // Duració de la transició (1.5 segons) static constexpr float ESCALA_TITULO = 0.6f; // Escala per les lletres del títol (50%) @@ -71,21 +74,21 @@ class EscenaTitol { static constexpr int MUSIC_FADE = 1000; // Duracio del fade de la musica del titol al començar a jugar // Constants d'animació del logo - static constexpr float ORBIT_AMPLITUDE_X = 2.0f*2; // Amplitud oscil·lació horitzontal (píxels) - static constexpr float ORBIT_AMPLITUDE_Y = 1.5f*2; // Amplitud oscil·lació vertical (píxels) - static constexpr float ORBIT_FREQUENCY_X = 0.8f; // Velocitat oscil·lació horitzontal (Hz) - static constexpr float ORBIT_FREQUENCY_Y = 1.2f; // Velocitat oscil·lació vertical (Hz) - static constexpr float ORBIT_PHASE_OFFSET = 1.57f; // Desfasament entre X i Y (90° per circular) + static constexpr float ORBIT_AMPLITUDE_X = 2.0f * 2; // Amplitud oscil·lació horitzontal (píxels) + static constexpr float ORBIT_AMPLITUDE_Y = 1.5f * 2; // Amplitud oscil·lació vertical (píxels) + static constexpr float ORBIT_FREQUENCY_X = 0.8f; // Velocitat oscil·lació horitzontal (Hz) + static constexpr float ORBIT_FREQUENCY_Y = 1.2f; // Velocitat oscil·lació vertical (Hz) + static constexpr float ORBIT_PHASE_OFFSET = 1.57f; // Desfasament entre X i Y (90° per circular) // Constants d'ombra del logo - static constexpr float SHADOW_DELAY = 0.5f; // Retard temporal de l'ombra (segons) - static constexpr float SHADOW_BRIGHTNESS = 0.4f; // Multiplicador de brillantor de l'ombra (0.0-1.0) - static constexpr float SHADOW_OFFSET_X = 2.0f; // Offset espacial X fix (píxels) - static constexpr float SHADOW_OFFSET_Y = 2.0f; // Offset espacial Y fix (píxels) + static constexpr float SHADOW_DELAY = 0.5f; // Retard temporal de l'ombra (segons) + static constexpr float SHADOW_BRIGHTNESS = 0.4f; // Multiplicador de brillantor de l'ombra (0.0-1.0) + static constexpr float SHADOW_OFFSET_X = 2.0f; // Offset espacial X fix (píxels) + static constexpr float SHADOW_OFFSET_Y = 2.0f; // Offset espacial Y fix (píxels) // Temporització de l'arrencada de l'animació static constexpr float DELAY_INICI_ANIMACIO = 10.0f; // 10s estàtic abans d'animar - static constexpr float DURACIO_LERP = 2.0f; // 2s per arribar a amplitud completa + static constexpr float DURACIO_LERP = 2.0f; // 2s per arribar a amplitud completa // Mètodes privats void actualitzar(float delta_time);