fase 1 de zones

This commit is contained in:
2026-04-10 13:58:59 +02:00
parent 12ace89890
commit 4b4bfdf314
9 changed files with 197 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
#pragma once
#include <string> // 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

View File

@@ -0,0 +1,98 @@
#include "game/gameplay/zone_manager.hpp"
#include <exception> // Para exception
#include <iostream> // Para cerr, cout
#include <string> // 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<std::string>();
}
if (zone_node.contains("tileSetFile")) {
zone.tile_set_file = zone_node["tileSetFile"].get_value<std::string>();
}
if (zone_node.contains("music")) {
zone.music = zone_node["music"].get_value<std::string>();
}
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::string> {
std::vector<std::string> names;
names.reserve(zones_.size());
for (const auto& zone : zones_) {
names.push_back(zone.name);
}
return names;
}

View File

@@ -0,0 +1,55 @@
#pragma once
#include <string> // Para string
#include <vector> // 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<std::string>;
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<Zone::Data> zones_; // Catálogo de zonas
};