217 lines
8.3 KiB
C++
217 lines
8.3 KiB
C++
#include "game/scenes/game_over.hpp"
|
|
|
|
#include <SDL3/SDL.h>
|
|
|
|
#include <algorithm> // Para min, max
|
|
#include <string> // Para basic_string, operator+, to_string
|
|
|
|
#include "core/input/global_inputs.hpp" // Para check
|
|
#include "core/rendering/screen.hpp" // Para Screen
|
|
#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
|
|
#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"))),
|
|
delta_timer_(std::make_shared<DeltaTimer>()) {
|
|
SceneManager::current = SceneManager::Scene::GAME_OVER;
|
|
SceneManager::options = SceneManager::Options::NONE;
|
|
|
|
// 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 (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(); // Empieza en black
|
|
}
|
|
|
|
// Actualiza el objeto
|
|
void GameOver::update() {
|
|
// Obtiene el delta time desde el último frame
|
|
const float delta = delta_timer_->tick();
|
|
elapsed_time_ += delta;
|
|
|
|
// Comprueba las entradas
|
|
checkInput();
|
|
|
|
// Actualiza el estado de la escena
|
|
updateState();
|
|
|
|
// Actualiza el color usado para renderizar los textos e imagenes
|
|
updateColor();
|
|
|
|
// Actualiza los dos sprites con delta time
|
|
player_sprite_->update(delta);
|
|
tv_sprite_->update(delta);
|
|
|
|
// Actualiza el objeto Screen
|
|
Screen::get()->update(delta);
|
|
}
|
|
|
|
// Dibuja el final en pantalla
|
|
void GameOver::render() {
|
|
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, TEXT_Y, "G A M E O V E R", 1, color_);
|
|
|
|
// 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, 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, 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();
|
|
}
|
|
|
|
// Comprueba el manejador de eventos
|
|
void GameOver::checkEvents() {
|
|
SDL_Event event;
|
|
while (SDL_PollEvent(&event)) {
|
|
GlobalEvents::check(event);
|
|
}
|
|
}
|
|
|
|
// Comprueba las entradas
|
|
void GameOver::checkInput() {
|
|
GlobalInputs::check();
|
|
}
|
|
|
|
// Bucle principal
|
|
void GameOver::run() {
|
|
while (SceneManager::current == SceneManager::Scene::GAME_OVER) {
|
|
update();
|
|
checkEvents();
|
|
render();
|
|
}
|
|
}
|
|
|
|
// Actualiza el color usado para renderizar los textos e imagenes
|
|
void GameOver::updateColor() {
|
|
// Calcula el color basado en el estado actual
|
|
switch (state_) {
|
|
case State::WAITING:
|
|
// Durante la espera, mantener en black
|
|
color_ = colors_.back(); // black
|
|
break;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
// Dibuja los sprites
|
|
void GameOver::renderSprites() {
|
|
player_sprite_->render(1, color_);
|
|
tv_sprite_->render(1, color_);
|
|
}
|
|
|
|
// 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;
|
|
|
|
case State::FADE_IN:
|
|
// 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::options = SceneManager::Options::LOGO_TO_TITLE;
|
|
break;
|
|
}
|
|
} |