|
|
|
|
@@ -33,8 +33,8 @@
|
|
|
|
|
|
|
|
|
|
// Constructor
|
|
|
|
|
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_(std::make_shared<Scoreboard>(board_)),
|
|
|
|
|
: 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>(scoreboard_data_)),
|
|
|
|
|
room_tracker_(std::make_shared<RoomTracker>()),
|
|
|
|
|
stats_(std::make_shared<Stats>(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<Room>(current_room_, board_);
|
|
|
|
|
room_ = std::make_shared<Room>(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<Room>(current_room_, board_);
|
|
|
|
|
room_ = std::make_shared<Room>(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<Options::Cheat::State>(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>(room_path, board_);
|
|
|
|
|
room_ = std::make_shared<Room>(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<Uint8>(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<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
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|