forked from jaildesigner-jailgames/jaildoctors_dilemma
migrat GameOver a time based
This commit is contained in:
@@ -37,7 +37,7 @@ enum class Options {
|
||||
inline Scene current = Scene::LOGO; // Escena actual
|
||||
inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual
|
||||
#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
|
||||
#endif
|
||||
|
||||
|
||||
@@ -10,86 +10,85 @@
|
||||
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
|
||||
#include "core/rendering/text.hpp" // Para TEXT_CENTER, TEXT_COLOR, Text
|
||||
#include "core/resources/resource.hpp" // Para Resource
|
||||
#include "core/system/global_events.hpp" // Para check
|
||||
#include "external/jail_audio.h" // Para JA_PlayMusic
|
||||
#include "game/options.hpp" // Para Options, options, OptionsStats, Secti...
|
||||
#include "game/scene_manager.hpp" // Para SceneManager
|
||||
#include "utils/defines.hpp" // Para GAMECANVAS_CENTER_X, GAME_SPEED
|
||||
#include "core/system/global_events.hpp" // Para check
|
||||
#include "utils/defines.hpp" // Para GAMECANVAS_CENTER_X
|
||||
#include "utils/delta_timer.hpp" // Para DeltaTimer
|
||||
#include "utils/utils.hpp" // Para PaletteColor, stringToColor
|
||||
|
||||
// Constructor
|
||||
GameOver::GameOver()
|
||||
: 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::options = SceneManager::Options::NONE;
|
||||
|
||||
player_sprite_->setPosX(GAMECANVAS_CENTER_X + 10);
|
||||
player_sprite_->setPosY(30);
|
||||
tv_sprite_->setPosX(GAMECANVAS_CENTER_X - tv_sprite_->getWidth() - 10);
|
||||
tv_sprite_->setPosY(30);
|
||||
// Inicializa las posiciones de los sprites usando las constantes
|
||||
player_sprite_->setPosX(GAMECANVAS_CENTER_X + PLAYER_X_OFFSET);
|
||||
player_sprite_->setPosY(TEXT_Y + SPRITE_Y_OFFSET);
|
||||
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));
|
||||
|
||||
// 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"};
|
||||
for (const auto& color : COLORS) {
|
||||
colors_.push_back(stringToColor(color));
|
||||
}
|
||||
color_ = colors_.back();
|
||||
color_ = colors_.back(); // Empieza en black
|
||||
}
|
||||
|
||||
// Actualiza el objeto
|
||||
void GameOver::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 desde el último frame
|
||||
const float delta = delta_timer_->tick();
|
||||
elapsed_time_ += delta;
|
||||
|
||||
// Comprueba las entradas
|
||||
checkInput();
|
||||
// Comprueba las entradas
|
||||
checkInput();
|
||||
|
||||
// Actualiza el color usado para renderizar los textos e imagenes
|
||||
updateColor();
|
||||
// Actualiza el estado de la escena
|
||||
updateState();
|
||||
|
||||
// Actualiza los contadores
|
||||
updateCounters();
|
||||
// Actualiza el color usado para renderizar los textos e imagenes
|
||||
updateColor();
|
||||
|
||||
// Actualiza los dos sprites
|
||||
player_sprite_->update();
|
||||
tv_sprite_->update();
|
||||
// Actualiza los dos sprites (con delta time escalado por velocidad)
|
||||
player_sprite_->update();
|
||||
tv_sprite_->update();
|
||||
|
||||
// Actualiza el objeto Screen
|
||||
Screen::get()->update();
|
||||
}
|
||||
// Actualiza el objeto Screen
|
||||
Screen::get()->update();
|
||||
}
|
||||
|
||||
// Dibuja el final en pantalla
|
||||
void GameOver::render() {
|
||||
constexpr int Y = 32;
|
||||
|
||||
Screen::get()->start();
|
||||
Screen::get()->clearSurface(static_cast<Uint8>(PaletteColor::BLACK));
|
||||
|
||||
auto text = Resource::get()->getText("smb2");
|
||||
|
||||
// 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
|
||||
player_sprite_->setPosY(Y + 30);
|
||||
tv_sprite_->setPosY(Y + 30);
|
||||
// Dibuja los sprites (ya posicionados en el constructor, solo ajustamos Y)
|
||||
player_sprite_->setPosY(TEXT_Y + SPRITE_Y_OFFSET);
|
||||
tv_sprite_->setPosY(TEXT_Y + SPRITE_Y_OFFSET);
|
||||
renderSprites();
|
||||
|
||||
// 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 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, Y + 90, "ROOMS: " + ROOMS_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, TEXT_Y + ROOMS_Y_OFFSET, "ROOMS: " + ROOMS_TEXT, 1, color_);
|
||||
|
||||
// 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, Y + 120, Options::stats.worst_nightmare, 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, TEXT_Y + NIGHTMARE_TEXT_Y_OFFSET, Options::stats.worst_nightmare, 1, color_);
|
||||
|
||||
// Vuelca el contenido del renderizador en pantalla
|
||||
Screen::get()->render();
|
||||
@@ -119,16 +118,41 @@ void GameOver::run() {
|
||||
|
||||
// Actualiza el color usado para renderizar los textos e imagenes
|
||||
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) {
|
||||
const float STEP = std::min(counter_, COUNTER_FADE_LENGHT) / (float)COUNTER_FADE_LENGHT;
|
||||
const int INDEX = (colors_.size() - 1) - int((colors_.size() - 1) * STEP);
|
||||
color_ = colors_[INDEX];
|
||||
} else {
|
||||
const float STEP = std::min(std::max(counter_, COUNTER_INIT_FADE) - COUNTER_INIT_FADE, COUNTER_FADE_LENGHT) / (float)COUNTER_FADE_LENGHT;
|
||||
const int INDEX = (colors_.size() - 1) * STEP;
|
||||
color_ = colors_[INDEX];
|
||||
case State::FADE_IN: {
|
||||
// Fade in: de black (último color) a white (primer color)
|
||||
// Progreso: 0.0 (black) -> 1.0 (white)
|
||||
const float progress = std::min(elapsed_time_ / FADE_IN_DURATION, 1.0f);
|
||||
const int index = (colors_.size() - 1) - static_cast<int>((colors_.size() - 1) * progress);
|
||||
color_ = colors_[std::clamp(index, 0, static_cast<int>(colors_.size() - 1))];
|
||||
break;
|
||||
}
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
// Actualiza los contadores
|
||||
void GameOver::updateCounters() {
|
||||
// Actualiza el contador
|
||||
if (pre_counter_ < 50) {
|
||||
pre_counter_++;
|
||||
} else {
|
||||
counter_++;
|
||||
}
|
||||
// Actualiza el estado de la escena y gestiona transiciones
|
||||
void GameOver::updateState() {
|
||||
// Máquina de estados basada en tiempo transcurrido
|
||||
switch (state_) {
|
||||
case State::WAITING:
|
||||
// Espera inicial antes de empezar
|
||||
if (elapsed_time_ >= WAITING_DURATION) {
|
||||
state_ = State::FADE_IN;
|
||||
elapsed_time_ = 0.0f;
|
||||
// Hace sonar la música cuando termina la espera
|
||||
JA_PlayMusic(Resource::get()->getMusic("game_over.ogg"), 0);
|
||||
}
|
||||
break;
|
||||
|
||||
// Hace sonar la música
|
||||
if (counter_ == 1) {
|
||||
JA_PlayMusic(Resource::get()->getMusic("game_over.ogg"), 0);
|
||||
}
|
||||
case State::FADE_IN:
|
||||
// Fade in de colores desde black
|
||||
if (elapsed_time_ >= FADE_IN_DURATION) {
|
||||
state_ = State::DISPLAY;
|
||||
elapsed_time_ = 0.0f;
|
||||
}
|
||||
break;
|
||||
|
||||
// Comprueba si ha terminado la sección
|
||||
else if (counter_ == COUNTER_SECTION_END) {
|
||||
SceneManager::current = SceneManager::Scene::LOGO;
|
||||
SceneManager::options = SceneManager::Options::LOGO_TO_TITLE;
|
||||
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::options = SceneManager::Options::LOGO_TO_TITLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -5,53 +5,62 @@
|
||||
#include <memory> // Para shared_ptr
|
||||
#include <vector> // Para vector
|
||||
class SurfaceAnimatedSprite; // lines 7-7
|
||||
class DeltaTimer; // Forward declaration
|
||||
|
||||
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:
|
||||
// Constructor
|
||||
// Constructor y Destructor
|
||||
GameOver();
|
||||
|
||||
// Destructor
|
||||
~GameOver() = default;
|
||||
|
||||
// Bucle principal
|
||||
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
|
||||
};
|
||||
Reference in New Issue
Block a user