diff --git a/CMakeLists.txt b/CMakeLists.txt index 69ced58..ea98e8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,6 +86,7 @@ set(APP_SOURCES source/game/ui/notifier.cpp # Utils + source/utils/delta_timer.cpp source/utils/global_events.cpp source/utils/utils.cpp diff --git a/source/game/options.cpp b/source/game/options.cpp index 702f253..88a0da5 100644 --- a/source/game/options.cpp +++ b/source/game/options.cpp @@ -15,18 +15,7 @@ #include "utils/utils.hpp" // Para stringToBool, boolToString, safeStoi namespace Options { -// --- Variables globales --- -std::string version; // Versión del fichero de configuración. Sirve para saber si las opciones son compatibles -bool console; // Indica si ha de mostrar información por la consola de texto -Cheat cheats; // Contiene trucos y ventajas para el juego -Game game; // Opciones de juego -Video video; // Opciones de video -Stats stats; // Datos con las estadisticas de juego -Notification notifications; // Opciones relativas a las notificaciones; -Window window; // Opciones relativas a la ventana -Audio audio; // Opciones relativas al audio -ControlScheme keys; // Teclas usadas para jugar - +// Declaración de función interna bool setOptions(const std::string& var, const std::string& value); // Crea e inicializa las opciones del programa diff --git a/source/game/options.hpp b/source/game/options.hpp index 56d06c0..f6fccd4 100644 --- a/source/game/options.hpp +++ b/source/game/options.hpp @@ -312,17 +312,17 @@ struct Game { height(game_height) {} }; -// --- Variables --- -extern std::string version; // Versión del fichero de configuración. Sirve para saber si las opciones son compatibles -extern bool console; // Indica si ha de mostrar información por la consola de texto -extern Cheat cheats; // Contiene trucos y ventajas para el juego -extern Game game; // Opciones de juego -extern Video video; // Opciones de video -extern Stats stats; // Datos con las estadisticas de juego -extern Notification notifications; // Opciones relativas a las notificaciones; -extern Window window; // Opciones relativas a la ventana -extern Audio audio; // Opciones relativas al audio -extern ControlScheme keys; // Teclas usadas para jugar +// --- Variables globales (inline C++17+) --- +inline std::string version{}; // Versión del fichero de configuración. Sirve para saber si las opciones son compatibles +inline bool console{false}; // Indica si ha de mostrar información por la consola de texto +inline Cheat cheats{}; // Contiene trucos y ventajas para el juego +inline Game game{}; // Opciones de juego +inline Video video{}; // Opciones de video +inline Stats stats{}; // Datos con las estadisticas de juego +inline Notification notifications{}; // Opciones relativas a las notificaciones; +inline Window window{}; // Opciones relativas a la ventana +inline Audio audio{}; // Opciones relativas al audio +inline ControlScheme keys{GameDefaults::CONTROL_SCHEME}; // Teclas usadas para jugar // --- Funciones --- void init(); // Crea e inicializa las opciones del programa diff --git a/source/game/scenes/logo.cpp b/source/game/scenes/logo.cpp index 8c89d04..56e3fc5 100644 --- a/source/game/scenes/logo.cpp +++ b/source/game/scenes/logo.cpp @@ -1,6 +1,7 @@ #include "game/scenes/logo.hpp" #include +#include // Para std::clamp #include "core/input/global_inputs.hpp" // Para check #include "core/rendering/screen.hpp" // Para Screen @@ -9,7 +10,7 @@ #include "core/resources/resource.hpp" // Para Resource #include "game/options.hpp" // Para Options, SectionState, options, Section #include "game/scene_manager.hpp" // Para SceneManager -#include "utils/defines.hpp" // Para GAME_SPEED +#include "utils/delta_timer.hpp" // Para DeltaTimer #include "utils/global_events.hpp" // Para check #include "utils/utils.hpp" // Para PaletteColor @@ -17,7 +18,10 @@ Logo::Logo() : jailgames_surface_(Resource::get()->getSurface("jailgames.gif")), since_1998_surface_(Resource::get()->getSurface("since_1998.gif")), - since_1998_sprite_(std::make_shared(since_1998_surface_, (256 - since_1998_surface_->getWidth()) / 2, 83 + jailgames_surface_->getHeight() + 5, since_1998_surface_->getWidth(), since_1998_surface_->getHeight())) { + since_1998_sprite_(std::make_shared(since_1998_surface_, (256 - since_1998_surface_->getWidth()) / 2, 83 + jailgames_surface_->getHeight() + 5, since_1998_surface_->getWidth(), since_1998_surface_->getHeight())), + delta_timer_(std::make_unique()), + state_(LogoState::INITIAL), + state_time_(0.0f) { // Configura variables since_1998_sprite_->setClip(0, 0, since_1998_surface_->getWidth(), since_1998_surface_->getHeight()); since_1998_color_ = static_cast(PaletteColor::BLACK); @@ -26,15 +30,8 @@ Logo::Logo() // Inicializa variables SceneManager::current = SceneManager::Scene::LOGO; - // Crea los sprites de cada linea - for (int i = 0; i < jailgames_surface_->getHeight(); ++i) { - jailgames_sprite_.push_back(std::make_shared(jailgames_surface_, 0, i, jailgames_surface_->getWidth(), 1)); - jailgames_sprite_.back()->setClip(0, i, jailgames_surface_->getWidth(), 1); - jailgames_sprite_.at(i)->setX((i % 2 == 0) ? (256 + (i * 3)) : (-181 - (i * 3))); - jailgames_sprite_.at(i)->setY(83 + i); - } - - initColors(); // Inicializa el vector de colores + initSprites(); // Crea los sprites de cada linea + initColors(); // Inicializa el vector de colores // Cambia el color del borde Screen::get()->setBorderColor(static_cast(PaletteColor::BLACK)); @@ -53,119 +50,140 @@ void Logo::checkInput() { globalInputs::check(); } -// Gestiona el logo de JAILGAME -void Logo::updateJAILGAMES() { - if (counter_ > 30) { - for (int i = 1; i < (int)jailgames_sprite_.size(); ++i) { - constexpr int SPEED = 8; - constexpr int DEST = 37; - if (jailgames_sprite_.at(i)->getX() != 37) { - if (i % 2 == 0) { - jailgames_sprite_.at(i)->incX(-SPEED); - if (jailgames_sprite_.at(i)->getX() < DEST) { - jailgames_sprite_.at(i)->setX(DEST); - } - } else { - jailgames_sprite_.at(i)->incX(SPEED); - if (jailgames_sprite_.at(i)->getX() > DEST) { - jailgames_sprite_.at(i)->setX(DEST); - } - } +// Gestiona el logo de JAILGAME (time-based) +void Logo::updateJAILGAMES(float delta_time) { + // Solo actualizar durante el estado JAILGAMES_SLIDE_IN + if (state_ != LogoState::JAILGAMES_SLIDE_IN) { + return; + } + + // Calcular el desplazamiento basado en velocidad y delta time + const float displacement = JAILGAMES_SLIDE_SPEED * delta_time; + + // Actualizar cada línea del sprite JAILGAMES + for (size_t i = 1; i < jailgames_sprite_.size(); ++i) { + const int current_x = jailgames_sprite_[i]->getX(); + + // Las líneas pares se mueven desde la derecha, las impares desde la izquierda + if (i % 2 == 0) { + // Mover hacia la izquierda + if (current_x > JAILGAMES_DEST_X) { + const int new_x = static_cast(current_x - displacement); + jailgames_sprite_[i]->setX(new_x < JAILGAMES_DEST_X ? JAILGAMES_DEST_X : new_x); + } + } else { + // Mover hacia la derecha + if (current_x < JAILGAMES_DEST_X) { + const int new_x = static_cast(current_x + displacement); + jailgames_sprite_[i]->setX(new_x > JAILGAMES_DEST_X ? JAILGAMES_DEST_X : new_x); } } } } +// Calcula el índice de color según el progreso (0.0-1.0) +int Logo::getColorIndex(float progress) const { + // Asegurar que progress esté en el rango [0.0, 1.0] + progress = std::clamp(progress, 0.0f, 1.0f); + + // Mapear el progreso al índice de color (0-7) + const int max_index = static_cast(color_.size()) - 1; + const int index = static_cast(progress * max_index); + + return index; +} + // Gestiona el color de las texturas void Logo::updateTextureColors() { - constexpr int INI = 70; - constexpr int INC = 4; + switch (state_) { + case LogoState::SINCE_1998_FADE_IN: { + // Fade-in de "Since 1998" de negro a blanco + const float progress = state_time_ / SINCE_1998_FADE_DURATION; + since_1998_color_ = color_[getColorIndex(progress)]; + break; + } - if (counter_ == INI + INC * 0) { - since_1998_color_ = color_.at(0); + case LogoState::DISPLAY: { + // Asegurar que ambos logos estén en blanco durante el display + jailgames_color_ = color_.back(); // BRIGHT_WHITE + since_1998_color_ = color_.back(); // BRIGHT_WHITE + break; + } + + case LogoState::FADE_OUT: { + // Fade-out de ambos logos de blanco a negro + const float progress = 1.0f - (state_time_ / FADE_OUT_DURATION); + const int color_index = getColorIndex(progress); + jailgames_color_ = color_[color_index]; + since_1998_color_ = color_[color_index]; + break; + } + + default: + // En otros estados, mantener los colores actuales + break; } +} - else if (counter_ == INI + INC * 1) { - since_1998_color_ = color_.at(1); - } +// Transiciona a un nuevo estado +void Logo::transitionToState(LogoState new_state) { + state_ = new_state; + state_time_ = 0.0f; +} - else if (counter_ == INI + INC * 2) { - since_1998_color_ = color_.at(2); - } +// Actualiza el estado actual +void Logo::updateState(float delta_time) { + state_time_ += delta_time; - else if (counter_ == INI + INC * 3) { - since_1998_color_ = color_.at(3); - } + // Gestionar transiciones entre estados basándose en el tiempo + switch (state_) { + case LogoState::INITIAL: + if (state_time_ >= INITIAL_DELAY) { + transitionToState(LogoState::JAILGAMES_SLIDE_IN); + } + break; - else if (counter_ == INI + INC * 4) { - since_1998_color_ = color_.at(4); - } + case LogoState::JAILGAMES_SLIDE_IN: + if (state_time_ >= JAILGAMES_SLIDE_DURATION) { + transitionToState(LogoState::SINCE_1998_FADE_IN); + } + break; - else if (counter_ == INI + INC * 5) { - since_1998_color_ = color_.at(5); - } + case LogoState::SINCE_1998_FADE_IN: + if (state_time_ >= SINCE_1998_FADE_DURATION) { + transitionToState(LogoState::DISPLAY); + } + break; - else if (counter_ == INI + INC * 6) { - since_1998_color_ = color_.at(6); - } + case LogoState::DISPLAY: + if (state_time_ >= DISPLAY_DURATION) { + transitionToState(LogoState::FADE_OUT); + } + break; - else if (counter_ == INI + INC * 7) { - since_1998_color_ = color_.at(7); - } + case LogoState::FADE_OUT: + if (state_time_ >= FADE_OUT_DURATION) { + transitionToState(LogoState::END); + endSection(); + } + break; - else if (counter_ == INIT_FADE_ + INC * 0) { - jailgames_color_ = color_.at(6); - since_1998_color_ = color_.at(6); - } - - else if (counter_ == INIT_FADE_ + INC * 1) { - jailgames_color_ = color_.at(5); - since_1998_color_ = color_.at(5); - } - - else if (counter_ == INIT_FADE_ + INC * 2) { - jailgames_color_ = color_.at(4); - since_1998_color_ = color_.at(4); - } - - else if (counter_ == INIT_FADE_ + INC * 3) { - jailgames_color_ = color_.at(3); - since_1998_color_ = color_.at(3); - } - - else if (counter_ == INIT_FADE_ + INC * 4) { - jailgames_color_ = color_.at(2); - since_1998_color_ = color_.at(2); - } - - else if (counter_ == INIT_FADE_ + INC * 5) { - jailgames_color_ = color_.at(1); - since_1998_color_ = color_.at(1); - } - - else if (counter_ == INIT_FADE_ + INC * 6) { - jailgames_color_ = color_.at(0); - since_1998_color_ = color_.at(0); + case LogoState::END: + // Estado final, no hacer nada + break; } } // Actualiza las variables void Logo::update() { - // Comprueba que la diferencia de ticks sea mayor a la velocidad del juego - if (SDL_GetTicks() - ticks_ > GAME_SPEED) { - ticks_ = SDL_GetTicks(); // Actualiza el contador de ticks + // Obtener delta time desde el último frame + const float delta_time = delta_timer_->tick(); - checkInput(); // Comprueba las entradas - counter_++; // Incrementa el contador - updateJAILGAMES(); // Gestiona el logo de JAILGAME - updateTextureColors(); // Gestiona el color de las texturas - Screen::get()->update(); // Actualiza el objeto Screen - - // Comprueba si ha terminado el logo - if (counter_ == END_LOGO_ + POST_LOGO_) { - endSection(); - } - } + checkInput(); // Comprueba las entradas + updateState(delta_time); // Actualiza el estado y gestiona transiciones + updateJAILGAMES(delta_time); // Gestiona el logo de JAILGAME + updateTextureColors(); // Gestiona el color de las texturas + Screen::get()->update(); // Actualiza el objeto Screen } // Dibuja en pantalla @@ -175,8 +193,8 @@ void Logo::render() { Screen::get()->clearSurface(static_cast(PaletteColor::BLACK)); // Dibuja los objetos - for (const auto& s : jailgames_sprite_) { - s->render(1, jailgames_color_); + for (const auto& sprite : jailgames_sprite_) { + sprite->render(1, jailgames_color_); } since_1998_sprite_->render(1, since_1998_color_); @@ -225,4 +243,15 @@ void Logo::initColors() { for (const auto& color : COLORS) { color_.push_back(color); } +} + +// Crea los sprites de cada linea +void Logo::initSprites() { + const float WIDTH = jailgames_surface_->getWidth(); + for (int i = 0; i < jailgames_surface_->getHeight(); ++i) { + jailgames_sprite_.push_back(std::make_shared(jailgames_surface_, 0, i, jailgames_surface_->getWidth(), 1)); + jailgames_sprite_.back()->setClip(0, i, jailgames_surface_->getWidth(), 1); + jailgames_sprite_.at(i)->setX((i % 2 == 0) ? (256 + (i * 3)) : (-WIDTH - (i * 3))); + jailgames_sprite_.at(i)->setY(83 + i); + } } \ No newline at end of file diff --git a/source/game/scenes/logo.hpp b/source/game/scenes/logo.hpp index f8c64d5..b64564b 100644 --- a/source/game/scenes/logo.hpp +++ b/source/game/scenes/logo.hpp @@ -4,17 +4,39 @@ #include // Para shared_ptr #include // Para vector -class SurfaceSprite; // lines 7-7 -class Surface; // lines 8-8 +#include "utils/delta_timer.hpp" // Para DeltaTimer +class SurfaceSprite; // Forward declaration +class Surface; // Forward declaration + +// Estados de la secuencia del logo +enum class LogoState { + INITIAL, // Espera inicial + JAILGAMES_SLIDE_IN, // Las líneas de JAILGAMES se deslizan hacia el centro + SINCE_1998_FADE_IN, // Aparición gradual del texto "Since 1998" + DISPLAY, // Logo completo visible + FADE_OUT, // Desaparición gradual + END // Fin de la secuencia +}; class Logo { - private: - // Constantes - static constexpr int INIT_FADE_ = 300; // Tiempo del contador cuando inicia el fade a negro - static constexpr int END_LOGO_ = 400; // Tiempo del contador para terminar el logo - static constexpr int POST_LOGO_ = 20; // Tiempo que dura el logo con el fade al maximo + public: + Logo(); // Constructor + ~Logo() = default; // Destructor + void run(); // Bucle principal - // Objetos y punteros + private: + // --- Constantes de tiempo (en segundos) --- + static constexpr float INITIAL_DELAY = 0.5f; // Tiempo antes de que empiece la animación + static constexpr float JAILGAMES_SLIDE_DURATION = 1.2f; // Duración del slide-in de JAILGAMES + static constexpr float SINCE_1998_FADE_DURATION = 0.5f; // Duración del fade-in de "Since 1998" + static constexpr float DISPLAY_DURATION = 3.5f; // Tiempo que el logo permanece visible + static constexpr float FADE_OUT_DURATION = 0.5f; // Duración del fade-out final + + // --- Constantes de animación --- + static constexpr float JAILGAMES_SLIDE_SPEED = 800.0f; // Velocidad de slide-in (pixels/segundo) + static constexpr int JAILGAMES_DEST_X = 37; // Posición X de destino para JAILGAMES + + // --- Objetos y punteros --- std::shared_ptr jailgames_surface_; // Textura con los graficos "JAILGAMES" std::shared_ptr since_1998_surface_; // Textura con los graficos "Since 1998" std::vector> jailgames_sprite_; // Vector con los sprites de cada linea que forman el bitmap JAILGAMES @@ -22,42 +44,23 @@ class Logo { Uint8 jailgames_color_ = 0; // Color para el sprite de "JAILGAMES" Uint8 since_1998_color_ = 0; // Color para el sprite de "Since 1998" - // Variables - std::vector color_; // Vector con los colores para el fade - int counter_ = 0; // Contador - Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa + // --- Variables de estado --- + std::vector color_; // Vector con los colores para el fade + std::unique_ptr delta_timer_; // Timer para delta time + LogoState state_; // Estado actual de la secuencia + float state_time_; // Tiempo acumulado en el estado actual - // Actualiza las variables - void update(); - - // Dibuja en pantalla - void render(); - - // Comprueba el manejador de eventos - void checkEvents(); - - // Comprueba las entradas - void checkInput(); - - // Gestiona el logo de JAILGAME - void updateJAILGAMES(); - - // Gestiona el color de las texturas - void updateTextureColors(); - - // Termina la sección - void endSection(); - - // Inicializa el vector de colores - void initColors(); - - public: - // Constructor - Logo(); - - // Destructor - ~Logo() = default; - - // Bucle principal - void run(); + // --- Funciones --- + void update(); // Actualiza las variables + void render(); // Dibuja en pantalla + void checkEvents(); // Comprueba el manejador de eventos + void checkInput(); // Comprueba las entradas + void updateJAILGAMES(float delta_time); // Gestiona el logo de JAILGAME (time-based) + void updateTextureColors(); // Gestiona el color de las texturas + void updateState(float delta_time); // Actualiza el estado actual + void transitionToState(LogoState new_state); // Transiciona a un nuevo estado + int getColorIndex(float progress) const; // Calcula el índice de color según el progreso (0.0-1.0) + void endSection(); // Termina la sección + void initColors(); // Inicializa el vector de colores + void initSprites(); // Crea los sprites de cada linea }; \ No newline at end of file diff --git a/source/utils/delta_timer.cpp b/source/utils/delta_timer.cpp new file mode 100644 index 0000000..efc89a0 --- /dev/null +++ b/source/utils/delta_timer.cpp @@ -0,0 +1,39 @@ +#include "utils/delta_timer.hpp" + +DeltaTimer::DeltaTimer() noexcept + : last_counter_(SDL_GetPerformanceCounter()), + perf_freq_(static_cast(SDL_GetPerformanceFrequency())), + time_scale_(1.0f) { +} + +float DeltaTimer::tick() noexcept { + const Uint64 now = SDL_GetPerformanceCounter(); + const Uint64 diff = (now > last_counter_) ? (now - last_counter_) : 0; + last_counter_ = now; + const double seconds = static_cast(diff) / perf_freq_; + return static_cast(seconds * static_cast(time_scale_)); +} + +float DeltaTimer::peek() const noexcept { + const Uint64 now = SDL_GetPerformanceCounter(); + const Uint64 diff = (now > last_counter_) ? (now - last_counter_) : 0; + const double seconds = static_cast(diff) / perf_freq_; + return static_cast(seconds * static_cast(time_scale_)); +} + +void DeltaTimer::reset(Uint64 counter) noexcept { + if (counter == 0) { + last_counter_ = SDL_GetPerformanceCounter(); + } else { + last_counter_ = counter; + } +} + +void DeltaTimer::setTimeScale(float scale) noexcept { + time_scale_ = std::max(scale, 0.0f); +} + +float DeltaTimer::getTimeScale() const noexcept { + return time_scale_; +} + diff --git a/source/utils/delta_timer.hpp b/source/utils/delta_timer.hpp new file mode 100644 index 0000000..0896d8a --- /dev/null +++ b/source/utils/delta_timer.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +class DeltaTimer { +public: + DeltaTimer() noexcept; + + // Calcula delta en segundos y actualiza el contador interno + float tick() noexcept; + + // Devuelve el delta estimado desde el último tick sin actualizar el contador + float peek() const noexcept; + + // Reinicia el contador al valor actual o al valor pasado (en performance counter ticks) + void reset(Uint64 counter = 0) noexcept; + + // Escala el tiempo retornado por tick/peek, por defecto 1.0f + void setTimeScale(float scale) noexcept; + float getTimeScale() const noexcept; + +private: + Uint64 last_counter_; + double perf_freq_; + float time_scale_; +};