migrat GameOver a time based

This commit is contained in:
2025-10-27 19:22:36 +01:00
parent 6af2d72ea8
commit 70b76edcbf
3 changed files with 168 additions and 102 deletions

View File

@@ -37,7 +37,7 @@ enum class Options {
inline Scene current = Scene::LOGO; // Escena actual inline Scene current = Scene::LOGO; // Escena actual
inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual
#else #else
inline Scene current = Scene::TITLE; // Escena actual inline Scene current = Scene::GAME_OVER; // Escena actual
inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual
#endif #endif

View File

@@ -10,86 +10,85 @@
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite #include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
#include "core/rendering/text.hpp" // Para TEXT_CENTER, TEXT_COLOR, Text #include "core/rendering/text.hpp" // Para TEXT_CENTER, TEXT_COLOR, Text
#include "core/resources/resource.hpp" // Para Resource #include "core/resources/resource.hpp" // Para Resource
#include "core/system/global_events.hpp" // Para check
#include "external/jail_audio.h" // Para JA_PlayMusic #include "external/jail_audio.h" // Para JA_PlayMusic
#include "game/options.hpp" // Para Options, options, OptionsStats, Secti... #include "game/options.hpp" // Para Options, options, OptionsStats, Secti...
#include "game/scene_manager.hpp" // Para SceneManager #include "game/scene_manager.hpp" // Para SceneManager
#include "utils/defines.hpp" // Para GAMECANVAS_CENTER_X, GAME_SPEED #include "utils/defines.hpp" // Para GAMECANVAS_CENTER_X
#include "core/system/global_events.hpp" // Para check #include "utils/delta_timer.hpp" // Para DeltaTimer
#include "utils/utils.hpp" // Para PaletteColor, stringToColor #include "utils/utils.hpp" // Para PaletteColor, stringToColor
// Constructor // Constructor
GameOver::GameOver() GameOver::GameOver()
: player_sprite_(std::make_shared<SurfaceAnimatedSprite>(Resource::get()->getSurface("player_game_over.gif"), Resource::get()->getAnimations("player_game_over.ani"))), : player_sprite_(std::make_shared<SurfaceAnimatedSprite>(Resource::get()->getSurface("player_game_over.gif"), Resource::get()->getAnimations("player_game_over.ani"))),
tv_sprite_(std::make_shared<SurfaceAnimatedSprite>(Resource::get()->getSurface("tv.gif"), Resource::get()->getAnimations("tv.ani"))) { tv_sprite_(std::make_shared<SurfaceAnimatedSprite>(Resource::get()->getSurface("tv.gif"), Resource::get()->getAnimations("tv.ani"))),
delta_timer_(std::make_shared<DeltaTimer>()) {
SceneManager::current = SceneManager::Scene::GAME_OVER; SceneManager::current = SceneManager::Scene::GAME_OVER;
SceneManager::options = SceneManager::Options::NONE; SceneManager::options = SceneManager::Options::NONE;
player_sprite_->setPosX(GAMECANVAS_CENTER_X + 10); // Inicializa las posiciones de los sprites usando las constantes
player_sprite_->setPosY(30); player_sprite_->setPosX(GAMECANVAS_CENTER_X + PLAYER_X_OFFSET);
tv_sprite_->setPosX(GAMECANVAS_CENTER_X - tv_sprite_->getWidth() - 10); player_sprite_->setPosY(TEXT_Y + SPRITE_Y_OFFSET);
tv_sprite_->setPosY(30); tv_sprite_->setPosX(GAMECANVAS_CENTER_X - tv_sprite_->getWidth() - TV_X_OFFSET);
tv_sprite_->setPosY(TEXT_Y + SPRITE_Y_OFFSET);
Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK)); Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK));
// Inicializa el vector de colores // Inicializa el vector de colores (de brillante a oscuro para fade)
const std::vector<std::string> COLORS = {"white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"}; const std::vector<std::string> COLORS = {"white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"};
for (const auto& color : COLORS) { for (const auto& color : COLORS) {
colors_.push_back(stringToColor(color)); colors_.push_back(stringToColor(color));
} }
color_ = colors_.back(); color_ = colors_.back(); // Empieza en black
} }
// Actualiza el objeto // Actualiza el objeto
void GameOver::update() { void GameOver::update() {
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego // Obtiene el delta time desde el último frame
if (SDL_GetTicks() - ticks_ > GAME_SPEED) { const float delta = delta_timer_->tick();
// Actualiza el contador de ticks elapsed_time_ += delta;
ticks_ = SDL_GetTicks();
// Comprueba las entradas // Comprueba las entradas
checkInput(); checkInput();
// Actualiza el estado de la escena
updateState();
// Actualiza el color usado para renderizar los textos e imagenes // Actualiza el color usado para renderizar los textos e imagenes
updateColor(); updateColor();
// Actualiza los contadores // Actualiza los dos sprites (con delta time escalado por velocidad)
updateCounters();
// Actualiza los dos sprites
player_sprite_->update(); player_sprite_->update();
tv_sprite_->update(); tv_sprite_->update();
// Actualiza el objeto Screen // Actualiza el objeto Screen
Screen::get()->update(); Screen::get()->update();
}
} }
// Dibuja el final en pantalla // Dibuja el final en pantalla
void GameOver::render() { void GameOver::render() {
constexpr int Y = 32;
Screen::get()->start(); Screen::get()->start();
Screen::get()->clearSurface(static_cast<Uint8>(PaletteColor::BLACK)); Screen::get()->clearSurface(static_cast<Uint8>(PaletteColor::BLACK));
auto text = Resource::get()->getText("smb2"); auto text = Resource::get()->getText("smb2");
// Escribe el texto de GAME OVER // Escribe el texto de GAME OVER
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y, "G A M E O V E R", 1, color_); text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, TEXT_Y, "G A M E O V E R", 1, color_);
// Dibuja los sprites // Dibuja los sprites (ya posicionados en el constructor, solo ajustamos Y)
player_sprite_->setPosY(Y + 30); player_sprite_->setPosY(TEXT_Y + SPRITE_Y_OFFSET);
tv_sprite_->setPosY(Y + 30); tv_sprite_->setPosY(TEXT_Y + SPRITE_Y_OFFSET);
renderSprites(); renderSprites();
// Escribe el texto con las habitaciones y los items // Escribe el texto con las habitaciones y los items
const std::string ITEMS_TEXT = std::to_string(Options::stats.items / 100) + std::to_string((Options::stats.items % 100) / 10) + std::to_string(Options::stats.items % 10); const std::string ITEMS_TEXT = std::to_string(Options::stats.items / 100) + std::to_string((Options::stats.items % 100) / 10) + std::to_string(Options::stats.items % 10);
const std::string ROOMS_TEXT = std::to_string(Options::stats.rooms / 100) + std::to_string((Options::stats.rooms % 100) / 10) + std::to_string(Options::stats.rooms % 10); const std::string ROOMS_TEXT = std::to_string(Options::stats.rooms / 100) + std::to_string((Options::stats.rooms % 100) / 10) + std::to_string(Options::stats.rooms % 10);
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 80, "ITEMS: " + ITEMS_TEXT, 1, color_); text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, TEXT_Y + ITEMS_Y_OFFSET, "ITEMS: " + ITEMS_TEXT, 1, color_);
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 90, "ROOMS: " + ROOMS_TEXT, 1, color_); text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, TEXT_Y + ROOMS_Y_OFFSET, "ROOMS: " + ROOMS_TEXT, 1, color_);
// Escribe el texto con "Tu peor pesadilla" // Escribe el texto con "Tu peor pesadilla"
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 110, "YOUR WORST NIGHTMARE IS", 1, color_); text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, TEXT_Y + NIGHTMARE_TITLE_Y_OFFSET, "YOUR WORST NIGHTMARE IS", 1, color_);
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 120, Options::stats.worst_nightmare, 1, color_); text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, TEXT_Y + NIGHTMARE_TEXT_Y_OFFSET, Options::stats.worst_nightmare, 1, color_);
// Vuelca el contenido del renderizador en pantalla // Vuelca el contenido del renderizador en pantalla
Screen::get()->render(); Screen::get()->render();
@@ -119,16 +118,41 @@ void GameOver::run() {
// Actualiza el color usado para renderizar los textos e imagenes // Actualiza el color usado para renderizar los textos e imagenes
void GameOver::updateColor() { void GameOver::updateColor() {
const int HALF = COUNTER_SECTION_END / 2; // Calcula el color basado en el estado actual
switch (state_) {
case State::WAITING:
// Durante la espera, mantener en black
color_ = colors_.back(); // black
break;
if (counter_ < HALF) { case State::FADE_IN: {
const float STEP = std::min(counter_, COUNTER_FADE_LENGHT) / (float)COUNTER_FADE_LENGHT; // Fade in: de black (último color) a white (primer color)
const int INDEX = (colors_.size() - 1) - int((colors_.size() - 1) * STEP); // Progreso: 0.0 (black) -> 1.0 (white)
color_ = colors_[INDEX]; const float progress = std::min(elapsed_time_ / FADE_IN_DURATION, 1.0f);
} else { const int index = (colors_.size() - 1) - static_cast<int>((colors_.size() - 1) * progress);
const float STEP = std::min(std::max(counter_, COUNTER_INIT_FADE) - COUNTER_INIT_FADE, COUNTER_FADE_LENGHT) / (float)COUNTER_FADE_LENGHT; color_ = colors_[std::clamp(index, 0, static_cast<int>(colors_.size() - 1))];
const int INDEX = (colors_.size() - 1) * STEP; break;
color_ = colors_[INDEX]; }
case State::DISPLAY:
// Durante display, mantener el color más brillante
color_ = colors_[0]; // white
break;
case State::FADE_OUT: {
// Fade out: de white (primer color) a black (último color)
// Progreso: 0.0 (white) -> 1.0 (black)
const float progress = std::min(elapsed_time_ / FADE_OUT_DURATION, 1.0f);
const int index = static_cast<int>((colors_.size() - 1) * progress);
color_ = colors_[std::clamp(index, 0, static_cast<int>(colors_.size() - 1))];
break;
}
case State::ENDING:
case State::TRANSITION:
// Al final, mantener en black
color_ = colors_.back(); // black
break;
} }
} }
@@ -138,23 +162,56 @@ void GameOver::renderSprites() {
tv_sprite_->render(1, color_); tv_sprite_->render(1, color_);
} }
// Actualiza los contadores // Actualiza el estado de la escena y gestiona transiciones
void GameOver::updateCounters() { void GameOver::updateState() {
// Actualiza el contador // Máquina de estados basada en tiempo transcurrido
if (pre_counter_ < 50) { switch (state_) {
pre_counter_++; case State::WAITING:
} else { // Espera inicial antes de empezar
counter_++; if (elapsed_time_ >= WAITING_DURATION) {
} state_ = State::FADE_IN;
elapsed_time_ = 0.0f;
// Hace sonar la música // Hace sonar la música cuando termina la espera
if (counter_ == 1) {
JA_PlayMusic(Resource::get()->getMusic("game_over.ogg"), 0); JA_PlayMusic(Resource::get()->getMusic("game_over.ogg"), 0);
} }
break;
// Comprueba si ha terminado la sección case State::FADE_IN:
else if (counter_ == COUNTER_SECTION_END) { // Fade in de colores desde black
if (elapsed_time_ >= FADE_IN_DURATION) {
state_ = State::DISPLAY;
elapsed_time_ = 0.0f;
}
break;
case State::DISPLAY:
// Mostrando contenido con color brillante
if (elapsed_time_ >= DISPLAY_DURATION) {
state_ = State::FADE_OUT;
elapsed_time_ = 0.0f;
}
break;
case State::FADE_OUT:
// Fade out hacia black
if (elapsed_time_ >= FADE_OUT_DURATION) {
state_ = State::ENDING;
elapsed_time_ = 0.0f;
}
break;
case State::ENDING:
// Pantalla en negro antes de salir
if (elapsed_time_ >= ENDING_DURATION) {
state_ = State::TRANSITION;
elapsed_time_ = 0.0f;
}
break;
case State::TRANSITION:
// Transición a la escena de logo
SceneManager::current = SceneManager::Scene::LOGO; SceneManager::current = SceneManager::Scene::LOGO;
SceneManager::options = SceneManager::Options::LOGO_TO_TITLE; SceneManager::options = SceneManager::Options::LOGO_TO_TITLE;
break;
} }
} }

