diff --git a/data/enemies/upv_student.gif b/data/enemies/upv_student.gif index a44675c..2766d3f 100644 Binary files a/data/enemies/upv_student.gif and b/data/enemies/upv_student.gif differ diff --git a/data/room/03.yaml b/data/room/03.yaml index 4d2fcf0..ba6b4e1 100644 --- a/data/room/03.yaml +++ b/data/room/03.yaml @@ -72,7 +72,7 @@ enemies: velocity: {x: 24, y: 0} boundaries: position1: {x: 3, y: 2} - position2: {x: 11, y: 2} + position2: {x: 19, y: 2} color: 12 # Objetos en esta habitación diff --git a/source/game/editor/map_editor.cpp b/source/game/editor/map_editor.cpp index f3d86dd..007063c 100644 --- a/source/game/editor/map_editor.cpp +++ b/source/game/editor/map_editor.cpp @@ -289,8 +289,6 @@ auto MapEditor::revert() -> std::string { } room_->setItemColors(room_data_.item_color1, room_data_.item_color2); - // Refrescar visuales de la habitación - room_->setBgColor(room_data_.bg_color); // Restaurar el tilemap completo for (int i = 0; i < static_cast(room_data_.tile_map.size()); ++i) { room_->setTile(i, room_data_.tile_map[i]); @@ -521,7 +519,7 @@ void MapEditor::handleEvent(const SDL_Event& event) { // NOLINT(readability-fun tile_picker_.on_select = [this](int tile) { brush_tile_ = tile; }; - tile_picker_.open(room_->getTileSetFile(), current, room_data_.bg_color); + tile_picker_.open(room_->getTileSetFile(), current, 0); } return; } @@ -991,7 +989,7 @@ void MapEditor::updateStatusBarInfo() { // NOLINT(readability-function-cognitiv conv = "right"; } - line2 = "bg:" + std::to_string(room_data_.bg_color) + " conv:" + conv; + line2 = "conv:" + conv; line3 = "u:" + conn(room_data_.upper_room) + " d:" + conn(room_data_.lower_room) + " l:" + conn(room_data_.left_room) + " r:" + conn(room_data_.right_room) + " itm:" + std::to_string(room_data_.item_color1) + "/" + std::to_string(room_data_.item_color2); @@ -1223,14 +1221,6 @@ auto MapEditor::setRoomProperty(const std::string& property, const std::string& std::string val = toLower(value); - if (property == "BGCOLOR") { - auto color = static_cast(safeStoi(val, 0)); - room_data_.bg_color = color; - room_->setBgColor(color); - autosave(); - return "bgcolor: " + std::to_string(color); - } - if (property == "ITEMCOLOR1") { auto color = static_cast(safeStoi(val, 0)); room_data_.item_color1 = color; @@ -1353,7 +1343,7 @@ auto MapEditor::setRoomProperty(const std::string& property, const std::string& return toLower(property) + ": " + connection; } - return "Unknown property: " + property + " (use: bgcolor, itemcolor1, itemcolor2, conveyor, tileset, up, down, left, right)"; + return "Unknown property: " + property + " (use: itemcolor1, itemcolor2, conveyor, tileset, up, down, left, right)"; } // Crea una nueva habitación @@ -1405,7 +1395,6 @@ auto MapEditor::createNewRoom(const std::string& direction) -> std::string { // // Crear Room::Data por defecto con conexión recíproca Room::Data new_room; new_room.number = std::string(name_buf).substr(0, std::string(name_buf).find('.')); - new_room.bg_color = 0; new_room.tile_set_file = "standard.gif"; new_room.item_color1 = 11; new_room.item_color2 = 12; @@ -1439,7 +1428,6 @@ auto MapEditor::createNewRoom(const std::string& direction) -> std::string { // file << "room:\n"; file << " name_en: \"NO_NAME\"\n"; file << " name_ca: \"NO_NAME\"\n"; - file << " bgColor: black\n"; file << " tileSetFile: standard.gif\n"; file << "\n"; file << " connections:\n"; @@ -1698,7 +1686,7 @@ void MapEditor::renderGrid() const { auto game_surface = Screen::get()->getRendererSurface(); if (!game_surface) { return; } - const Uint8 COLOR = pickGridColor(room_data_.bg_color, game_surface); + const Uint8 COLOR = pickGridColor(0, game_surface); // Líneas verticales (cada 8 pixels) for (int x = Tile::SIZE; x < PlayArea::WIDTH; x += Tile::SIZE) { diff --git a/source/game/editor/room_saver.cpp b/source/game/editor/room_saver.cpp index 9502a1c..3acc01e 100644 --- a/source/game/editor/room_saver.cpp +++ b/source/game/editor/room_saver.cpp @@ -43,7 +43,7 @@ auto RoomSaver::buildYAML(const fkyaml::node& original_yaml, const Room::Data& r // --- Sección room --- out << "room:\n"; - out << " bgColor: " << static_cast(room_data.bg_color) << "\n"; + // bgColor ya no se escribe en el YAML out << " tileSetFile: " << room_data.tile_set_file << "\n"; // Conexiones diff --git a/source/game/entities/player.hpp b/source/game/entities/player.hpp index 2e9f8de..cac4c13 100644 --- a/source/game/entities/player.hpp +++ b/source/game/entities/player.hpp @@ -31,7 +31,7 @@ class Player { }; // --- Constantes de física --- - static constexpr float HORIZONTAL_VELOCITY = 60.0F; + static constexpr float HORIZONTAL_VELOCITY = 75.0F; static constexpr float HORIZONTAL_ACCEL = 500.0F; static constexpr float MAX_VY = 160.0F; static constexpr float JUMP_VELOCITY = -178.5F; diff --git a/source/game/gameplay/room_loader.cpp b/source/game/gameplay/room_loader.cpp index a77fc97..a76626c 100644 --- a/source/game/gameplay/room_loader.cpp +++ b/source/game/gameplay/room_loader.cpp @@ -70,9 +70,7 @@ void RoomLoader::parseRoomConfig(const fkyaml::node& yaml, Room::Data& room, con room.number = file_name.substr(0, file_name.find_last_of('.')); // Basic properties - if (room_node.contains("bgColor")) { - room.bg_color = readColorNode(room_node["bgColor"]); - } + // bgColor ya no se lee del YAML; bg_color queda siempre a 0 if (room_node.contains("tileSetFile")) { room.tile_set_file = room_node["tileSetFile"].get_value(); } diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index b2b633e..0b271e3 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -66,7 +66,7 @@ Game::Game(Mode mode) // Crea objetos e inicializa variables ItemTracker::init(); demoInit(); - room_ = std::make_shared(current_room_, scoreboard_data_); + room_ = getOrCreateRoom(current_room_); initPlayer(spawn_data_, room_); game_backbuffer_surface_ = std::make_shared(Options::game.width, Options::game.height); changeRoom(current_room_); @@ -314,6 +314,7 @@ void Game::updatePlaying(float delta_time) { if (transitioning_) { transition_old_room_->update(delta_time); } + updateAdjacentRooms(delta_time); switch (mode_) { case Mode::GAME: #ifdef _DEBUG @@ -420,8 +421,10 @@ void Game::transitionToState(State new_state) { // Lógica de ENTRADA según el nuevo estado if (new_state == State::BLACK_SCREEN) { + // Limpiar caché de habitaciones (enemigos vuelven a sus posiciones iniciales) + room_cache_.clear(); // Respawn room y player - room_ = std::make_shared(current_room_, scoreboard_data_); + room_ = getOrCreateRoom(current_room_); initPlayer(spawn_data_, room_); // Pausar ambos room_->setPaused(true); @@ -763,8 +766,8 @@ 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()) { // NOLINT(readability-static-accessed-through-instance) - // Crea un objeto habitación nuevo a partir del fichero - room_ = std::make_shared(room_path, scoreboard_data_); + // Obtiene la habitación del caché o la crea + room_ = getOrCreateRoom(room_path); // Pone el color del marcador en función del color del borde de la habitación if (room_tracker_->addRoom(room_path)) { @@ -788,6 +791,32 @@ auto Game::changeRoom(const std::string& room_path) -> bool { return false; } +// Obtiene una habitación del caché o la crea si no existe +auto Game::getOrCreateRoom(const std::string& room_path) -> std::shared_ptr { + auto it = room_cache_.find(room_path); + if (it != room_cache_.end()) { + return it->second; + } + auto room = std::make_shared(room_path, scoreboard_data_); + room_cache_[room_path] = room; + return room; +} + +// Actualiza los enemigos de las habitaciones adyacentes a la actual +void Game::updateAdjacentRooms(float delta_time) { + for (auto border : {Room::Border::TOP, Room::Border::RIGHT, Room::Border::BOTTOM, Room::Border::LEFT}) { + const auto ROOM_NAME = room_->getRoom(border); + if (ROOM_NAME == "0") { + continue; + } + auto adjacent = getOrCreateRoom(ROOM_NAME); + // Evitar actualizar la habitación actual o la que ya se actualiza en la transición + if (adjacent != room_ && adjacent != transition_old_room_) { + adjacent->update(delta_time); + } + } +} + // Comprueba si el jugador esta en el borde de la pantalla void Game::checkPlayerIsOnBorder() { // No permitir transiciones encadenadas diff --git a/source/game/scenes/game.hpp b/source/game/scenes/game.hpp index 6a4890d..9abf6db 100644 --- a/source/game/scenes/game.hpp +++ b/source/game/scenes/game.hpp @@ -2,10 +2,11 @@ #include -#include // Para initializer_list -#include // Para shared_ptr -#include // Para string -#include // Para vector +#include // Para initializer_list +#include // Para shared_ptr +#include // Para string +#include // Para unordered_map +#include // Para vector #include "game/entities/player.hpp" // Para PlayerSpawn #include "game/gameplay/room.hpp" // Para Room, Room::Border @@ -68,6 +69,8 @@ class Game { void renderFadeToEnding(); // Renderiza el juego en estado FADE_TO_ENDING (via backbuffer) static void renderPostFadeEnding(); // Renderiza el juego en estado POST_FADE_ENDING (pantalla negra) auto changeRoom(const std::string& room_path) -> bool; // Cambia de habitación + auto getOrCreateRoom(const std::string& room_path) -> std::shared_ptr; // Obtiene una habitación del caché o la crea + void updateAdjacentRooms(float delta_time); // Actualiza enemigos de las habitaciones adyacentes void handleInput(); // Comprueba el teclado void checkPlayerIsOnBorder(); // Comprueba si el jugador esta en el borde de la pantalla y actua auto checkPlayerAndEnemies() -> bool; // Comprueba las colisiones del jugador con los enemigos @@ -105,6 +108,9 @@ class Game { float state_time_{0.0F}; // Tiempo acumulado en el estado actual float fade_accumulator_{0.0F}; // Acumulador de tiempo para el fade + // Caché de habitaciones vivas (enemigos mantienen su posición) + std::unordered_map> room_cache_; + // Transición animada entre pantallas bool transitioning_{false}; // Indica si hay una transición en curso float transition_timer_{0.0F}; // Tiempo transcurrido en la transición