488 lines
18 KiB
C++
488 lines
18 KiB
C++
#include "game/scenes/title.hpp"
|
|
|
|
#include <SDL3/SDL.h>
|
|
|
|
#include <algorithm> // Para clamp
|
|
|
|
#include "core/audio/audio.hpp" // Para Audio
|
|
#include "core/input/global_inputs.hpp" // Para check
|
|
#include "core/input/input.hpp" // Para Input, InputAction, Input::DO_NOT_ALLOW_REPEAT, REP...
|
|
#include "core/rendering/screen.hpp" // Para Screen
|
|
#include "core/rendering/surface.hpp" // Para Surface
|
|
#include "core/rendering/surface_sprite.hpp" // Para SSprite
|
|
#include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR
|
|
#include "core/resources/resource.hpp" // Para Resource
|
|
#include "core/system/global_events.hpp" // Para check
|
|
#include "game/gameplay/cheevos.hpp" // Para Cheevos, Achievement
|
|
#include "game/options.hpp" // Para Options, options, SectionState, Section
|
|
#include "game/scene_manager.hpp" // Para SceneManager
|
|
#include "utils/defines.hpp" // Para PLAY_AREA_CENTER_X, GAMECANVAS_WIDTH
|
|
#include "utils/utils.hpp" // Para stringToColor, PaletteColor, playMusic
|
|
|
|
// Constructor
|
|
Title::Title()
|
|
: game_logo_surface_(Resource::get()->getSurface("title_logo.gif")),
|
|
game_logo_sprite_(std::make_unique<SurfaceSprite>(game_logo_surface_, 29, 9, game_logo_surface_->getWidth(), game_logo_surface_->getHeight())),
|
|
loading_screen_surface_(Resource::get()->getSurface("loading_screen_color.gif")),
|
|
loading_screen_sprite_(std::make_unique<SurfaceSprite>(loading_screen_surface_, 0, 0, loading_screen_surface_->getWidth(), loading_screen_surface_->getHeight())),
|
|
title_surface_(std::make_shared<Surface>(Options::game.width, Options::game.height)),
|
|
delta_timer_(std::make_unique<DeltaTimer>()),
|
|
marquee_text_(Resource::get()->getText("gauntlet")),
|
|
menu_text_(Resource::get()->getText("gauntlet")),
|
|
first_active_letter_(0),
|
|
last_active_letter_(0),
|
|
state_time_(0.0F),
|
|
fade_accumulator_(0.0F),
|
|
exit_scene_(SceneManager::Scene::GAME) {
|
|
// Inicializa variables
|
|
state_ = SceneManager::options == SceneManager::Options::TITLE_WITH_LOADING_SCREEN ? State::SHOW_LOADING_SCREEN : State::MAIN_MENU;
|
|
SceneManager::current = SceneManager::Scene::TITLE;
|
|
SceneManager::options = SceneManager::Options::NONE;
|
|
initMarquee();
|
|
|
|
// Crea y rellena la textura para mostrar los logros
|
|
createCheevosTexture();
|
|
|
|
// Cambia el color del borde
|
|
Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK));
|
|
|
|
// Inicia la musica
|
|
playMusic("title.ogg");
|
|
}
|
|
|
|
// Inicializa la marquesina
|
|
void Title::initMarquee() {
|
|
letters_.clear();
|
|
long_text_ = "HEY JAILERS!! IT'S 2022 AND WE'RE STILL ROCKING LIKE IT'S 1998!!! HAVE YOU HEARD IT? JAILGAMES ARE BACK!! YEEESSS BACK!! MORE THAN 10 TITLES ON JAILDOC'S KITCHEN!! THATS A LOOOOOOT OF JAILGAMES, BUT WHICH ONE WILL STRIKE FIRST? THERE IS ALSO A NEW DEVICE TO COME THAT WILL BLOW YOUR MIND WITH JAILGAMES ON THE GO: P.A.C.O. BUT WAIT! WHAT'S THAT BEAUTY I'M SEEING RIGHT OVER THERE?? OOOH THAT TINY MINIASCII IS PURE LOVE!! I WANT TO LICK EVERY BYTE OF IT!! OH SHIT! AND DON'T FORGET TO BRING BACK THOSE OLD AND FAT MS-DOS JAILGAMES TO GITHUB TO KEEP THEM ALIVE!! WHAT WILL BE THE NEXT JAILDOC RELEASE? WHAT WILL BE THE NEXT PROJECT TO COME ALIVE?? OH BABY WE DON'T KNOW BUT HERE YOU CAN FIND THE ANSWER, YOU JUST HAVE TO COMPLETE JAILDOCTOR'S DILEMMA ... COULD YOU?";
|
|
|
|
// Pre-calcular anchos de caracteres para eficiencia
|
|
for (size_t i = 0; i < long_text_.length(); ++i) {
|
|
Glyph l;
|
|
l.letter = long_text_[i]; // char directo, no substring
|
|
l.x = MARQUEE_START_X; // Usar constante
|
|
l.width = marquee_text_->lenght(std::string(1, long_text_[i])); // Pre-calcular ancho
|
|
l.enabled = false;
|
|
letters_.push_back(l);
|
|
}
|
|
|
|
letters_[0].enabled = true;
|
|
first_active_letter_ = 0;
|
|
last_active_letter_ = 0;
|
|
}
|
|
|
|
// Comprueba el manejador de eventos
|
|
void Title::handleEvents() {
|
|
SDL_Event event;
|
|
while (SDL_PollEvent(&event)) {
|
|
GlobalEvents::handle(event);
|
|
|
|
if (event.type == SDL_EVENT_KEY_DOWN) {
|
|
switch (state_) {
|
|
case State::MAIN_MENU:
|
|
switch (event.key.key) {
|
|
case SDLK_1:
|
|
exit_scene_ = SceneManager::Scene::GAME;
|
|
transitionToState(State::FADE_MENU);
|
|
Audio::get()->fadeOutMusic(1000);
|
|
break;
|
|
|
|
case SDLK_2:
|
|
transitionToState(State::CONTROLS_MENU);
|
|
break;
|
|
|
|
case SDLK_3:
|
|
transitionToState(State::CHEEVOS_MENU);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Comprueba las entradas
|
|
void Title::handleInput(float delta_time) {
|
|
Input::get()->update();
|
|
|
|
switch (state_) {
|
|
case State::SHOW_LOADING_SCREEN:
|
|
if (Input::get()->checkAction(InputAction::ACCEPT, Input::DO_NOT_ALLOW_REPEAT)) {
|
|
transitionToState(State::FADE_LOADING_SCREEN);
|
|
}
|
|
break;
|
|
|
|
case State::CHEEVOS_MENU:
|
|
if (Input::get()->checkAction(InputAction::RIGHT, Input::ALLOW_REPEAT)) {
|
|
moveCheevosList(1, delta_time);
|
|
} else if (Input::get()->checkAction(InputAction::LEFT, Input::ALLOW_REPEAT)) {
|
|
moveCheevosList(0, delta_time);
|
|
}
|
|
|
|
if (Input::get()->checkAction(InputAction::ACCEPT, Input::DO_NOT_ALLOW_REPEAT) ||
|
|
Input::get()->checkAction(InputAction::CANCEL, Input::DO_NOT_ALLOW_REPEAT)) {
|
|
resetCheevosScroll();
|
|
transitionToState(State::MAIN_MENU);
|
|
}
|
|
break;
|
|
|
|
case State::CONTROLS_MENU:
|
|
if (Input::get()->checkAction(InputAction::ACCEPT, Input::DO_NOT_ALLOW_REPEAT) ||
|
|
Input::get()->checkAction(InputAction::CANCEL, Input::DO_NOT_ALLOW_REPEAT)) {
|
|
transitionToState(State::MAIN_MENU);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
GlobalInputs::handle();
|
|
}
|
|
|
|
// Actualiza la marquesina
|
|
void Title::updateMarquee(float delta_time) {
|
|
const float DISPLACEMENT = MARQUEE_SPEED * delta_time;
|
|
|
|
// Solo procesar letras en rango activo + 1 para poder activar la siguiente
|
|
for (int i = first_active_letter_; i <= last_active_letter_ + 1 && i < (int)letters_.size(); ++i) {
|
|
auto& letter = letters_[i];
|
|
|
|
if (letter.enabled) {
|
|
letter.x -= DISPLACEMENT;
|
|
|
|
// Desactivar si sale de pantalla
|
|
if (letter.x < MARQUEE_EXIT_X) {
|
|
letter.enabled = false;
|
|
if (i == first_active_letter_) {
|
|
first_active_letter_++; // Avanzar inicio del rango
|
|
}
|
|
}
|
|
} else if (i > 0 && letters_[i - 1].x < MARQUEE_START_X && letters_[i - 1].enabled) {
|
|
// Activar siguiente letra usando ancho pre-calculado
|
|
letter.enabled = true;
|
|
letter.x = letters_[i - 1].x + letters_[i - 1].width + MARQUEE_LETTER_SPACING;
|
|
last_active_letter_ = i; // Expandir fin del rango
|
|
}
|
|
}
|
|
|
|
// Comprueba si ha terminado la marquesina y la reinicia
|
|
if (letters_[letters_.size() - 1].x < MARQUEE_EXIT_X) {
|
|
initMarquee();
|
|
}
|
|
}
|
|
|
|
// Dibuja la marquesina
|
|
void Title::renderMarquee() {
|
|
// Solo renderizar letras activas (optimización: usa cache y rangos)
|
|
for (int i = first_active_letter_; i <= last_active_letter_ + 1 && i < (int)letters_.size(); ++i) {
|
|
const auto& letter = letters_[i];
|
|
if (letter.enabled) {
|
|
marquee_text_->writeColored(
|
|
static_cast<int>(letter.x), // Conversión explícita float→int
|
|
static_cast<int>(MARQUEE_Y), // Usar constante
|
|
std::string(1, letter.letter), // Convertir char a string
|
|
static_cast<Uint8>(PaletteColor::MAGENTA));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Actualiza las variables
|
|
void Title::update() {
|
|
const float DELTA_TIME = delta_timer_->tick();
|
|
|
|
handleEvents(); // Comprueba los eventos
|
|
handleInput(DELTA_TIME); // Comprueba las entradas
|
|
|
|
updateState(DELTA_TIME); // Actualiza el estado actual
|
|
|
|
Audio::get()->update(); // Actualiza el objeto Audio
|
|
Screen::get()->update(DELTA_TIME); // Actualiza el objeto Screen
|
|
}
|
|
|
|
// Actualiza el estado actual
|
|
void Title::updateState(float delta_time) {
|
|
switch (state_) {
|
|
case State::SHOW_LOADING_SCREEN:
|
|
updateShowLoadingScreen(delta_time);
|
|
break;
|
|
|
|
case State::FADE_LOADING_SCREEN:
|
|
updateFadeLoadingScreen(delta_time);
|
|
break;
|
|
|
|
case State::MAIN_MENU:
|
|
updateMainMenu(delta_time);
|
|
break;
|
|
|
|
case State::CHEEVOS_MENU:
|
|
updateCheevosMenu(delta_time);
|
|
break;
|
|
|
|
case State::CONTROLS_MENU:
|
|
updateControlsMenu(delta_time);
|
|
break;
|
|
|
|
case State::FADE_MENU:
|
|
updateFadeMenu(delta_time);
|
|
break;
|
|
|
|
case State::POST_FADE_MENU:
|
|
updatePostFadeMenu(delta_time);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Transiciona a un nuevo estado
|
|
void Title::transitionToState(State new_state) {
|
|
state_ = new_state;
|
|
state_time_ = 0.0F;
|
|
fade_accumulator_ = 0.0F;
|
|
}
|
|
|
|
// Actualiza el estado SHOW_LOADING_SCREEN
|
|
void Title::updateShowLoadingScreen(float delta_time) {
|
|
state_time_ += delta_time;
|
|
if (state_time_ >= SHOW_LOADING_DURATION) {
|
|
transitionToState(State::FADE_LOADING_SCREEN);
|
|
}
|
|
}
|
|
|
|
// Actualiza el estado FADE_LOADING_SCREEN
|
|
void Title::updateFadeLoadingScreen(float delta_time) {
|
|
fade_accumulator_ += delta_time;
|
|
if (fade_accumulator_ >= FADE_STEP_INTERVAL) {
|
|
fade_accumulator_ = 0.0F;
|
|
if (loading_screen_surface_->fadeSubPalette()) {
|
|
transitionToState(State::MAIN_MENU);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Actualiza el estado MAIN_MENU
|
|
void Title::updateMainMenu(float delta_time) {
|
|
// Actualiza la marquesina
|
|
updateMarquee(delta_time);
|
|
|
|
// Incrementa el temporizador solo en el menú principal
|
|
state_time_ += delta_time;
|
|
|
|
// Si el tiempo alcanza el timeout, va a créditos con fade
|
|
if (state_time_ >= MAIN_MENU_IDLE_TIMEOUT) {
|
|
exit_scene_ = SceneManager::Scene::CREDITS;
|
|
transitionToState(State::FADE_MENU);
|
|
}
|
|
}
|
|
|
|
// Actualiza el estado CHEEVOS_MENU
|
|
void Title::updateCheevosMenu(float delta_time) {
|
|
// Actualiza la marquesina (sigue visible en fondo)
|
|
updateMarquee(delta_time);
|
|
// No incrementar state_time_ (no timeout en este estado)
|
|
}
|
|
|
|
// Actualiza el estado CONTROLS_MENU
|
|
void Title::updateControlsMenu(float delta_time) {
|
|
// Actualiza la marquesina (sigue visible en fondo)
|
|
updateMarquee(delta_time);
|
|
// No incrementar state_time_ (no timeout en este estado)
|
|
}
|
|
|
|
// Actualiza el estado FADE_MENU
|
|
void Title::updateFadeMenu(float delta_time) {
|
|
fade_accumulator_ += delta_time;
|
|
if (fade_accumulator_ >= FADE_STEP_INTERVAL) {
|
|
fade_accumulator_ = 0.0F;
|
|
if (title_surface_->fadeSubPalette()) {
|
|
transitionToState(State::POST_FADE_MENU);
|
|
}
|
|
}
|
|
// Actualiza la marquesina (sigue visible en fondo)
|
|
updateMarquee(delta_time);
|
|
}
|
|
|
|
// Actualiza el estado POST_FADE_MENU
|
|
void Title::updatePostFadeMenu(float delta_time) {
|
|
state_time_ += delta_time;
|
|
if (state_time_ >= POST_FADE_DELAY) {
|
|
SceneManager::current = exit_scene_;
|
|
SceneManager::options = SceneManager::Options::NONE;
|
|
}
|
|
}
|
|
|
|
// Dibuja en pantalla
|
|
void Title::render() {
|
|
// Rellena la surface
|
|
fillTitleSurface();
|
|
|
|
// Prepara para empezar a dibujar en la textura de juego
|
|
Screen::get()->start();
|
|
Screen::get()->clearSurface(static_cast<Uint8>(PaletteColor::BLACK));
|
|
|
|
// Dibuja en pantalla la surface con la composicion
|
|
title_surface_->render();
|
|
|
|
// Vuelca el contenido del renderizador en pantalla
|
|
Screen::get()->render();
|
|
}
|
|
|
|
// Bucle para el logo del juego
|
|
void Title::run() {
|
|
while (SceneManager::current == SceneManager::Scene::TITLE) {
|
|
update();
|
|
render();
|
|
}
|
|
}
|
|
|
|
// Desplaza la lista de logros
|
|
void Title::moveCheevosList(int direction, float delta_time) {
|
|
// Calcula el desplazamiento basado en tiempo
|
|
const float DISPLACEMENT = CHEEVOS_SCROLL_SPEED * delta_time;
|
|
|
|
// Modifica la posición de la ventana de vista
|
|
cheevos_surface_view_.y = direction == 0
|
|
? cheevos_surface_view_.y - DISPLACEMENT
|
|
: cheevos_surface_view_.y + DISPLACEMENT;
|
|
|
|
// Ajusta los limites
|
|
const float BOTTOM = cheevos_surface_->getHeight() - cheevos_surface_view_.h;
|
|
cheevos_surface_view_.y = std::clamp(cheevos_surface_view_.y, 0.0F, BOTTOM);
|
|
|
|
cheevos_sprite_->setClip(cheevos_surface_view_);
|
|
}
|
|
|
|
// Crea y rellena la textura para mostrar los logros
|
|
void Title::createCheevosTexture() {
|
|
// Crea la textura con el listado de logros
|
|
const auto CHEEVOS_LIST = Cheevos::get()->list();
|
|
const auto TEXT = Resource::get()->getText("subatomic");
|
|
constexpr int CHEEVOS_TEXTURE_WIDTH = 200;
|
|
constexpr int CHEEVOS_TEXTURE_VIEW_HEIGHT = 110 - 8;
|
|
constexpr int CHEEVOS_TEXTURE_POS_Y = 73;
|
|
constexpr int CHEEVOS_PADDING = 10;
|
|
const int CHEEVO_HEIGHT = CHEEVOS_PADDING + (TEXT->getCharacterSize() * 2) + 1;
|
|
const int CHEEVOS_TEXTURE_HEIGHT = (CHEEVO_HEIGHT * CHEEVOS_LIST.size()) + 2 + TEXT->getCharacterSize() + 8;
|
|
cheevos_surface_ = std::make_shared<Surface>(CHEEVOS_TEXTURE_WIDTH, CHEEVOS_TEXTURE_HEIGHT);
|
|
|
|
// Prepara para dibujar sobre la textura
|
|
auto previuos_renderer = Screen::get()->getRendererSurface();
|
|
Screen::get()->setRendererSurface(cheevos_surface_);
|
|
|
|
// Rellena la textura con color sólido
|
|
const auto CHEEVOS_BG_COLOR = static_cast<Uint8>(PaletteColor::BLACK);
|
|
cheevos_surface_->clear(CHEEVOS_BG_COLOR);
|
|
|
|
// Escribe la lista de logros en la textura
|
|
const std::string CHEEVOS_OWNER = "ACHIEVEMENTS";
|
|
const std::string CHEEVOS_LIST_CAPTION = CHEEVOS_OWNER + " (" + std::to_string(Cheevos::get()->getTotalUnlockedAchievements()) + " / " + std::to_string(Cheevos::get()->size()) + ")";
|
|
int pos = 2;
|
|
TEXT->writeDX(TEXT_CENTER | TEXT_COLOR, cheevos_surface_->getWidth() / 2, pos, CHEEVOS_LIST_CAPTION, 1, stringToColor("bright_green"));
|
|
pos += TEXT->getCharacterSize();
|
|
const Uint8 CHEEVO_LOCKED_COLOR = stringToColor("white");
|
|
const Uint8 CHEEVO_UNLOCKED_COLOR = stringToColor("bright_green");
|
|
constexpr int LINE_X1 = (CHEEVOS_TEXTURE_WIDTH / 7) * 3;
|
|
constexpr int LINE_X2 = LINE_X1 + ((CHEEVOS_TEXTURE_WIDTH / 7) * 1);
|
|
|
|
for (const auto& cheevo : CHEEVOS_LIST) {
|
|
const Uint8 CHEEVO_COLOR = cheevo.completed ? CHEEVO_UNLOCKED_COLOR : CHEEVO_LOCKED_COLOR;
|
|
pos += CHEEVOS_PADDING;
|
|
constexpr int HALF = CHEEVOS_PADDING / 2;
|
|
cheevos_surface_->drawLine(LINE_X1, pos - HALF - 1, LINE_X2, pos - HALF - 1, CHEEVO_COLOR);
|
|
TEXT->writeDX(TEXT_CENTER | TEXT_COLOR, CHEEVOS_TEXTURE_WIDTH / 2, pos, cheevo.caption, 1, CHEEVO_COLOR);
|
|
pos += TEXT->getCharacterSize() + 1;
|
|
TEXT->writeDX(TEXT_CENTER | TEXT_COLOR, CHEEVOS_TEXTURE_WIDTH / 2, pos, cheevo.description, 1, CHEEVO_COLOR);
|
|
pos += TEXT->getCharacterSize();
|
|
}
|
|
|
|
// Restablece el RenderSurface
|
|
Screen::get()->setRendererSurface(previuos_renderer);
|
|
|
|
// Crea el sprite para el listado de logros
|
|
cheevos_sprite_ = std::make_unique<SurfaceSprite>(cheevos_surface_, (GAMECANVAS_WIDTH - cheevos_surface_->getWidth()) / 2, CHEEVOS_TEXTURE_POS_Y, cheevos_surface_->getWidth(), cheevos_surface_->getHeight());
|
|
cheevos_surface_view_ = {.x = 0, .y = 0, .w = cheevos_surface_->getWidth(), .h = CHEEVOS_TEXTURE_VIEW_HEIGHT};
|
|
cheevos_sprite_->setClip(cheevos_surface_view_);
|
|
}
|
|
|
|
// Resetea el scroll de la lista de logros
|
|
void Title::resetCheevosScroll() {
|
|
cheevos_surface_view_.y = 0;
|
|
cheevos_sprite_->setClip(cheevos_surface_view_);
|
|
}
|
|
|
|
// Dibuja el logo con el titulo del juego
|
|
void Title::renderGameLogo() {
|
|
game_logo_sprite_->render();
|
|
}
|
|
|
|
// Dibuja el menu principal
|
|
void Title::renderMainMenu() {
|
|
const Uint8 COLOR = stringToColor("green");
|
|
const int TEXT_SIZE = menu_text_->getCharacterSize();
|
|
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 11 * TEXT_SIZE, "1. PLAY", 1, COLOR);
|
|
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 13 * TEXT_SIZE, "2. CONTROLS", 1, COLOR);
|
|
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 15 * TEXT_SIZE, "3. ACHIEVEMENTS", 1, COLOR);
|
|
}
|
|
|
|
// Dibuja el menu de logros
|
|
void Title::renderCheevosMenu() {
|
|
cheevos_sprite_->render();
|
|
}
|
|
|
|
// Dibuja el menu de controles
|
|
void Title::renderControlsMenu() {
|
|
const Uint8 COLOR = stringToColor("green");
|
|
const int TEXT_SIZE = menu_text_->getCharacterSize();
|
|
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 11 * TEXT_SIZE, "1. REDEFINE KEYBOARD", 1, COLOR);
|
|
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 13 * TEXT_SIZE, "2. REDEFINE JOYSTICK", 1, COLOR);
|
|
}
|
|
|
|
// Dibuja los elementos en la surface
|
|
void Title::fillTitleSurface() {
|
|
// Renderiza sobre la textura
|
|
auto previuos_renderer = Screen::get()->getRendererSurface();
|
|
Screen::get()->setRendererSurface(title_surface_);
|
|
|
|
// Rellena la textura de color
|
|
title_surface_->clear(static_cast<Uint8>(PaletteColor::BLACK));
|
|
|
|
switch (state_) {
|
|
case State::MAIN_MENU:
|
|
case State::FADE_MENU:
|
|
renderGameLogo();
|
|
renderMainMenu();
|
|
renderMarquee();
|
|
break;
|
|
|
|
case State::CHEEVOS_MENU:
|
|
renderGameLogo();
|
|
renderCheevosMenu();
|
|
renderMarquee();
|
|
break;
|
|
|
|
case State::CONTROLS_MENU:
|
|
renderGameLogo();
|
|
renderControlsMenu();
|
|
renderMarquee();
|
|
break;
|
|
|
|
case State::SHOW_LOADING_SCREEN:
|
|
case State::FADE_LOADING_SCREEN:
|
|
loading_screen_sprite_->render();
|
|
renderGameLogo();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// Deja el renderizador como estaba
|
|
Screen::get()->setRendererSurface(previuos_renderer);
|
|
} |