diff --git a/source/game/entities/player.cpp b/source/game/entities/player.cpp index f09f895..52dc282 100644 --- a/source/game/entities/player.cpp +++ b/source/game/entities/player.cpp @@ -599,8 +599,13 @@ auto Player::handleKillingTiles() -> bool { return false; // No se encontró ninguna colisión } -// Establece el color del jugador -void Player::setColor() { +// Establece el color del jugador (0 = automático según cheats) +void Player::setColor(Uint8 color) { + if (color != 0) { + color_ = color; + return; + } + if (Options::cheats.invincible == Options::Cheat::State::ENABLED) { color_ = static_cast(PaletteColor::CYAN); } else if (Options::cheats.infinite_lives == Options::Cheat::State::ENABLED) { diff --git a/source/game/entities/player.hpp b/source/game/entities/player.hpp index 35dcd7a..407e2a3 100644 --- a/source/game/entities/player.hpp +++ b/source/game/entities/player.hpp @@ -99,7 +99,7 @@ class Player { 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 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_ = 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_; } // Comprueba si el jugador esta vivo diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index b8369a6..45496d3 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -33,8 +33,8 @@ // Constructor Game::Game(Mode mode) - : board_(std::make_shared(0, 9, 0, true, 0, SDL_GetTicks(), Options::cheats.jail_is_open == Options::Cheat::State::ENABLED)), - scoreboard_(std::make_shared(board_)), + : scoreboard_data_(std::make_shared(0, 9, 0, true, 0, SDL_GetTicks(), Options::cheats.jail_is_open == Options::Cheat::State::ENABLED)), + scoreboard_(std::make_shared(scoreboard_data_)), room_tracker_(std::make_shared()), stats_(std::make_shared(Resource::List::get()->get("stats.csv"), Resource::List::get()->get("stats_buffer.csv"))), mode_(mode), @@ -49,7 +49,7 @@ Game::Game(Mode mode) // Crea objetos e inicializa variables ItemTracker::init(); demoInit(); - room_ = std::make_shared(current_room_, board_); + room_ = std::make_shared(current_room_, scoreboard_data_); initPlayer(spawn_data_, room_); initStats(); total_items_ = getTotalItems(); @@ -86,9 +86,9 @@ void Game::handleInput() { // Inputs globales siempre funcionan if (Input::get()->checkAction(InputAction::TOGGLE_MUSIC, Input::DO_NOT_ALLOW_REPEAT)) { - board_->music = !board_->music; - board_->music ? Audio::get()->resumeMusic() : Audio::get()->pauseMusic(); - Notifier::get()->show({"MUSIC " + std::string(board_->music ? "ENABLED" : "DISABLED")}); + scoreboard_data_->music = !scoreboard_data_->music; + scoreboard_data_->music ? Audio::get()->resumeMusic() : Audio::get()->pauseMusic(); + Notifier::get()->show({"MUSIC " + std::string(scoreboard_data_->music ? "ENABLED" : "DISABLED")}); } // Durante fade/postfade, solo procesar inputs globales @@ -109,7 +109,7 @@ void Game::handleInput() { // Bucle para el juego void Game::run() { keepMusicPlaying(); - if (!board_->music && mode_ == Mode::GAME) { + if (!scoreboard_data_->music && mode_ == Mode::GAME) { Audio::get()->pauseMusic(); } @@ -200,7 +200,7 @@ void Game::updateBlackScreen(float delta_time) { state_time_ += delta_time; // 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); return; } @@ -263,7 +263,7 @@ void Game::transitionToState(State new_state) { // Lógica de ENTRADA según el nuevo estado if (new_state == State::BLACK_SCREEN) { // Respawn room y player - room_ = std::make_shared(current_room_, board_); + room_ = std::make_shared(current_room_, scoreboard_data_); initPlayer(spawn_data_, room_); // Pausar ambos 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 Options::cheats.invincible = static_cast(Debug::get()->isEnabled()); player_->setColor(); - board_->music = !Debug::get()->isEnabled(); - board_->music ? Audio::get()->resumeMusic() : Audio::get()->pauseMusic(); + scoreboard_data_->music = !Debug::get()->isEnabled(); + scoreboard_data_->music ? Audio::get()->resumeMusic() : Audio::get()->pauseMusic(); break; case SDLK_R: @@ -441,6 +441,23 @@ void Game::handleDebugEvents(const SDL_Event& event) { changeRoom(room_->getRoom(Room::Border::RIGHT)); 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: Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", "I LIKE MY MULTICOLOURED FRIENDS"}, Notifier::Style::CHEEVO, -1, false, "F7"); break; @@ -541,7 +558,7 @@ auto Game::changeRoom(const std::string& room_path) -> bool { // Verifica que exista el fichero que se va a cargar if (!Resource::List::get()->get(room_path).empty()) { // Crea un objeto habitación nuevo a partir del fichero - room_ = std::make_shared(room_path, board_); + room_ = std::make_shared(room_path, scoreboard_data_); // Pone el nombre de la habitación en la textura fillRoomNameTexture(); @@ -551,8 +568,8 @@ auto Game::changeRoom(const std::string& room_path) -> bool { if (room_tracker_->addRoom(room_path)) { // Incrementa el contador de habitaciones visitadas - board_->rooms++; - Options::stats.rooms = board_->rooms; + scoreboard_data_->rooms++; + Options::stats.rooms = scoreboard_data_->rooms; // Actualiza las estadisticas stats_->addVisit(room_->getName()); @@ -620,7 +637,7 @@ void Game::killPlayer() { // Resta una vida al jugador if (Options::cheats.infinite_lives == Options::Cheat::State::DISABLED) { - --board_->lives; + --scoreboard_data_->lives; } // Actualiza las estadisticas @@ -645,18 +662,16 @@ void Game::setScoreBoardColor() { const bool IS_BRIGHT_BLACK = BORDER_COLOR == static_cast(PaletteColor::BRIGHT_BLACK); // 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(PaletteColor::WHITE) : BORDER_COLOR; + scoreboard_data_->color = IS_BLACK || IS_BRIGHT_BLACK ? static_cast(PaletteColor::WHITE) : BORDER_COLOR; } // Comprueba si ha finalizado el juego auto Game::checkEndGame() -> bool { - 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 IS_ON_THE_DOOR = player_->getRect().x <= 128; // Y en la ubicación que toca (En la puerta) + const bool IS_ON_THE_ROOM = room_->getName() == "THE JAIL"; // Estar en la habitación que toca + 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) - if (HAVE_THE_ITEMS) { - board_->jail_is_open = true; - } + scoreboard_data_->jail_is_open = HAVE_THE_ITEMS; if (HAVE_THE_ITEMS && IS_ON_THE_ROOM && IS_ON_THE_DOOR) { // Comprueba los logros de completar el juego @@ -694,7 +709,7 @@ void Game::togglePause() { // Da vidas al jugador cuando está en la Jail 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 return; } @@ -706,11 +721,11 @@ void Game::checkRestoringJail(float delta_time) { // Incrementa el numero de vidas if (jail_restore_time_ >= JAIL_RESTORE_INTERVAL) { 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); // 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) { Cheevos::get()->setUnobtainable(9); } @@ -750,31 +765,31 @@ void Game::checkSomeCheevos() { auto* cheevos = Cheevos::get(); // Logros sobre la cantidad de items - if (board_->items == total_items_) { + if (scoreboard_data_->items == total_items_) { cheevos->unlock(4); cheevos->unlock(3); cheevos->unlock(2); 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(2); 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(1); - } else if (board_->items >= total_items_ * 0.25F) { + } else if (scoreboard_data_->items >= total_items_ * 0.25F) { cheevos->unlock(1); } // Logros sobre las habitaciones visitadas - if (board_->rooms >= 60) { + if (scoreboard_data_->rooms >= 60) { cheevos->unlock(7); cheevos->unlock(6); cheevos->unlock(5); - } else if (board_->rooms >= 40) { + } else if (scoreboard_data_->rooms >= 40) { cheevos->unlock(6); cheevos->unlock(5); - } else if (board_->rooms >= 20) { + } else if (scoreboard_data_->rooms >= 20) { cheevos->unlock(5); } } @@ -790,7 +805,7 @@ void Game::checkEndGameCheevos() { cheevos->unlock(9); // "Complete the game with all items" - if (board_->items == total_items_) { + if (scoreboard_data_->items == total_items_) { cheevos->unlock(10); } diff --git a/source/game/scenes/game.hpp b/source/game/scenes/game.hpp index b1f9658..739d550 100644 --- a/source/game/scenes/game.hpp +++ b/source/game/scenes/game.hpp @@ -100,14 +100,14 @@ class Game { // --- Variables miembro --- // Objetos y punteros a recursos - std::shared_ptr board_; // Estructura con los datos del marcador - std::shared_ptr scoreboard_; // Objeto encargado de gestionar el marcador - std::shared_ptr room_tracker_; // Lleva el control de las habitaciones visitadas - std::shared_ptr room_; // Objeto encargado de gestionar cada habitación del juego - std::shared_ptr player_; // Objeto con el jugador - std::shared_ptr stats_; // Objeto encargado de gestionar las estadísticas - std::shared_ptr room_name_surface_; // Textura para escribir el nombre de la habitación - std::shared_ptr game_backbuffer_surface_; // Backbuffer para efectos de fade + std::shared_ptr scoreboard_data_; // Estructura con los datos del marcador + std::shared_ptr scoreboard_; // Objeto encargado de gestionar el marcador + std::shared_ptr room_tracker_; // Lleva el control de las habitaciones visitadas + std::shared_ptr room_; // Objeto encargado de gestionar cada habitación del juego + std::shared_ptr player_; // Objeto con el jugador + std::shared_ptr stats_; // Objeto encargado de gestionar las estadísticas + std::shared_ptr room_name_surface_; // Textura para escribir el nombre de la habitación + std::shared_ptr game_backbuffer_surface_; // Backbuffer para efectos de fade // Variables de estado del juego Mode mode_; // Modo del juego