es poden activar els trucos en calent

This commit is contained in:
2025-11-22 10:27:14 +01:00
parent 9ef7f4274d
commit fda8ff3f65
4 changed files with 64 additions and 44 deletions

View File

@@ -599,8 +599,13 @@ auto Player::handleKillingTiles() -> bool {
return false; // No se encontró ninguna colisión return false; // No se encontró ninguna colisión
} }
// Establece el color del jugador // Establece el color del jugador (0 = automático según cheats)
void Player::setColor() { void Player::setColor(Uint8 color) {
if (color != 0) {
color_ = color;
return;
}
if (Options::cheats.invincible == Options::Cheat::State::ENABLED) { if (Options::cheats.invincible == Options::Cheat::State::ENABLED) {
color_ = static_cast<Uint8>(PaletteColor::CYAN); color_ = static_cast<Uint8>(PaletteColor::CYAN);
} else if (Options::cheats.infinite_lives == Options::Cheat::State::ENABLED) { } else if (Options::cheats.infinite_lives == Options::Cheat::State::ENABLED) {

View File

@@ -99,7 +99,7 @@ class Player {
auto getRect() -> SDL_FRect { return {x_, y_, WIDTH, HEIGHT}; } // Obtiene el rectangulo que delimita al jugador auto getRect() -> SDL_FRect { return {x_, y_, WIDTH, HEIGHT}; } // Obtiene el rectangulo que delimita al jugador
auto getCollider() -> SDL_FRect& { return collider_box_; } // Obtiene el rectangulo de colision del jugador auto getCollider() -> SDL_FRect& { return collider_box_; } // Obtiene el rectangulo de colision del jugador
auto getSpawnParams() -> SpawnData { return {.x = x_, .y = y_, .vx = vx_, .vy = vy_, .last_grounded_position = last_grounded_position_, .state = state_, .flip = sprite_->getFlip()}; } // Obtiene el estado de reaparición del jugador auto getSpawnParams() -> SpawnData { return {.x = x_, .y = y_, .vx = vx_, .vy = vy_, .last_grounded_position = last_grounded_position_, .state = state_, .flip = sprite_->getFlip()}; } // Obtiene el estado de reaparición del jugador
void setColor(); // Establece el color del jugador void setColor(Uint8 color = 0); // Establece el color del jugador (0 = automático según cheats)
void setRoom(std::shared_ptr<Room> room) { room_ = std::move(room); } // Establece la habitación en la que se encuentra el jugador void setRoom(std::shared_ptr<Room> room) { room_ = std::move(room); } // Establece la habitación en la que se encuentra el jugador
//[[nodiscard]] auto isAlive() const -> bool { return is_alive_ || (Options::cheats.invincible == Options::Cheat::State::ENABLED); } // Comprueba si el jugador esta vivo //[[nodiscard]] auto isAlive() const -> bool { return is_alive_ || (Options::cheats.invincible == Options::Cheat::State::ENABLED); } // Comprueba si el jugador esta vivo
[[nodiscard]] auto isAlive() const -> bool { return is_alive_; } // Comprueba si el jugador esta vivo [[nodiscard]] auto isAlive() const -> bool { return is_alive_; } // Comprueba si el jugador esta vivo

View File

@@ -33,8 +33,8 @@
// Constructor // Constructor
Game::Game(Mode mode) Game::Game(Mode mode)
: board_(std::make_shared<Scoreboard::Data>(0, 9, 0, true, 0, SDL_GetTicks(), Options::cheats.jail_is_open == Options::Cheat::State::ENABLED)), : scoreboard_data_(std::make_shared<Scoreboard::Data>(0, 9, 0, true, 0, SDL_GetTicks(), Options::cheats.jail_is_open == Options::Cheat::State::ENABLED)),
scoreboard_(std::make_shared<Scoreboard>(board_)), scoreboard_(std::make_shared<Scoreboard>(scoreboard_data_)),
room_tracker_(std::make_shared<RoomTracker>()), room_tracker_(std::make_shared<RoomTracker>()),
stats_(std::make_shared<Stats>(Resource::List::get()->get("stats.csv"), Resource::List::get()->get("stats_buffer.csv"))), stats_(std::make_shared<Stats>(Resource::List::get()->get("stats.csv"), Resource::List::get()->get("stats_buffer.csv"))),
mode_(mode), mode_(mode),
@@ -49,7 +49,7 @@ Game::Game(Mode mode)
// Crea objetos e inicializa variables // Crea objetos e inicializa variables
ItemTracker::init(); ItemTracker::init();
demoInit(); demoInit();
room_ = std::make_shared<Room>(current_room_, board_); room_ = std::make_shared<Room>(current_room_, scoreboard_data_);
initPlayer(spawn_data_, room_); initPlayer(spawn_data_, room_);
initStats(); initStats();
total_items_ = getTotalItems(); total_items_ = getTotalItems();
@@ -86,9 +86,9 @@ void Game::handleInput() {
// Inputs globales siempre funcionan // Inputs globales siempre funcionan
if (Input::get()->checkAction(InputAction::TOGGLE_MUSIC, Input::DO_NOT_ALLOW_REPEAT)) { if (Input::get()->checkAction(InputAction::TOGGLE_MUSIC, Input::DO_NOT_ALLOW_REPEAT)) {
board_->music = !board_->music; scoreboard_data_->music = !scoreboard_data_->music;
board_->music ? Audio::get()->resumeMusic() : Audio::get()->pauseMusic(); scoreboard_data_->music ? Audio::get()->resumeMusic() : Audio::get()->pauseMusic();
Notifier::get()->show({"MUSIC " + std::string(board_->music ? "ENABLED" : "DISABLED")}); Notifier::get()->show({"MUSIC " + std::string(scoreboard_data_->music ? "ENABLED" : "DISABLED")});
} }
// Durante fade/postfade, solo procesar inputs globales // Durante fade/postfade, solo procesar inputs globales
@@ -109,7 +109,7 @@ void Game::handleInput() {
// Bucle para el juego // Bucle para el juego
void Game::run() { void Game::run() {
keepMusicPlaying(); keepMusicPlaying();
if (!board_->music && mode_ == Mode::GAME) { if (!scoreboard_data_->music && mode_ == Mode::GAME) {
Audio::get()->pauseMusic(); Audio::get()->pauseMusic();
} }
@@ -200,7 +200,7 @@ void Game::updateBlackScreen(float delta_time) {
state_time_ += delta_time; state_time_ += delta_time;
// Si se acabaron las vidas Y pasó el threshold → GAME_OVER // Si se acabaron las vidas Y pasó el threshold → GAME_OVER
if (board_->lives < 0 && state_time_ > GAME_OVER_THRESHOLD) { if (scoreboard_data_->lives < 0 && state_time_ > GAME_OVER_THRESHOLD) {
transitionToState(State::GAME_OVER); transitionToState(State::GAME_OVER);
return; return;
} }
@@ -263,7 +263,7 @@ void Game::transitionToState(State new_state) {
// Lógica de ENTRADA según el nuevo estado // Lógica de ENTRADA según el nuevo estado
if (new_state == State::BLACK_SCREEN) { if (new_state == State::BLACK_SCREEN) {
// Respawn room y player // Respawn room y player
room_ = std::make_shared<Room>(current_room_, board_); room_ = std::make_shared<Room>(current_room_, scoreboard_data_);
initPlayer(spawn_data_, room_); initPlayer(spawn_data_, room_);
// Pausar ambos // Pausar ambos
room_->setPaused(true); room_->setPaused(true);
@@ -417,8 +417,8 @@ void Game::handleDebugEvents(const SDL_Event& event) {
room_->redrawMap(); // Redibuja el tilemap para mostrar/ocultar líneas de colisión room_->redrawMap(); // Redibuja el tilemap para mostrar/ocultar líneas de colisión
Options::cheats.invincible = static_cast<Options::Cheat::State>(Debug::get()->isEnabled()); Options::cheats.invincible = static_cast<Options::Cheat::State>(Debug::get()->isEnabled());
player_->setColor(); player_->setColor();
board_->music = !Debug::get()->isEnabled(); scoreboard_data_->music = !Debug::get()->isEnabled();
board_->music ? Audio::get()->resumeMusic() : Audio::get()->pauseMusic(); scoreboard_data_->music ? Audio::get()->resumeMusic() : Audio::get()->pauseMusic();
break; break;
case SDLK_R: case SDLK_R:
@@ -441,6 +441,23 @@ void Game::handleDebugEvents(const SDL_Event& event) {
changeRoom(room_->getRoom(Room::Border::RIGHT)); changeRoom(room_->getRoom(Room::Border::RIGHT));
break; break;
case SDLK_1:
Options::cheats.infinite_lives = Options::cheats.infinite_lives == Options::Cheat::State::ENABLED ? Options::Cheat::State::DISABLED : Options::Cheat::State::ENABLED;
Notifier::get()->show({std::string("INFINITE LIVES ") + (Options::cheats.infinite_lives == Options::Cheat::State::ENABLED ? "ENABLED" : "DISABLED")}, Notifier::Style::DEFAULT, -1, true);
player_->setColor();
break;
case SDLK_2:
Options::cheats.invincible = Options::cheats.invincible == Options::Cheat::State::ENABLED ? Options::Cheat::State::DISABLED : Options::Cheat::State::ENABLED;
Notifier::get()->show({std::string("INVINCIBLE ") + (Options::cheats.invincible == Options::Cheat::State::ENABLED ? "ENABLED" : "DISABLED")}, Notifier::Style::DEFAULT, -1, true);
player_->setColor();
break;
case SDLK_3:
Options::cheats.jail_is_open = Options::cheats.jail_is_open == Options::Cheat::State::ENABLED ? Options::Cheat::State::DISABLED : Options::Cheat::State::ENABLED;
Notifier::get()->show({std::string("JAIL IS OPEN ") + (Options::cheats.jail_is_open == Options::Cheat::State::ENABLED ? "ENABLED" : "DISABLED")}, Notifier::Style::DEFAULT, -1, true);
break;
case SDLK_7: case SDLK_7:
Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", "I LIKE MY MULTICOLOURED FRIENDS"}, Notifier::Style::CHEEVO, -1, false, "F7"); Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", "I LIKE MY MULTICOLOURED FRIENDS"}, Notifier::Style::CHEEVO, -1, false, "F7");
break; break;
@@ -541,7 +558,7 @@ auto Game::changeRoom(const std::string& room_path) -> bool {
// Verifica que exista el fichero que se va a cargar // Verifica que exista el fichero que se va a cargar
if (!Resource::List::get()->get(room_path).empty()) { if (!Resource::List::get()->get(room_path).empty()) {
// Crea un objeto habitación nuevo a partir del fichero // Crea un objeto habitación nuevo a partir del fichero
room_ = std::make_shared<Room>(room_path, board_); room_ = std::make_shared<Room>(room_path, scoreboard_data_);
// Pone el nombre de la habitación en la textura // Pone el nombre de la habitación en la textura
fillRoomNameTexture(); fillRoomNameTexture();
@@ -551,8 +568,8 @@ auto Game::changeRoom(const std::string& room_path) -> bool {
if (room_tracker_->addRoom(room_path)) { if (room_tracker_->addRoom(room_path)) {
// Incrementa el contador de habitaciones visitadas // Incrementa el contador de habitaciones visitadas
board_->rooms++; scoreboard_data_->rooms++;
Options::stats.rooms = board_->rooms; Options::stats.rooms = scoreboard_data_->rooms;
// Actualiza las estadisticas // Actualiza las estadisticas
stats_->addVisit(room_->getName()); stats_->addVisit(room_->getName());
@@ -620,7 +637,7 @@ void Game::killPlayer() {
// Resta una vida al jugador // Resta una vida al jugador
if (Options::cheats.infinite_lives == Options::Cheat::State::DISABLED) { if (Options::cheats.infinite_lives == Options::Cheat::State::DISABLED) {
--board_->lives; --scoreboard_data_->lives;
} }
// Actualiza las estadisticas // Actualiza las estadisticas
@@ -645,18 +662,16 @@ void Game::setScoreBoardColor() {
const bool IS_BRIGHT_BLACK = BORDER_COLOR == static_cast<Uint8>(PaletteColor::BRIGHT_BLACK); const bool IS_BRIGHT_BLACK = BORDER_COLOR == static_cast<Uint8>(PaletteColor::BRIGHT_BLACK);
// Si el color del borde es negro o negro brillante cambia el texto del marcador a blanco // Si el color del borde es negro o negro brillante cambia el texto del marcador a blanco
board_->color = IS_BLACK || IS_BRIGHT_BLACK ? static_cast<Uint8>(PaletteColor::WHITE) : BORDER_COLOR; scoreboard_data_->color = IS_BLACK || IS_BRIGHT_BLACK ? static_cast<Uint8>(PaletteColor::WHITE) : BORDER_COLOR;
} }
// Comprueba si ha finalizado el juego // Comprueba si ha finalizado el juego
auto Game::checkEndGame() -> bool { auto Game::checkEndGame() -> bool {
const bool IS_ON_THE_ROOM = room_->getName() == "THE JAIL"; // Estar en la habitación que toca const bool IS_ON_THE_ROOM = room_->getName() == "THE JAIL"; // Estar en la habitación que toca
const bool HAVE_THE_ITEMS = board_->items >= int(total_items_ * 0.9F) || Options::cheats.jail_is_open == Options::Cheat::State::ENABLED; // Con mas del 90% de los items recogidos const bool HAVE_THE_ITEMS = scoreboard_data_->items >= int(total_items_ * 0.9F) || Options::cheats.jail_is_open == Options::Cheat::State::ENABLED; // Con mas del 90% de los items recogidos
const bool IS_ON_THE_DOOR = player_->getRect().x <= 128; // Y en la ubicación que toca (En la puerta) const bool IS_ON_THE_DOOR = player_->getRect().x <= 128; // Y en la ubicación que toca (En la puerta)
if (HAVE_THE_ITEMS) { scoreboard_data_->jail_is_open = HAVE_THE_ITEMS;
board_->jail_is_open = true;
}
if (HAVE_THE_ITEMS && IS_ON_THE_ROOM && IS_ON_THE_DOOR) { if (HAVE_THE_ITEMS && IS_ON_THE_ROOM && IS_ON_THE_DOOR) {
// Comprueba los logros de completar el juego // Comprueba los logros de completar el juego
@@ -694,7 +709,7 @@ void Game::togglePause() {
// Da vidas al jugador cuando está en la Jail // Da vidas al jugador cuando está en la Jail
void Game::checkRestoringJail(float delta_time) { void Game::checkRestoringJail(float delta_time) {
if (room_->getName() != "THE JAIL" || board_->lives == 9) { if (room_->getName() != "THE JAIL" || scoreboard_data_->lives == 9) {
jail_restore_time_ = 0.0F; // Reset timer cuando no está en la Jail jail_restore_time_ = 0.0F; // Reset timer cuando no está en la Jail
return; return;
} }
@@ -706,11 +721,11 @@ void Game::checkRestoringJail(float delta_time) {
// Incrementa el numero de vidas // Incrementa el numero de vidas
if (jail_restore_time_ >= JAIL_RESTORE_INTERVAL) { if (jail_restore_time_ >= JAIL_RESTORE_INTERVAL) {
jail_restore_time_ -= JAIL_RESTORE_INTERVAL; // Mantiene el excedente para precisión jail_restore_time_ -= JAIL_RESTORE_INTERVAL; // Mantiene el excedente para precisión
board_->lives++; scoreboard_data_->lives++;
Audio::get()->playSound("death.wav", Audio::Group::GAME); Audio::get()->playSound("death.wav", Audio::Group::GAME);
// Invalida el logro de completar el juego sin entrar a la jail // Invalida el logro de completar el juego sin entrar a la jail
const bool HAVE_THE_ITEMS = board_->items >= int(total_items_ * 0.9F); const bool HAVE_THE_ITEMS = scoreboard_data_->items >= int(total_items_ * 0.9F);
if (!HAVE_THE_ITEMS) { if (!HAVE_THE_ITEMS) {
Cheevos::get()->setUnobtainable(9); Cheevos::get()->setUnobtainable(9);
} }
@@ -750,31 +765,31 @@ void Game::checkSomeCheevos() {
auto* cheevos = Cheevos::get(); auto* cheevos = Cheevos::get();
// Logros sobre la cantidad de items // Logros sobre la cantidad de items
if (board_->items == total_items_) { if (scoreboard_data_->items == total_items_) {
cheevos->unlock(4); cheevos->unlock(4);
cheevos->unlock(3); cheevos->unlock(3);
cheevos->unlock(2); cheevos->unlock(2);
cheevos->unlock(1); cheevos->unlock(1);
} else if (board_->items >= total_items_ * 0.75F) { } else if (scoreboard_data_->items >= total_items_ * 0.75F) {
cheevos->unlock(3); cheevos->unlock(3);
cheevos->unlock(2); cheevos->unlock(2);
cheevos->unlock(1); cheevos->unlock(1);
} else if (board_->items >= total_items_ * 0.5F) { } else if (scoreboard_data_->items >= total_items_ * 0.5F) {
cheevos->unlock(2); cheevos->unlock(2);
cheevos->unlock(1); cheevos->unlock(1);
} else if (board_->items >= total_items_ * 0.25F) { } else if (scoreboard_data_->items >= total_items_ * 0.25F) {
cheevos->unlock(1); cheevos->unlock(1);
} }
// Logros sobre las habitaciones visitadas // Logros sobre las habitaciones visitadas
if (board_->rooms >= 60) { if (scoreboard_data_->rooms >= 60) {
cheevos->unlock(7); cheevos->unlock(7);
cheevos->unlock(6); cheevos->unlock(6);
cheevos->unlock(5); cheevos->unlock(5);
} else if (board_->rooms >= 40) { } else if (scoreboard_data_->rooms >= 40) {
cheevos->unlock(6); cheevos->unlock(6);
cheevos->unlock(5); cheevos->unlock(5);
} else if (board_->rooms >= 20) { } else if (scoreboard_data_->rooms >= 20) {
cheevos->unlock(5); cheevos->unlock(5);
} }
} }
@@ -790,7 +805,7 @@ void Game::checkEndGameCheevos() {
cheevos->unlock(9); cheevos->unlock(9);
// "Complete the game with all items" // "Complete the game with all items"
if (board_->items == total_items_) { if (scoreboard_data_->items == total_items_) {
cheevos->unlock(10); cheevos->unlock(10);
} }

View File

@@ -100,14 +100,14 @@ class Game {
// --- Variables miembro --- // --- Variables miembro ---
// Objetos y punteros a recursos // Objetos y punteros a recursos
std::shared_ptr<Scoreboard::Data> board_; // Estructura con los datos del marcador std::shared_ptr<Scoreboard::Data> scoreboard_data_; // Estructura con los datos del marcador
std::shared_ptr<Scoreboard> scoreboard_; // Objeto encargado de gestionar el marcador std::shared_ptr<Scoreboard> scoreboard_; // Objeto encargado de gestionar el marcador
std::shared_ptr<RoomTracker> room_tracker_; // Lleva el control de las habitaciones visitadas std::shared_ptr<RoomTracker> room_tracker_; // Lleva el control de las habitaciones visitadas
std::shared_ptr<Room> room_; // Objeto encargado de gestionar cada habitación del juego std::shared_ptr<Room> room_; // Objeto encargado de gestionar cada habitación del juego
std::shared_ptr<Player> player_; // Objeto con el jugador std::shared_ptr<Player> player_; // Objeto con el jugador
std::shared_ptr<Stats> stats_; // Objeto encargado de gestionar las estadísticas std::shared_ptr<Stats> stats_; // Objeto encargado de gestionar las estadísticas
std::shared_ptr<Surface> room_name_surface_; // Textura para escribir el nombre de la habitación std::shared_ptr<Surface> room_name_surface_; // Textura para escribir el nombre de la habitación
std::shared_ptr<Surface> game_backbuffer_surface_; // Backbuffer para efectos de fade std::shared_ptr<Surface> game_backbuffer_surface_; // Backbuffer para efectos de fade
// Variables de estado del juego // Variables de estado del juego
Mode mode_; // Modo del juego Mode mode_; // Modo del juego