diff --git a/source/game/scene_manager.hpp b/source/game/scene_manager.hpp index d59618d..0dc91dc 100644 --- a/source/game/scene_manager.hpp +++ b/source/game/scene_manager.hpp @@ -34,7 +34,7 @@ enum class Options { // --- Variables de estado globales --- #ifdef _DEBUG -inline Scene current = Scene::ENDING; // Escena actual +inline Scene current = Scene::ENDING2; // Escena actual inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual #else inline Scene current = Scene::LOGO; // Escena actual diff --git a/source/game/scenes/ending2.cpp b/source/game/scenes/ending2.cpp index 9e997c0..e157859 100644 --- a/source/game/scenes/ending2.cpp +++ b/source/game/scenes/ending2.cpp @@ -4,6 +4,7 @@ #include // Para max, replace +#include "core/audio/audio.hpp" // Para Audio #include "core/input/global_inputs.hpp" // Para check #include "core/rendering/screen.hpp" // Para Screen #include "core/rendering/surface.hpp" // Para Surface @@ -11,16 +12,17 @@ #include "core/rendering/surface_moving_sprite.hpp" // Para SMovingSprite #include "core/rendering/text.hpp" // Para Text #include "core/resources/resource.hpp" // Para Resource -#include "external/jail_audio.h" // Para JA_SetVolume, JA_PlayMusic, JA_StopMusic +#include "core/system/global_events.hpp" // Para check #include "game/options.hpp" // Para Options, options, OptionsGame, Sectio... #include "game/scene_manager.hpp" // Para SceneManager #include "utils/defines.hpp" // Para GAMECANVAS_CENTER_X, GAMECANVAS_CENTER_Y -#include "core/system/global_events.hpp" // Para check +#include "utils/delta_timer.hpp" // Para DeltaTimer #include "utils/utils.hpp" // Para PaletteColor, stringToColor // Constructor Ending2::Ending2() - : state_(EndingState::PRE_CREDITS, SDL_GetTicks(), STATE_PRE_CREDITS_DURATION) { + : delta_timer_(std::make_unique()), + state_(EndingState::PRE_CREDITS, STATE_PRE_CREDITS_DURATION) { SceneManager::current = SceneManager::Scene::ENDING2; SceneManager::options = SceneManager::Options::NONE; @@ -51,41 +53,35 @@ Ending2::Ending2() // Actualiza el objeto void Ending2::update() { - // Comprueba que la diferencia de ticks sea mayor a la velocidad del juego - if (SDL_GetTicks() - ticks_ > GAME_SPEED) { - // Actualiza el contador de ticks - ticks_ = SDL_GetTicks(); + // Obtiene el delta time + current_delta_ = delta_timer_->tick(); - // Comprueba las entradas - checkInput(); + // Comprueba las entradas + checkInput(); - // Actualiza el estado - updateState(); + // Actualiza el estado + updateState(current_delta_); - switch (state_.state) { - case EndingState::CREDITS: - // Actualiza los sprites, los textos y los textos del final - for (int i = 0; i < 25; ++i) { - updateSprites(); - updateTextSprites(); - updateTexts(); - } - break; + switch (state_.state) { + case EndingState::CREDITS: + // Actualiza los sprites, los textos y los textos del final + updateSprites(current_delta_); + updateTextSprites(current_delta_); + updateTexts(current_delta_); + break; - case EndingState::FADING: - // Actualiza el fade final y el volumen de la música - updateFinalFade(); - updateMusicVolume(); - break; + case EndingState::FADING: + // Actualiza el fade final + updateFinalFade(); + break; - default: - // No hacer nada si el estado no corresponde a un caso manejado - break; - } - - // Actualiza el objeto - Screen::get()->update(); + default: + // No hacer nada si el estado no corresponde a un caso manejado + break; } + + // Actualiza el objeto + Screen::get()->update(current_delta_); } // Dibuja el final en pantalla @@ -145,7 +141,7 @@ void Ending2::checkInput() { // Bucle principal void Ending2::run() { - JA_PlayMusic(Resource::get()->getMusic("ending2.ogg")); + Audio::get()->playMusic("ending2.ogg"); while (SceneManager::current == SceneManager::Scene::ENDING2) { update(); @@ -153,33 +149,34 @@ void Ending2::run() { render(); } - JA_StopMusic(); - JA_SetVolume(128); + Audio::get()->stopMusic(); } // Actualiza el estado -void Ending2::updateState() { +void Ending2::updateState(float delta_time) { + state_time_ += delta_time; + switch (state_.state) { case EndingState::PRE_CREDITS: - if (state_.hasEnded(EndingState::PRE_CREDITS)) { - state_.set(EndingState::CREDITS, 0); + if (state_time_ >= STATE_PRE_CREDITS_DURATION) { + transitionToState(EndingState::CREDITS); } break; case EndingState::CREDITS: if (texts_.back()->getPosY() <= GAMECANVAS_CENTER_Y) { - state_.set(EndingState::POST_CREDITS, STATE_POST_CREDITS_DURATION); + transitionToState(EndingState::POST_CREDITS); } break; case EndingState::POST_CREDITS: - if (state_.hasEnded(EndingState::POST_CREDITS)) { - state_.set(EndingState::FADING, STATE_FADE_DURATION); + if (state_time_ >= STATE_POST_CREDITS_DURATION) { + transitionToState(EndingState::FADING); } break; case EndingState::FADING: - if (state_.hasEnded(EndingState::FADING)) { + if (state_time_ >= STATE_FADE_DURATION) { SceneManager::current = SceneManager::Scene::LOGO; SceneManager::options = SceneManager::Options::LOGO_TO_LOADING_SCREEN; } @@ -190,6 +187,32 @@ void Ending2::updateState() { } } +// Transición entre estados +void Ending2::transitionToState(EndingState new_state) { + state_.state = new_state; + state_time_ = 0.0F; + + // Actualizar duración según el nuevo estado + switch (new_state) { + case EndingState::PRE_CREDITS: + state_.duration = STATE_PRE_CREDITS_DURATION; + break; + case EndingState::POST_CREDITS: + state_.duration = STATE_POST_CREDITS_DURATION; + break; + case EndingState::FADING: + state_.duration = STATE_FADE_DURATION; + // Al entrar en FADING, iniciar fade de audio + Audio::get()->fadeOutMusic(MUSIC_FADE_DURATION); + break; + case EndingState::CREDITS: + state_.duration = 0.0F; // CREDITS no tiene duración fija, termina cuando el último texto llega al centro + break; + default: + break; + } +} + // Inicializa la lista de sprites void Ending2::iniSpriteList() { // Reinicia el vector @@ -282,23 +305,23 @@ void Ending2::loadSprites() { } // Actualiza los sprites -void Ending2::updateSprites() { +void Ending2::updateSprites(float delta) { for (const auto& sprite : sprites_) { - sprite->update(); + sprite->update(delta); } } // Actualiza los sprites de texto -void Ending2::updateTextSprites() { +void Ending2::updateTextSprites(float delta) { for (const auto& sprite : sprite_texts_) { - sprite->update(); + sprite->update(delta); } } // Actualiza los sprites de texto del final -void Ending2::updateTexts() { +void Ending2::updateTexts(float delta) { for (const auto& sprite : texts_) { - sprite->update(); + sprite->update(delta); } } @@ -345,7 +368,7 @@ void Ending2::renderTexts() { void Ending2::placeSprites() { for (int i = 0; i < static_cast(sprites_.size()); ++i) { const float X = i % 2 == 0 ? FIRST_COL : SECOND_COL; - const float Y = ((i / 1) * (sprite_max_height_ + DIST_SPRITE_TEXT + Resource::get()->getText("smb2")->getCharacterSize() + DIST_SPRITE_SPRITE)) + Options::game.height + 40; + const float Y = ((i / 1) * (sprite_max_height_ + DIST_SPRITE_TEXT + Resource::get()->getText("smb2")->getCharacterSize() + DIST_SPRITE_SPRITE)) + Options::game.height + INITIAL_Y_OFFSET; const float W = sprites_.at(i)->getWidth(); const float H = sprites_.at(i)->getHeight(); const float DX = -(W / 2); @@ -416,7 +439,7 @@ void Ending2::createTexts() { const float H = text->getCharacterSize(); const float X = GAMECANVAS_CENTER_X; const float DX = -(W / 2); - const float Y = Options::game.height + (text->getCharacterSize() * (i * 2)); + const float Y = Options::game.height + (text->getCharacterSize() * (i * TEXT_SPACING_MULTIPLIER)); // Crea la surface auto surface = std::make_shared(W, H); @@ -445,7 +468,7 @@ void Ending2::createTexts() { const float H = text->getCharacterSize(); const float X = GAMECANVAS_CENTER_X; const float DX = -(W / 2); - const float Y = START + (text->getCharacterSize() * (i * 2)); + const float Y = START + (text->getCharacterSize() * (i * TEXT_SPACING_MULTIPLIER)); // Crea la surface auto surface = std::make_shared(W, H); @@ -467,27 +490,3 @@ void Ending2::updateFinalFade() { sprite->getSurface()->fadeSubPalette(0); } } - -// Actualiza el volumen de la musica -void Ending2::updateMusicVolume() const { - // Constante para la duración en milisegundos - constexpr Uint32 VOLUME_FADE_DURATION = 3000; - - // Tiempo actual - const Uint32 CURRENT_TICKS = SDL_GetTicks(); - - // Calcular el tiempo transcurrido desde init_ticks - Uint32 elapsed_ticks = CURRENT_TICKS - state_.init_ticks; - - // Limitar el tiempo máximo a la duración definida - elapsed_ticks = std::min(elapsed_ticks, VOLUME_FADE_DURATION); - - // Calcular el step basado en la duración - const float STEP = (static_cast(VOLUME_FADE_DURATION) - elapsed_ticks) / VOLUME_FADE_DURATION; - - // Calcular el volumen en función del step - const int VOLUME = static_cast(128 * STEP); - - // Actualizar el volumen - JA_SetVolume(VOLUME); -} diff --git a/source/game/scenes/ending2.hpp b/source/game/scenes/ending2.hpp index 2e5d64d..c196032 100644 --- a/source/game/scenes/ending2.hpp +++ b/source/game/scenes/ending2.hpp @@ -9,6 +9,7 @@ #include "utils/defines.hpp" // Para GAMECANVAS_WIDTH, GAMECANVAS_FIRST_QUAR... class SurfaceAnimatedSprite; // lines 9-9 class SurfaceMovingSprite; // lines 10-10 +class DeltaTimer; class Ending2 { public: @@ -31,32 +32,12 @@ class Ending2 { // --- Estructura para controlar los estados y su duración --- struct State { EndingState state; // Estado actual - Uint32 init_ticks; // Ticks en los que se inicializó el estado - Uint32 duration; // Duración en milisegundos para el estado actual + float duration; // Duración en segundos para el estado actual // Constructor parametrizado para inicializar la estructura - State(EndingState initial_state, Uint32 initial_ticks, Uint32 state_duration) + State(EndingState initial_state, float state_duration) : state(initial_state), - init_ticks(initial_ticks), duration(state_duration) {} - - // Método para comprobar si el estado ha terminado y verifica el nombre del estado - [[nodiscard]] auto hasEnded(EndingState expected_state) const -> bool { - // Comprobar si el estado actual coincide con el estado esperado - if (state != expected_state) { - return false; // Si no coincide, considerar que no ha terminado - } - - // Comprobar si el tiempo transcurrido excede la duración - return (SDL_GetTicks() - init_ticks) >= duration; - } - - // Método para establecer un nuevo estado - void set(EndingState new_state, Uint32 new_duration) { - state = new_state; // Actualizar el estado - init_ticks = SDL_GetTicks(); // Reiniciar el tiempo de inicio - duration = new_duration; // Actualizar la duración - } }; // --- Constantes --- @@ -64,41 +45,49 @@ class Ending2 { static constexpr int SECOND_COL = GAMECANVAS_THIRD_QUARTER_X - (GAMECANVAS_WIDTH / 16); // Segunda columna por donde desfilan los sprites static constexpr int DIST_SPRITE_TEXT = 8; // Distancia entre el sprite y el texto que lo acompaña static constexpr int DIST_SPRITE_SPRITE = 0; // Distancia entre dos sprites de la misma columna - static constexpr float SPRITE_DESP_SPEED = -0.2F; // Velocidad de desplazamiento de los sprites - static constexpr int STATE_PRE_CREDITS_DURATION = 3000; - static constexpr int STATE_POST_CREDITS_DURATION = 5000; - static constexpr int STATE_FADE_DURATION = 5000; + static constexpr int INITIAL_Y_OFFSET = 40; // Offset inicial en Y para posicionar sprites + static constexpr int SCREEN_MESH_HEIGHT = 8; // Altura de la malla superior/inferior de la pantalla + static constexpr int TEXT_SPACING_MULTIPLIER = 2; // Multiplicador para espaciado entre líneas de texto + + // Constantes de tiempo (basadas en tiempo real, no en frames) + static constexpr float SPRITE_DESP_SPEED = -12.0F; // Velocidad de desplazamiento en pixels/segundo (era -0.2 px/frame @ 60fps) + static constexpr float STATE_PRE_CREDITS_DURATION = 3.0F; // Duración del estado previo a créditos en segundos + static constexpr float STATE_POST_CREDITS_DURATION = 5.0F; // Duración del estado posterior a créditos en segundos + static constexpr float STATE_FADE_DURATION = 5.0F; // Duración del fade final en segundos + static constexpr int MUSIC_FADE_DURATION = 3000; // Duración del fade de música en milisegundos (para Audio API) // --- Objetos y punteros --- std::vector> sprites_; // Vector con todos los sprites a dibujar std::vector> sprite_texts_; // Vector con los sprites de texto de los sprites std::vector> texts_; // Vector con los sprites de texto + std::unique_ptr delta_timer_; // Temporizador delta para time-based update // --- Variables --- - Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa std::vector sprite_list_; // Lista con todos los sprites a dibujar std::vector colors_; // Vector con los colores para el fade float sprite_max_width_ = 0; // El valor de ancho del sprite mas ancho float sprite_max_height_ = 0; // El valor de alto del sprite mas alto + float state_time_ = 0.0F; // Tiempo acumulado en el estado actual + float current_delta_ = 0.0F; // Delta time del frame actual State state_; // Controla el estado de la clase // --- Fucniones --- - void update(); // Actualiza el objeto - void render(); // Dibuja el final en pantalla - static void checkEvents(); // Comprueba el manejador de eventos - static void checkInput(); // Comprueba las entradas - void updateState(); // Actualiza el estado - void iniSpriteList(); // Inicializa la lista de sprites - void loadSprites(); // Carga todos los sprites desde una lista - void updateSprites(); // Actualiza los sprites - void updateTextSprites(); // Actualiza los sprites de texto - void updateTexts(); // Actualiza los sprites de texto del final - void renderSprites(); // Dibuja los sprites - void renderSpriteTexts(); // Dibuja los sprites con el texto - void renderTexts(); // Dibuja los sprites con el texto del final - void placeSprites(); // Coloca los sprites en su sito - void createSpriteTexts(); // Crea los sprites con las texturas con los textos - void createTexts(); // Crea los sprites con las texturas con los textos del final - void updateFinalFade(); // Actualiza el fade final - void updateMusicVolume() const; // Actualiza el volumen de la musica + void update(); // Actualiza el objeto + void render(); // Dibuja el final en pantalla + static void checkEvents(); // Comprueba el manejador de eventos + static void checkInput(); // Comprueba las entradas + void updateState(float delta_time); // Actualiza el estado + void transitionToState(EndingState new_state); // Transición entre estados + void iniSpriteList(); // Inicializa la lista de sprites + void loadSprites(); // Carga todos los sprites desde una lista + void updateSprites(float delta); // Actualiza los sprites + void updateTextSprites(float delta); // Actualiza los sprites de texto + void updateTexts(float delta); // Actualiza los sprites de texto del final + void renderSprites(); // Dibuja los sprites + void renderSpriteTexts(); // Dibuja los sprites con el texto + void renderTexts(); // Dibuja los sprites con el texto del final + void placeSprites(); // Coloca los sprites en su sito + void createSpriteTexts(); // Crea los sprites con las texturas con los textos + void createTexts(); // Crea los sprites con las texturas con los textos del final + void updateFinalFade(); // Actualiza el fade final };