From 4b4bfdf314a8d2687fe736d4f0790a304baba483 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Fri, 10 Apr 2026 13:58:59 +0200 Subject: [PATCH] fase 1 de zones --- CMakeLists.txt | 1 + config/assets.yaml | 5 ++ data/tilesets/cave.gif | Bin 0 -> 8335 bytes data/tilesets/neighborhood.gif | Bin 0 -> 7934 bytes data/zones/zones.yaml | 13 ++++ source/game/gameplay/zone.hpp | 22 ++++++ source/game/gameplay/zone_manager.cpp | 98 ++++++++++++++++++++++++++ source/game/gameplay/zone_manager.hpp | 55 +++++++++++++++ source/game/scenes/game.cpp | 3 + 9 files changed, 197 insertions(+) create mode 100644 data/tilesets/cave.gif create mode 100644 data/tilesets/neighborhood.gif create mode 100644 data/zones/zones.yaml create mode 100644 source/game/gameplay/zone.hpp create mode 100644 source/game/gameplay/zone_manager.cpp create mode 100644 source/game/gameplay/zone_manager.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ca1c558..9fb832f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,7 @@ set(APP_SOURCES source/game/gameplay/room.cpp source/game/gameplay/scoreboard.cpp source/game/gameplay/tilemap_renderer.cpp + source/game/gameplay/zone_manager.cpp # Game - Scenes source/game/scenes/game.cpp diff --git a/config/assets.yaml b/config/assets.yaml index 035e3b2..1e4b0b0 100644 --- a/config/assets.yaml +++ b/config/assets.yaml @@ -63,6 +63,11 @@ assets: DATA: - ${PREFIX}/data/console/commands.yaml + # ZONES + zones: + DATA: + - ${PREFIX}/data/zones/zones.yaml + # ROOMS rooms: ROOM: diff --git a/data/tilesets/cave.gif b/data/tilesets/cave.gif new file mode 100644 index 0000000000000000000000000000000000000000..f15ee3475545deaad27bfdb8c6cd0e0da15cfb9f GIT binary patch literal 8335 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 literal 0 HcmV?d00001 diff --git a/data/tilesets/neighborhood.gif b/data/tilesets/neighborhood.gif new file mode 100644 index 0000000000000000000000000000000000000000..24e170808d721c8a0817420938ac807e5623c2cb GIT binary patch literal 7934 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 literal 0 HcmV?d00001 diff --git a/data/zones/zones.yaml b/data/zones/zones.yaml new file mode 100644 index 0000000..f76d28e --- /dev/null +++ b/data/zones/zones.yaml @@ -0,0 +1,13 @@ +# Zonas del juego +# Cada zona define un tileset y una pista de música compartidos por todas las +# habitaciones que pertenecen a ella. Las habitaciones individuales pueden +# sobreescribir tileSetFile y/o music en su propio yaml. + +zones: + - name: neighborhood + tileSetFile: neighborhood.gif + music: 574070_KUVO_Farewell_to_school.ogg + + - name: cave + tileSetFile: cave.gif + music: 574071_EA_DTV.ogg diff --git a/source/game/gameplay/zone.hpp b/source/game/gameplay/zone.hpp new file mode 100644 index 0000000..c278f41 --- /dev/null +++ b/source/game/gameplay/zone.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include // Para string + +/** + * @brief Datos de una zona del juego + * + * Una zona agrupa un conjunto de habitaciones que comparten tileset y música. + * Las habitaciones pueden hacer override individual de tile_set_file y/o music + * en su propio yaml; los valores aquí son la fuente por defecto. + * + * Las zonas se cargan desde data/zones/zones.yaml por el ZoneManager. + */ +namespace Zone { + + struct Data { + std::string name; // Nombre único de la zona (ej. "neighborhood", "cave") + std::string tile_set_file; // Fichero de tileset por defecto (ej. "neighborhood.gif") + std::string music; // Pista de música por defecto (ej. "574070_KUVO_Farewell_to_school.ogg") + }; + +} // namespace Zone diff --git a/source/game/gameplay/zone_manager.cpp b/source/game/gameplay/zone_manager.cpp new file mode 100644 index 0000000..926297b --- /dev/null +++ b/source/game/gameplay/zone_manager.cpp @@ -0,0 +1,98 @@ +#include "game/gameplay/zone_manager.hpp" + +#include // Para exception +#include // Para cerr, cout +#include // Para string + +#include "core/resources/resource_helper.hpp" // Para Resource::Helper::loadFile +#include "external/fkyaml_node.hpp" // Para fkyaml::node + +// [SINGLETON] +ZoneManager* ZoneManager::zone_manager = nullptr; + +// [SINGLETON] Inicialización: crea la instancia y carga el yaml de zonas +void ZoneManager::init() { + if (ZoneManager::zone_manager != nullptr) { return; } + ZoneManager::zone_manager = new ZoneManager(); + ZoneManager::zone_manager->loadFromFile("data/zones/zones.yaml"); +} + +// [SINGLETON] +void ZoneManager::destroy() { + delete ZoneManager::zone_manager; + ZoneManager::zone_manager = nullptr; +} + +// [SINGLETON] +auto ZoneManager::get() -> ZoneManager* { + return ZoneManager::zone_manager; +} + +// Carga zones.yaml usando Resource::Helper (soporta pack + filesystem) +void ZoneManager::loadFromFile(const std::string& file_path) { + auto file_data = Resource::Helper::loadFile(file_path); + if (file_data.empty()) { + std::cerr << "ZoneManager: Unable to load " << file_path << "\n"; + return; + } + + try { + const std::string YAML_CONTENT(file_data.begin(), file_data.end()); + auto yaml = fkyaml::node::deserialize(YAML_CONTENT); + + if (!yaml.contains("zones") || yaml["zones"].is_null()) { + std::cerr << "ZoneManager: " << file_path << " has no 'zones' section\n"; + return; + } + + for (const auto& zone_node : yaml["zones"]) { + Zone::Data zone; + + if (zone_node.contains("name")) { + zone.name = zone_node["name"].get_value(); + } + if (zone_node.contains("tileSetFile")) { + zone.tile_set_file = zone_node["tileSetFile"].get_value(); + } + if (zone_node.contains("music")) { + zone.music = zone_node["music"].get_value(); + } + + if (zone.name.empty()) { + std::cerr << "ZoneManager: skipping zone without name\n"; + continue; + } + + zones_.push_back(zone); + } + + std::cout << "ZoneManager: loaded " << zones_.size() << " zones from " << file_path << "\n"; + } catch (const fkyaml::exception& e) { + std::cerr << "ZoneManager: YAML parsing error in " << file_path << ": " << e.what() << "\n"; + } catch (const std::exception& e) { + std::cerr << "ZoneManager: Error loading " << file_path << ": " << e.what() << "\n"; + } +} + +auto ZoneManager::getZone(const std::string& name) const -> const Zone::Data* { + for (const auto& zone : zones_) { + if (zone.name == name) { + return &zone; + } + } + return nullptr; +} + +auto ZoneManager::getDefaultZone() const -> const Zone::Data* { + if (zones_.empty()) { return nullptr; } + return &zones_.front(); +} + +auto ZoneManager::getZoneNames() const -> std::vector { + std::vector names; + names.reserve(zones_.size()); + for (const auto& zone : zones_) { + names.push_back(zone.name); + } + return names; +} diff --git a/source/game/gameplay/zone_manager.hpp b/source/game/gameplay/zone_manager.hpp new file mode 100644 index 0000000..b34f90c --- /dev/null +++ b/source/game/gameplay/zone_manager.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include // Para string +#include // Para vector + +#include "game/gameplay/zone.hpp" // Para Zone::Data + +/** + * @brief Singleton que carga y gestiona el catálogo de zonas + * + * Carga data/zones/zones.yaml en init() y permite consultar zonas por nombre. + * El loader usa Resource::Helper::loadFile, que soporta tanto el resource pack + * como el filesystem (modo desarrollo). Por eso ZoneManager no depende del + * Resource::Cache y puede inicializarse en cualquier momento antes de + * RoomLoader::loadYAML. + */ +class ZoneManager { + public: + // Gestión singleton + static void init(); // Carga zones.yaml y crea el singleton + static void destroy(); // Destruye el singleton + static auto get() -> ZoneManager*; // Acceso al singleton + + /** + * @brief Devuelve la zona con el nombre indicado, o nullptr si no existe + */ + [[nodiscard]] auto getZone(const std::string& name) const -> const Zone::Data*; + + /** + * @brief Devuelve la zona por defecto (primera del fichero), o nullptr si no hay zonas + * + * Se usa como fallback cuando una room.yaml no especifica zone o especifica + * una zona desconocida. + */ + [[nodiscard]] auto getDefaultZone() const -> const Zone::Data*; + + /** + * @brief Devuelve la lista de nombres de todas las zonas (para validación en editor) + */ + [[nodiscard]] auto getZoneNames() const -> std::vector; + + private: + // Constantes singleton + static ZoneManager* zone_manager; // [SINGLETON] Objeto privado + + // Constructor y destructor privados [SINGLETON] + ZoneManager() = default; + ~ZoneManager() = default; + + // Carga el yaml y rellena zones_ + void loadFromFile(const std::string& file_path); + + // Variables miembro + std::vector zones_; // Catálogo de zonas +}; diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index 6503504..c75c7e0 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -25,6 +25,7 @@ #include "game/gameplay/item_tracker.hpp" // Para ItemTracker #include "game/gameplay/key_tracker.hpp" // Para KeyTracker #include "game/gameplay/room.hpp" // Para Room, RoomData +#include "game/gameplay/zone_manager.hpp" // Para ZoneManager #include "game/gameplay/room_tracker.hpp" // Para RoomTracker #include "game/gameplay/scoreboard.hpp" // Para Scoreboard::Data, Scoreboard #include "game/options.hpp" // Para Options, options, Cheat, SectionState @@ -68,6 +69,7 @@ Game::Game(Mode mode) #endif // Crea objetos e inicializa variables + ZoneManager::init(); ItemTracker::init(); KeyTracker::init(); DoorTracker::init(); @@ -173,6 +175,7 @@ Game::~Game() { KeyTracker::destroy(); DoorTracker::destroy(); Inventory::destroy(); + ZoneManager::destroy(); if (Console::get() != nullptr) { Console::get()->on_toggle = nullptr; }