From c920f99c8243ed392f1827f5ac740a05b958cd37 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Tue, 19 May 2026 16:44:26 +0200 Subject: [PATCH] time-based: migrada escena Instructions + fix scroll diagonal del fons del Title (ancorat a posicio inicial) --- source/game/scenes/instructions.cpp | 26 ++++++++++++++++++++++++++ source/game/scenes/instructions.h | 23 +++++++++++++++-------- source/game/scenes/title.cpp | 15 +++++++++++---- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/source/game/scenes/instructions.cpp b/source/game/scenes/instructions.cpp index 1cb8a73..4f6fb79 100644 --- a/source/game/scenes/instructions.cpp +++ b/source/game/scenes/instructions.cpp @@ -97,6 +97,31 @@ void Instructions::update() { } } +// Time-based. counter_ es deriva de elapsed_s_*60 (cadència de referència 60Hz) +// per a no haver de refactoritzar render() — la geometria del scroll, la +// pulsació dels sprites i el blink de manual segueixen llegint counter_. +void Instructions::update(float dt_s) { + Audio::update(); + checkInput(); + + elapsed_s_ += dt_s; + constexpr float FRAMES_PER_S = 60.0F; + + if (mode_ == Mode::AUTO) { + counter_ = static_cast(elapsed_s_ * FRAMES_PER_S); + if (elapsed_s_ >= SCENE_DURATION_S) { + finished_ = true; + } + } else { + // counter_ acotat al rang original 0..59999 per no trencar les expressions + // de blink i sprite-cycling que en depenen. + counter_ = static_cast(static_cast(elapsed_s_ * FRAMES_PER_S) % 60000); + if (manual_quit_) { + finished_ = true; + } + } +} + // Pinta en pantalla void Instructions::render() { // Pinta en pantalla @@ -252,6 +277,7 @@ void Instructions::start(Mode mode) { manual_quit_ = false; counter_ = 0; ticks_ = 0; + elapsed_s_ = 0.0F; } // Indica si las instrucciones han terminado diff --git a/source/game/scenes/instructions.h b/source/game/scenes/instructions.h index 2471344..26a7049 100644 --- a/source/game/scenes/instructions.h +++ b/source/game/scenes/instructions.h @@ -23,11 +23,12 @@ class Instructions { Instructions(const Instructions &) = delete; auto operator=(const Instructions &) -> Instructions & = delete; - void run(Mode mode); // Bucle principal - void start(Mode mode); // Inicia las instrucciones (sin bucle) - void update(); // Actualiza las variables - void render(); // Pinta en pantalla - void checkEvents(); // Comprueba los eventos + void run(Mode mode); // Bucle principal + void start(Mode mode); // Inicia las instrucciones (sin bucle) + void update(); // Actualiza las variables (frame-based) + void update(float dt_s); // Actualiza las variables (time-based) + void render(); // Pinta en pantalla + void checkEvents(); // Comprueba los eventos [[nodiscard]] auto hasFinished() const -> bool; // Indica si las instrucciones han terminado [[nodiscard]] auto isQuitRequested() const -> bool; // Indica si se ha solicitado salir de la aplicación @@ -43,14 +44,20 @@ class Instructions { Section *section_; // Estado del bucle principal para saber si continua o se sale // Variables - Uint16 counter_; // Contador + Uint16 counter_; // Contador (derivat de elapsed_s_ * 60 en mode time-based) Uint16 counter_end_; // Valor final para el contador - Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa - Uint32 ticks_speed_; // Velocidad a la que se repiten los bucles del programa + Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa (frame-based) + Uint32 ticks_speed_; // Velocidad a la que se repiten los bucles del programa (frame-based) + float elapsed_s_{0.0F}; // Acumulador de temps (time-based) bool manual_quit_; // Indica si se quiere salir del modo manual Mode mode_{Instructions::Mode::AUTO}; // Modo en el que se van a ejecutar las instrucciones bool finished_; // Indica si las instrucciones han terminado bool quit_requested_; // Indica si se ha solicitado salir de la aplicación + // Time-based: durada total de la escena en mode AUTO (600 frames a 60Hz). + static constexpr float SCENE_DURATION_S = 10.0F; + // Time-based: temps mínim al mode MANUAL abans de poder sortir (30 frames a 60Hz). + static constexpr float MANUAL_QUIT_DELAY_S = 0.5F; + void checkInput(); // Comprueba las entradas }; diff --git a/source/game/scenes/title.cpp b/source/game/scenes/title.cpp index 2e8ee40..dd2f73a 100644 --- a/source/game/scenes/title.cpp +++ b/source/game/scenes/title.cpp @@ -638,13 +638,15 @@ void Title::checkInput() { void Title::updateBG(float dt_s) { if (background_mode_ == 0) { // Diagonal: 60 px/s a 60Hz ⇒ un cicle de 64 px cada 64/60 = 1.067 s. + // Ancorat a la posició inicial (128, 96): t=0 dona la mateixa vista que + // l'estàtic dels Title1/Title2, sense salt visual a l'entrada del Title3. constexpr float SCROLL_PERIOD_S = 64.0F / BG_SCROLL_SPEED_PX_PER_S; bg_scroll_x_s_ += dt_s; bg_scroll_y_s_ += dt_s; if (bg_scroll_x_s_ >= SCROLL_PERIOD_S) { bg_scroll_x_s_ -= SCROLL_PERIOD_S; } if (bg_scroll_y_s_ >= SCROLL_PERIOD_S) { bg_scroll_y_s_ -= SCROLL_PERIOD_S; } - background_window_.x = static_cast(bg_scroll_x_s_ * BG_SCROLL_SPEED_PX_PER_S); - background_window_.y = static_cast(bg_scroll_y_s_ * BG_SCROLL_SPEED_PX_PER_S); + background_window_.x = 128 + static_cast(bg_scroll_x_s_ * BG_SCROLL_SPEED_PX_PER_S); + background_window_.y = 96 + static_cast(bg_scroll_y_s_ * BG_SCROLL_SPEED_PX_PER_S); } else { // Cercle: 360 graus en BG_CIRCLE_PERIOD_S segons. bg_phase_s_ += dt_s; @@ -851,9 +853,11 @@ void Title::applyOptions() { // Ejecuta un frame void Title::iterate() { + const float DELTA_TIME_S = DeltaTime::tick(); + // Si las instrucciones están activas, delega el frame if (instructions_active_) { - instructions_->update(); + instructions_->update(DELTA_TIME_S); instructions_->render(); if (instructions_->hasFinished()) { @@ -872,6 +876,8 @@ void Title::iterate() { section_->name = SECTION_PROG_TITLE; section_->subsection = SUBSECTION_TITLE_3; } + // Reset del rellotge per evitar un dt enorme al tornar al Title. + DeltaTime::reset(); } return; } @@ -901,6 +907,8 @@ void Title::iterate() { section_->name = SECTION_PROG_TITLE; section_->subsection = SUBSECTION_TITLE_1; } + // Reset del rellotge per evitar un dt enorme al tornar al Title. + DeltaTime::reset(); } else { // Restaura section para que Director no transicione fuera de Title section_->name = SECTION_PROG_TITLE; @@ -909,7 +917,6 @@ void Title::iterate() { } // Ejecución normal del título - const float DELTA_TIME_S = DeltaTime::tick(); update(DELTA_TIME_S); render(); }