This commit is contained in:
2025-11-03 09:52:54 +01:00
parent 1409ab5bff
commit 3f1c737247
32 changed files with 254 additions and 243 deletions

View File

@@ -170,7 +170,7 @@ void Credits::update() {
shining_sprite_->update(DELTA_TIME);
}
Audio::get()->update(); // Actualiza el objeto Audio
Audio::update(); // Actualiza el objeto Audio
Screen::get()->update(DELTA_TIME); // Actualiza el objeto Screen
}

View File

@@ -55,7 +55,7 @@ void Ending::update() {
updateState(DELTA_TIME); // Actualiza la máquina de estados
updateSpriteCovers(); // Actualiza las cortinillas de los elementos
Audio::get()->update(); // Actualiza el objeto Audio
Audio::update(); // Actualiza el objeto Audio
Screen::get()->update(DELTA_TIME); // Actualiza el objeto Screen
}
@@ -496,43 +496,43 @@ void Ending::updateSpriteCovers() {
// Comprueba si se ha de cambiar de escena
void Ending::checkChangeScene() {
// Obtener duración de la escena actual
float CURRENT_DURATION = 0.0F;
State NEXT_STATE = State::ENDING;
float current_duration = 0.0F;
State next_state = State::ENDING;
switch (state_) {
case State::SCENE_0:
CURRENT_DURATION = SCENE_0_DURATION;
NEXT_STATE = State::SCENE_1;
current_duration = SCENE_0_DURATION;
next_state = State::SCENE_1;
break;
case State::SCENE_1:
CURRENT_DURATION = SCENE_1_DURATION;
NEXT_STATE = State::SCENE_2;
current_duration = SCENE_1_DURATION;
next_state = State::SCENE_2;
break;
case State::SCENE_2:
CURRENT_DURATION = SCENE_2_DURATION;
NEXT_STATE = State::SCENE_3;
current_duration = SCENE_2_DURATION;
next_state = State::SCENE_3;
break;
case State::SCENE_3:
CURRENT_DURATION = SCENE_3_DURATION;
NEXT_STATE = State::SCENE_4;
current_duration = SCENE_3_DURATION;
next_state = State::SCENE_4;
break;
case State::SCENE_4:
CURRENT_DURATION = SCENE_4_DURATION;
NEXT_STATE = State::ENDING;
current_duration = SCENE_4_DURATION;
next_state = State::ENDING;
break;
default:
return;
}
// Comprobar si ha pasado la duración de la escena
if (state_time_ >= CURRENT_DURATION) {
if (NEXT_STATE == State::ENDING) {
if (state_time_ >= current_duration) {
if (next_state == State::ENDING) {
// Termina el bucle
SceneManager::current = SceneManager::Scene::ENDING2;
} else {
// Transición a la siguiente escena
current_scene_++;
transitionToState(NEXT_STATE);
transitionToState(next_state);
}
}
}

View File

@@ -79,7 +79,7 @@ void Ending2::update() {
break;
}
Audio::get()->update(); // Actualiza el objeto Audio
Audio::update(); // Actualiza el objeto Audio
Screen::get()->update(DELTA_TIME); // Actualiza el objeto Screen
}

View File

@@ -148,7 +148,7 @@ void Game::update() {
keepMusicPlaying();
updateBlackScreen(DELTA_TIME);
Audio::get()->update(); // Actualiza el objeto Audio
Audio::update(); // Actualiza el objeto Audio
Screen::get()->update(DELTA_TIME); // Actualiza el objeto Screen
#ifdef _DEBUG

View File

@@ -56,7 +56,7 @@ void GameOver::update() {
player_sprite_->update(DELTA_TIME); // Actualiza el sprite
tv_sprite_->update(DELTA_TIME); // Actualiza el sprite
Audio::get()->update(); // Actualiza el objeto Audio
Audio::update(); // Actualiza el objeto Audio
Screen::get()->update(DELTA_TIME); // Actualiza el objeto Screen
}
@@ -123,9 +123,9 @@ void GameOver::updateColor() {
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))];
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;
}
@@ -137,9 +137,9 @@ void GameOver::updateColor() {
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))];
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;
}
@@ -165,7 +165,7 @@ void GameOver::updateState() {
// Espera inicial antes de empezar
if (elapsed_time_ >= WAITING_DURATION) {
state_ = State::FADE_IN;
elapsed_time_ = 0.0f;
elapsed_time_ = 0.0F;
// Hace sonar la música cuando termina la espera
Audio::get()->playMusic("game_over.ogg", 0);
}
@@ -175,7 +175,7 @@ void GameOver::updateState() {
// Fade in de colores desde black
if (elapsed_time_ >= FADE_IN_DURATION) {
state_ = State::DISPLAY;
elapsed_time_ = 0.0f;
elapsed_time_ = 0.0F;
}
break;
@@ -183,7 +183,7 @@ void GameOver::updateState() {
// Mostrando contenido con color brillante
if (elapsed_time_ >= DISPLAY_DURATION) {
state_ = State::FADE_OUT;
elapsed_time_ = 0.0f;
elapsed_time_ = 0.0F;
}
break;
@@ -191,7 +191,7 @@ void GameOver::updateState() {
// Fade out hacia black
if (elapsed_time_ >= FADE_OUT_DURATION) {
state_ = State::ENDING;
elapsed_time_ = 0.0f;
elapsed_time_ = 0.0F;
}
break;
@@ -199,7 +199,7 @@ void GameOver::updateState() {
// Pantalla en negro antes de salir
if (elapsed_time_ >= ENDING_DURATION) {
state_ = State::TRANSITION;
elapsed_time_ = 0.0f;
elapsed_time_ = 0.0F;
}
break;

View File

@@ -28,11 +28,11 @@ class GameOver {
};
// --- 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
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
@@ -51,7 +51,7 @@ class GameOver {
// --- Variables ---
State state_ = State::WAITING; // Estado actual de la escena
float elapsed_time_ = 0.0f; // Tiempo transcurrido en el estado actual
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

View File

@@ -277,7 +277,7 @@ void LoadingScreen::renderDataBorder() {
}
// Dibuja el efecto de carga rojo y azul en el borde
void LoadingScreen::renderHeaderBorder() {
void LoadingScreen::renderHeaderBorder() const {
// Obtiene la Surface del borde
auto border = Screen::get()->getBorderSurface();
@@ -441,10 +441,10 @@ void LoadingScreen::updateCarrier(float delta_time) {
constexpr float CARRIER_HEIGHT = HEADER_DATAROW_HEIGHT;
// Oscilación compuesta: mezcla de dos frecuencias para evitar patrón predecible
const float modulation = std::sin(carrier_.total_time * 1.2F) * std::sin(carrier_.total_time * 0.35F + 1.0F);
const float speed = CARRIER_BASE_SPEED * (0.5F + 0.5F * modulation); // rango [-200, 0]
const float MODULATION = std::sin(carrier_.total_time * 1.2F) * std::sin((carrier_.total_time * 0.35F) + 1.0F);
const float SPEED = CARRIER_BASE_SPEED * (0.5F + 0.5F * MODULATION); // rango [-200, 0]
carrier_.offset += speed * delta_time;
carrier_.offset += SPEED * delta_time;
if (carrier_.offset < 0.0F) {
carrier_.offset += CARRIER_HEIGHT; // reinicia al rango [0,HEADER_DATAROW_HEIGHT]
@@ -459,8 +459,8 @@ void LoadingScreen::updateSilent(float delta_time) {
constexpr float NOISE_THRESHOLD = 0.35F;
// Oscilación compuesta para simular picos de ruido
const float modulation = std::sin(noise_.total_time * 4.2F) * std::sin(noise_.total_time * 1.7F + 0.5F);
noise_.value = std::fabs(modulation); // rango [0.0, 1.0]
const float MODULATION = std::sin(noise_.total_time * 4.2F) * std::sin((noise_.total_time * 1.7F) + 0.5F);
noise_.value = std::fabs(MODULATION); // rango [0.0, 1.0]
// Detecta cruce de umbral solo si venía de abajo
if (noise_.value > NOISE_THRESHOLD && !noise_.crossed) {

View File

@@ -106,7 +106,7 @@ class LoadingScreen {
void updateColorLoad(float delta_time); // Gestiona la carga en color (time-based)
void renderBorder(); // Pinta el borde
static void renderDataBorder(); // Dibuja el efecto de carga amarillo y azul en el borde
void renderHeaderBorder(); // Dibuja el efecto de carga rojo y azul en el borde
void renderHeaderBorder() const; // Dibuja el efecto de carga rojo y azul en el borde
static void renderColoredBorder(PaletteColor color); // Dibuja el borde de color
void initLineIndexArray(); // Inicializa el array de índices de líneas
void printProgramName(); // Escribe el nombre del programa

View File

@@ -22,9 +22,7 @@ Logo::Logo()
: jailgames_surface_(Resource::get()->getSurface("jailgames.gif")),
since_1998_surface_(Resource::get()->getSurface("since_1998.gif")),
since_1998_sprite_(std::make_shared<SurfaceSprite>(since_1998_surface_, (256 - since_1998_surface_->getWidth()) / 2, 83 + jailgames_surface_->getHeight() + 5, since_1998_surface_->getWidth(), since_1998_surface_->getHeight())),
delta_timer_(std::make_unique<DeltaTimer>()),
state_(State::INITIAL),
state_time_(0.0F) {
delta_timer_(std::make_unique<DeltaTimer>()) {
// Configura variables
since_1998_sprite_->setClip(0, 0, since_1998_surface_->getWidth(), since_1998_surface_->getHeight());
since_1998_color_ = static_cast<Uint8>(PaletteColor::BLACK);
@@ -86,7 +84,7 @@ void Logo::updateJAILGAMES(float delta_time) {
}
// Verifica si todas las líneas están en su posición destino
bool Logo::allJailgamesLinesInPosition() const {
auto Logo::allJailgamesLinesInPosition() const -> bool {
// Iterar por todas las líneas (empezando desde 1, como en updateJAILGAMES)
for (size_t i = 1; i < jailgames_sprite_.size(); ++i) {
if (jailgames_sprite_[i]->getX() != JAILGAMES_DEST_X) {
@@ -200,7 +198,7 @@ void Logo::update() {
updateJAILGAMES(DELTA_TIME); // Gestiona el logo de JAILGAME
updateTextureColors(); // Gestiona el color de las texturas
Audio::get()->update(); // Actualiza el objeto Audio
Audio::update(); // Actualiza el objeto Audio
Screen::get()->update(DELTA_TIME); // Actualiza el objeto Screen
}

View File

@@ -63,7 +63,7 @@ class Logo {
void updateState(float delta_time); // Actualiza el estado actual
void transitionToState(State new_state); // Transiciona a un nuevo estado
[[nodiscard]] auto getColorIndex(float progress) const -> int; // Calcula el índice de color según el progreso (0.0-1.0)
[[nodiscard]] bool allJailgamesLinesInPosition() const; // Verifica si todas las líneas están en su posición destino
[[nodiscard]] auto allJailgamesLinesInPosition() const -> bool; // Verifica si todas las líneas están en su posición destino
static void endSection(); // Termina la sección
void initColors(); // Inicializa el vector de colores
void initSprites(); // Crea los sprites de cada linea

View File

@@ -91,53 +91,13 @@ void Title::handleEvents() {
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);
controls_menu_state_ = ControlsMenuState::MAIN;
break;
case SDLK_3:
transitionToState(State::CHEEVOS_MENU);
break;
default:
break;
}
handleMainMenuKeyPress(event.key.key);
break;
case State::CONTROLS_MENU:
if (controls_menu_state_ == ControlsMenuState::MAIN) {
// Menu principal de controles
switch (event.key.key) {
case SDLK_1:
// Iniciar redefinicion de teclado
controls_menu_state_ = ControlsMenuState::KEYBOARD_REMAP;
remap_step_ = 0;
remap_error_message_.clear();
break;
case SDLK_2:
// Redefinir joystick - solo si hay gamepads conectados
if (Input::get()->gameControllerFound()) {
controls_menu_state_ = ControlsMenuState::JOYSTICK_REMAP;
remap_step_ = 0;
remap_error_message_.clear();
axis_cooldown_ = 0.0F; // Resetear cooldown
}
break;
default:
break;
}
handleControlsMenuKeyPress(event.key.key);
} else if (controls_menu_state_ == ControlsMenuState::KEYBOARD_REMAP) {
// Captura de teclas para redefinir
handleControlsMenuKeyboardRemap(event);
}
break;
@@ -149,6 +109,54 @@ void Title::handleEvents() {
}
}
// Maneja las teclas del menu principal
void Title::handleMainMenuKeyPress(SDL_Keycode key) {
switch (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);
controls_menu_state_ = ControlsMenuState::MAIN;
break;
case SDLK_3:
transitionToState(State::CHEEVOS_MENU);
break;
default:
break;
}
}
// Maneja las teclas del menu de controles
void Title::handleControlsMenuKeyPress(SDL_Keycode key) {
switch (key) {
case SDLK_1:
// Iniciar redefinicion de teclado
controls_menu_state_ = ControlsMenuState::KEYBOARD_REMAP;
remap_step_ = 0;
remap_error_message_.clear();
break;
case SDLK_2:
// Redefinir joystick - solo si hay gamepads conectados
if (Input::get()->gameControllerFound()) {
controls_menu_state_ = ControlsMenuState::JOYSTICK_REMAP;
remap_step_ = 0;
remap_error_message_.clear();
axis_cooldown_ = 0.0F; // Resetear cooldown
}
break;
default:
break;
}
}
// Comprueba las entradas
void Title::handleInput(float delta_time) {
Input::get()->update();
@@ -247,7 +255,7 @@ void Title::update() {
updateState(DELTA_TIME); // Actualiza el estado actual
Audio::get()->update(); // Actualiza el objeto Audio
Audio::update(); // Actualiza el objeto Audio
Screen::get()->update(DELTA_TIME); // Actualiza el objeto Screen
}
@@ -343,9 +351,7 @@ void Title::updateControlsMenu(float delta_time) {
// Decrementar cooldown de ejes si estamos capturando botones
if (controls_menu_state_ == ControlsMenuState::JOYSTICK_REMAP && axis_cooldown_ > 0.0F) {
axis_cooldown_ -= delta_time;
if (axis_cooldown_ < 0.0F) {
axis_cooldown_ = 0.0F;
}
axis_cooldown_ = std::max(axis_cooldown_, 0.0F);
}
// Si estamos mostrando las teclas definidas, esperar antes de guardar
@@ -517,7 +523,7 @@ void Title::renderControlsMenu() {
controls_menu_state_ == ControlsMenuState::KEYBOARD_REMAP_COMPLETE) {
renderKeyboardRemap();
} else if (controls_menu_state_ == ControlsMenuState::JOYSTICK_REMAP ||
controls_menu_state_ == ControlsMenuState::JOYSTICK_REMAP_COMPLETE) {
controls_menu_state_ == ControlsMenuState::JOYSTICK_REMAP_COMPLETE) {
renderJoystickRemap();
} else {
// Menu principal de controles
@@ -527,9 +533,8 @@ void Title::renderControlsMenu() {
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 11 * TEXT_SIZE, "1. REDEFINE KEYBOARD", 1, COLOR);
// Deshabilitar opcion de joystick si no hay gamepads conectados
const bool gamepad_available = Input::get()->gameControllerFound();
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 13 * TEXT_SIZE,
"2. REDEFINE JOYSTICK", 1, gamepad_available ? COLOR : DISABLED_COLOR);
const bool GAMEPAD_AVAILABLE = Input::get()->gameControllerFound();
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 13 * TEXT_SIZE, "2. REDEFINE JOYSTICK", 1, GAMEPAD_AVAILABLE ? COLOR : DISABLED_COLOR);
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 17 * TEXT_SIZE, "ENTER TO GO BACK", 1, COLOR);
}
@@ -607,7 +612,7 @@ void Title::handleControlsMenuKeyboardRemap(const SDL_Event& event) {
}
// Valida si una tecla es permitida
bool Title::isKeyValid(SDL_Scancode scancode) {
auto Title::isKeyValid(SDL_Scancode scancode) -> bool {
// Prohibir ESC (reservado para cancelar)
if (scancode == SDL_SCANCODE_ESCAPE) {
return false;
@@ -627,7 +632,7 @@ bool Title::isKeyValid(SDL_Scancode scancode) {
}
// Verifica si una tecla ya fue usada en pasos anteriores
bool Title::isKeyDuplicate(SDL_Scancode scancode, int current_step) {
auto Title::isKeyDuplicate(SDL_Scancode scancode, int current_step) -> bool {
for (int i = 0; i < current_step; i++) {
if (temp_keys_[i] == scancode) {
return true;
@@ -637,7 +642,7 @@ bool Title::isKeyDuplicate(SDL_Scancode scancode, int current_step) {
}
// Retorna el nombre de la accion para el paso actual
std::string Title::getActionName(int step) {
auto Title::getActionName(int step) -> std::string {
switch (step) {
case 0:
return "LEFT";
@@ -671,7 +676,7 @@ void Title::renderKeyboardRemap() {
const int TEXT_SIZE = menu_text_->getCharacterSize();
// Titulo
//menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 9 * TEXT_SIZE, "REDEFINE KEYBOARD", 1, COLOR);
// menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 9 * TEXT_SIZE, "REDEFINE KEYBOARD", 1, COLOR);
// Mensaje principal: "PRESS KEY FOR [ACTION]" o "KEYS DEFINED" si completado
if (remap_step_ >= 3) {
@@ -764,7 +769,7 @@ void Title::handleControlsMenuJoystickRemap(const SDL_Event& event) {
// Capturar triggers como botones (usando valores especiales 100/101)
if (event.gaxis.axis == SDL_GAMEPAD_AXIS_LEFT_TRIGGER && event.gaxis.value > TRIGGER_THRESHOLD) {
captured_button = Input::TRIGGER_L2_AS_BUTTON; // 100
axis_cooldown_ = 0.5F; // Cooldown de medio segundo
axis_cooldown_ = 0.5F; // Cooldown de medio segundo
} else if (event.gaxis.axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER && event.gaxis.value > TRIGGER_THRESHOLD) {
captured_button = Input::TRIGGER_R2_AS_BUTTON; // 101
axis_cooldown_ = 0.5F;
@@ -805,7 +810,7 @@ void Title::handleControlsMenuJoystickRemap(const SDL_Event& event) {
}
// Valida si un botón está duplicado
bool Title::isButtonDuplicate(int button, int current_step) {
auto Title::isButtonDuplicate(int button, int current_step) -> bool {
for (int i = 0; i < current_step; ++i) {
if (temp_buttons_[i] == button) {
return true;
@@ -829,7 +834,7 @@ void Title::applyJoystickRemap() {
}
// Retorna el nombre amigable del botón del gamepad
std::string Title::getButtonName(int button) {
auto Title::getButtonName(int button) -> std::string {
// Triggers especiales
if (button == Input::TRIGGER_L2_AS_BUTTON) {
return "L2";
@@ -847,7 +852,7 @@ std::string Title::getButtonName(int button) {
}
// Botones estándar SDL
const auto sdl_button = static_cast<SDL_GamepadButton>(button);
const char* button_name = SDL_GetGamepadStringForButton(sdl_button);
return button_name ? std::string(button_name) : "UNKNOWN";
const auto GAMEPAD_BUTTON = static_cast<SDL_GamepadButton>(button);
const char* button_name = SDL_GetGamepadStringForButton(GAMEPAD_BUTTON);
return (button_name != nullptr) ? std::string(button_name) : "UNKNOWN";
}

View File

@@ -98,6 +98,8 @@ class Title {
void update(); // Actualiza las variables
void render(); // Dibuja en pantalla
void handleEvents(); // Comprueba el manejador de eventos
void handleMainMenuKeyPress(SDL_Keycode key); // Maneja las teclas del menu principal
void handleControlsMenuKeyPress(SDL_Keycode key); // Maneja las teclas del menu de controles
void handleInput(float delta_time); // Comprueba las entradas
void updateState(float delta_time); // Actualiza el estado actual
void transitionToState(State new_state); // Transiciona a un nuevo estado
@@ -120,13 +122,13 @@ class Title {
void moveCheevosList(int direction, float delta_time); // Desplaza la lista de logros (time-based)
void handleControlsMenuKeyboardRemap(const SDL_Event& event); // Maneja la captura de teclas
void handleControlsMenuJoystickRemap(const SDL_Event& event); // Maneja la captura de botones del gamepad
bool isKeyValid(SDL_Scancode scancode); // Valida si una tecla es permitida
bool isKeyDuplicate(SDL_Scancode scancode, int current_step); // Valida si una tecla esta duplicada
bool isButtonDuplicate(int button, int current_step); // Valida si un boton esta duplicado
static auto isKeyValid(SDL_Scancode scancode) -> bool; // Valida si una tecla es permitida
auto isKeyDuplicate(SDL_Scancode scancode, int current_step) -> bool; // Valida si una tecla esta duplicada
auto isButtonDuplicate(int button, int current_step) -> bool; // Valida si un boton esta duplicado
void applyKeyboardRemap(); // Aplica y guarda las teclas redefinidas
void applyJoystickRemap(); // Aplica y guarda los botones del gamepad redefinidos
std::string getActionName(int step); // Retorna el nombre de la accion (LEFT/RIGHT/JUMP)
std::string getButtonName(int button); // Retorna el nombre amigable del boton del gamepad
void applyJoystickRemap(); // Aplica y guarda los botones del gamepad redestatic finidos
static auto getActionName(int step) -> std::string; // Retorna el nombre de la accion (LEFT/RIGHstatic T/JUMP)
static auto getButtonName(int button) -> std::string; // Retorna el nombre amigable del boton del gamepad
void createCheevosTexture(); // Crea y rellena la surface para mostrar los logros
void resetCheevosScroll(); // Resetea el scroll de la lista de logros
void fillTitleSurface(); // Dibuja los elementos en la surface