View File

@@ -5,53 +5,62 @@
#include <memory> // Para shared_ptr #include <memory> // Para shared_ptr
#include <vector> // Para vector #include <vector> // Para vector
class SurfaceAnimatedSprite; // lines 7-7 class SurfaceAnimatedSprite; // lines 7-7
class DeltaTimer; // Forward declaration
class GameOver { class GameOver {
private:
// Constantes
static constexpr int COUNTER_SECTION_END = 400; // Contador: cuando acaba la sección
static constexpr int COUNTER_INIT_FADE = 310; // Contador: cuando emiepza el fade
static constexpr int COUNTER_FADE_LENGHT = 20; // Contador: duración del fade
// Objetos y punteros
std::shared_ptr<SurfaceAnimatedSprite> player_sprite_; // Sprite con el jugador
std::shared_ptr<SurfaceAnimatedSprite> tv_sprite_; // Sprite con el televisor
// Variables
int pre_counter_ = 0; // Contador previo
int counter_ = 0; // Contador
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
std::vector<Uint8> colors_; // Vector con los colores para el fade
Uint8 color_; // Color usado para el texto y los sprites
// Actualiza el objeto
void update();
// Dibuja el final en pantalla
void render();
// Comprueba el manejador de eventos
static void checkEvents();
// Comprueba las entradas
static void checkInput();
// Actualiza el color usado para renderizar los textos e imagenes
void updateColor();
// Dibuja los sprites
void renderSprites();
// Actualiza los contadores
void updateCounters();
public: public:
// Constructor // Constructor y Destructor
GameOver(); GameOver();
// Destructor
~GameOver() = default; ~GameOver() = default;
// Bucle principal // Bucle principal
void run(); void run();
private:
// --- Estados ---
enum class State {
WAITING, // Espera inicial antes de empezar
FADE_IN, // Fade in de colores desde black
DISPLAY, // Mostrando contenido con color brillante
FADE_OUT, // Fade out hacia black
ENDING, // Pantalla en negro antes de salir
TRANSITION // Cambio a logo
};
// --- Constantes de Duración (segundos) ---
static constexpr float WAITING_DURATION = 0.8f; // Espera inicial
static constexpr float FADE_IN_DURATION = 0.32f; // Duración del fade in
static constexpr float DISPLAY_DURATION = 4.64f; // Duración mostrando contenido
static constexpr float FADE_OUT_DURATION = 0.32f; // Duración del fade out
static constexpr float ENDING_DURATION = 1.12f; // Espera en negro antes de salir
// --- Constantes de Posición ---
static constexpr int TEXT_Y = 32; // Posición Y del texto principal
static constexpr int SPRITE_Y_OFFSET = 30; // Offset Y para sprites desde TEXT_Y
static constexpr int PLAYER_X_OFFSET = 10; // Offset X del jugador desde el centro
static constexpr int TV_X_OFFSET = 10; // Offset X del TV desde el centro
static constexpr int ITEMS_Y_OFFSET = 80; // Offset Y del texto de items desde TEXT_Y
static constexpr int ROOMS_Y_OFFSET = 90; // Offset Y del texto de rooms desde TEXT_Y
static constexpr int NIGHTMARE_TITLE_Y_OFFSET = 110; // Offset Y del título nightmare desde TEXT_Y
static constexpr int NIGHTMARE_TEXT_Y_OFFSET = 120; // Offset Y del texto nightmare desde TEXT_Y
// --- Objetos y punteros ---
std::shared_ptr<SurfaceAnimatedSprite> player_sprite_; // Sprite con el jugador
std::shared_ptr<SurfaceAnimatedSprite> tv_sprite_; // Sprite con el televisor
std::shared_ptr<DeltaTimer> delta_timer_; // Timer para time-based logic
// --- Variables ---
State state_ = State::WAITING; // Estado actual de la escena
float elapsed_time_ = 0.0f; // Tiempo transcurrido en el estado actual
std::vector<Uint8> colors_; // Vector con los colores para el fade
Uint8 color_; // Color usado para el texto y los sprites
// --- Funciones ---
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 y transiciones
void updateColor(); // Actualiza el color usado para renderizar los textos e imagenes
void renderSprites(); // Dibuja los sprites
}; };