migrat de yaml-cpp a fkYAML

This commit is contained in:
2025-11-17 09:25:50 +01:00
parent 23fe4a35a9
commit 6827512025
240 changed files with 15312 additions and 18558 deletions

View File

@@ -2,19 +2,19 @@
#include <exception> // Para exception
#include <iostream> // Para cout, cerr
#include <yaml-cpp/yaml.h> // Para YAML::Node, YAML::LoadFile
#include "external/fkyaml_node.hpp" // Para fkyaml::node
#include "core/resources/resource_helper.hpp" // Para Resource::Helper
#include "utils/defines.hpp" // Para TILE_SIZE
#include "utils/utils.hpp" // Para stringToColor
// Convierte room connection de YAML a formato legacy
// Convierte room connection de YAML a formato con extensión
auto RoomLoader::convertRoomConnection(const std::string& value) -> std::string {
if (value == "null" || value.empty()) {
return "0";
}
// "02" → "02.room"
return value + ".room";
// "02" → "02.yaml"
return value + ".yaml";
}
// Convierte un tilemap 2D a vector 1D flat
@@ -49,82 +49,82 @@ auto RoomLoader::loadYAML(const std::string& file_path, bool verbose) -> Room::D
// Parse YAML from string
std::string yaml_content(file_data.begin(), file_data.end());
YAML::Node yaml = YAML::Load(yaml_content);
auto yaml = fkyaml::node::deserialize(yaml_content);
// --- Parse room configuration ---
if (yaml["room"]) {
const YAML::Node& room_node = yaml["room"];
if (yaml.contains("room")) {
const auto& room_node = yaml["room"];
// Extract room number from filename (e.g., "01.yaml" → "01")
room.number = FILE_NAME.substr(0, FILE_NAME.find_last_of('.'));
// Basic properties
if (room_node["name"]) {
room.name = room_node["name"].as<std::string>();
if (room_node.contains("name")) {
room.name = room_node["name"].get_value<std::string>();
}
if (room_node["bgColor"]) {
room.bg_color = room_node["bgColor"].as<std::string>();
if (room_node.contains("bgColor")) {
room.bg_color = room_node["bgColor"].get_value<std::string>();
}
if (room_node["border"]) {
room.border_color = room_node["border"].as<std::string>();
if (room_node.contains("border")) {
room.border_color = room_node["border"].get_value<std::string>();
}
if (room_node["tileSetFile"]) {
room.tile_set_file = room_node["tileSetFile"].as<std::string>();
if (room_node.contains("tileSetFile")) {
room.tile_set_file = room_node["tileSetFile"].get_value<std::string>();
}
// Room connections
if (room_node["connections"]) {
const YAML::Node& conn = room_node["connections"];
if (room_node.contains("connections")) {
const auto& conn = room_node["connections"];
if (conn["up"]) {
room.upper_room = convertRoomConnection(conn["up"].as<std::string>("null"));
if (conn.contains("up")) {
room.upper_room = convertRoomConnection(conn["up"].get_value_or<std::string>("null"));
} else {
room.upper_room = "0";
}
if (conn["down"]) {
room.lower_room = convertRoomConnection(conn["down"].as<std::string>("null"));
if (conn.contains("down")) {
room.lower_room = convertRoomConnection(conn["down"].get_value_or<std::string>("null"));
} else {
room.lower_room = "0";
}
if (conn["left"]) {
room.left_room = convertRoomConnection(conn["left"].as<std::string>("null"));
if (conn.contains("left")) {
room.left_room = convertRoomConnection(conn["left"].get_value_or<std::string>("null"));
} else {
room.left_room = "0";
}
if (conn["right"]) {
room.right_room = convertRoomConnection(conn["right"].as<std::string>("null"));
if (conn.contains("right")) {
room.right_room = convertRoomConnection(conn["right"].get_value_or<std::string>("null"));
} else {
room.right_room = "0";
}
}
// Item colors
if (room_node["itemColor1"]) {
room.item_color1 = room_node["itemColor1"].as<std::string>("yellow");
if (room_node.contains("itemColor1")) {
room.item_color1 = room_node["itemColor1"].get_value_or<std::string>("yellow");
} else {
room.item_color1 = "yellow";
}
if (room_node["itemColor2"]) {
room.item_color2 = room_node["itemColor2"].as<std::string>("magenta");
if (room_node.contains("itemColor2")) {
room.item_color2 = room_node["itemColor2"].get_value_or<std::string>("magenta");
} else {
room.item_color2 = "magenta";
}
// Conveyor belt direction
if (room_node["autoSurface"]) {
room.conveyor_belt_direction = room_node["autoSurface"].as<int>(0);
if (room_node.contains("autoSurface")) {
room.conveyor_belt_direction = room_node["autoSurface"].get_value_or<int>(0);
} else {
room.conveyor_belt_direction = 0;
}
}
// --- Parse tilemap ---
if (yaml["tilemap"]) {
const YAML::Node& tilemap_node = yaml["tilemap"];
if (yaml.contains("tilemap")) {
const auto& tilemap_node = yaml["tilemap"];
// Read 2D array
std::vector<std::vector<int>> tilemap_2d;
@@ -135,7 +135,7 @@ auto RoomLoader::loadYAML(const std::string& file_path, bool verbose) -> Room::D
row.reserve(32);
for (const auto& tile_node : row_node) {
row.push_back(tile_node.as<int>());
row.push_back(tile_node.get_value<int>());
}
tilemap_2d.push_back(row);
@@ -152,78 +152,78 @@ auto RoomLoader::loadYAML(const std::string& file_path, bool verbose) -> Room::D
}
// --- Parse enemies ---
if (yaml["enemies"] && !yaml["enemies"].IsNull()) {
const YAML::Node& enemies_node = yaml["enemies"];
if (yaml.contains("enemies") && !yaml["enemies"].is_null()) {
const auto& enemies_node = yaml["enemies"];
for (const auto& enemy_node : enemies_node) {
Enemy::Data enemy;
// Animation path
if (enemy_node["animation"]) {
enemy.animation_path = enemy_node["animation"].as<std::string>();
if (enemy_node.contains("animation")) {
enemy.animation_path = enemy_node["animation"].get_value<std::string>();
}
// Position (in tiles, convert to pixels)
if (enemy_node["position"]) {
const YAML::Node& pos = enemy_node["position"];
if (pos["x"]) {
enemy.x = pos["x"].as<float>() * TILE_SIZE;
if (enemy_node.contains("position")) {
const auto& pos = enemy_node["position"];
if (pos.contains("x")) {
enemy.x = pos["x"].get_value<float>() * TILE_SIZE;
}
if (pos["y"]) {
enemy.y = pos["y"].as<float>() * TILE_SIZE;
if (pos.contains("y")) {
enemy.y = pos["y"].get_value<float>() * TILE_SIZE;
}
}
// Velocity (already in pixels/second)
if (enemy_node["velocity"]) {
const YAML::Node& vel = enemy_node["velocity"];
if (vel["x"]) {
enemy.vx = vel["x"].as<float>();
if (enemy_node.contains("velocity")) {
const auto& vel = enemy_node["velocity"];
if (vel.contains("x")) {
enemy.vx = vel["x"].get_value<float>();
}
if (vel["y"]) {
enemy.vy = vel["y"].as<float>();
if (vel.contains("y")) {
enemy.vy = vel["y"].get_value<float>();
}
}
// Boundaries (in tiles, convert to pixels)
if (enemy_node["boundaries"]) {
const YAML::Node& bounds = enemy_node["boundaries"];
if (bounds["x1"]) {
enemy.x1 = bounds["x1"].as<int>() * TILE_SIZE;
if (enemy_node.contains("boundaries")) {
const auto& bounds = enemy_node["boundaries"];
if (bounds.contains("x1")) {
enemy.x1 = bounds["x1"].get_value<int>() * TILE_SIZE;
}
if (bounds["y1"]) {
enemy.y1 = bounds["y1"].as<int>() * TILE_SIZE;
if (bounds.contains("y1")) {
enemy.y1 = bounds["y1"].get_value<int>() * TILE_SIZE;
}
if (bounds["x2"]) {
enemy.x2 = bounds["x2"].as<int>() * TILE_SIZE;
if (bounds.contains("x2")) {
enemy.x2 = bounds["x2"].get_value<int>() * TILE_SIZE;
}
if (bounds["y2"]) {
enemy.y2 = bounds["y2"].as<int>() * TILE_SIZE;
if (bounds.contains("y2")) {
enemy.y2 = bounds["y2"].get_value<int>() * TILE_SIZE;
}
}
// Color
if (enemy_node["color"]) {
enemy.color = enemy_node["color"].as<std::string>("white");
if (enemy_node.contains("color")) {
enemy.color = enemy_node["color"].get_value_or<std::string>("white");
} else {
enemy.color = "white";
}
// Optional fields
if (enemy_node["flip"]) {
enemy.flip = enemy_node["flip"].as<bool>(false);
if (enemy_node.contains("flip")) {
enemy.flip = enemy_node["flip"].get_value_or<bool>(false);
} else {
enemy.flip = false;
}
if (enemy_node["mirror"]) {
enemy.mirror = enemy_node["mirror"].as<bool>(false);
if (enemy_node.contains("mirror")) {
enemy.mirror = enemy_node["mirror"].get_value_or<bool>(false);
} else {
enemy.mirror = false;
}
if (enemy_node["frame"]) {
enemy.frame = enemy_node["frame"].as<int>(-1);
if (enemy_node.contains("frame")) {
enemy.frame = enemy_node["frame"].get_value_or<int>(-1);
} else {
enemy.frame = -1;
}
@@ -237,36 +237,36 @@ auto RoomLoader::loadYAML(const std::string& file_path, bool verbose) -> Room::D
}
// --- Parse items ---
if (yaml["items"] && !yaml["items"].IsNull()) {
const YAML::Node& items_node = yaml["items"];
if (yaml.contains("items") && !yaml["items"].is_null()) {
const auto& items_node = yaml["items"];
for (const auto& item_node : items_node) {
Item::Data item;
// Tileset file
if (item_node["tileSetFile"]) {
item.tile_set_file = item_node["tileSetFile"].as<std::string>();
if (item_node.contains("tileSetFile")) {
item.tile_set_file = item_node["tileSetFile"].get_value<std::string>();
}
// Tile index
if (item_node["tile"]) {
item.tile = item_node["tile"].as<int>();
if (item_node.contains("tile")) {
item.tile = item_node["tile"].get_value<int>();
}
// Position (in tiles, convert to pixels)
if (item_node["position"]) {
const YAML::Node& pos = item_node["position"];
if (pos["x"]) {
item.x = pos["x"].as<float>() * TILE_SIZE;
if (item_node.contains("position")) {
const auto& pos = item_node["position"];
if (pos.contains("x")) {
item.x = pos["x"].get_value<float>() * TILE_SIZE;
}
if (pos["y"]) {
item.y = pos["y"].as<float>() * TILE_SIZE;
if (pos.contains("y")) {
item.y = pos["y"].get_value<float>() * TILE_SIZE;
}
}
// Counter
if (item_node["counter"]) {
item.counter = item_node["counter"].as<int>(0);
if (item_node.contains("counter")) {
item.counter = item_node["counter"].get_value_or<int>(0);
} else {
item.counter = 0;
}
@@ -287,7 +287,7 @@ auto RoomLoader::loadYAML(const std::string& file_path, bool verbose) -> Room::D
std::cout << "Room loaded successfully: " << FILE_NAME << '\n';
}
} catch (const YAML::Exception& e) {
} catch (const fkyaml::exception& e) {
std::cerr << "YAML parsing error in " << FILE_NAME << ": " << e.what() << '\n';
} catch (const std::exception& e) {
std::cerr << "Error loading room " << FILE_NAME << ": " << e.what() << '\n';

View File

@@ -0,0 +1,297 @@
#include "room_loader.hpp"
#include <exception> // Para exception
#include <iostream> // Para cout, cerr
#include <yaml-cpp/yaml.h> // Para YAML::Node, YAML::LoadFile
#include "core/resources/resource_helper.hpp" // Para Resource::Helper
#include "utils/defines.hpp" // Para TILE_SIZE
#include "utils/utils.hpp" // Para stringToColor
// Convierte room connection de YAML a formato con extensión
auto RoomLoader::convertRoomConnection(const std::string& value) -> std::string {
if (value == "null" || value.empty()) {
return "0";
}
// "02" → "02.yaml"
return value + ".yaml";
}
// Convierte un tilemap 2D a vector 1D flat
auto RoomLoader::flattenTilemap(const std::vector<std::vector<int>>& tilemap_2d) -> std::vector<int> {
std::vector<int> tilemap_flat;
tilemap_flat.reserve(512); // 16 rows × 32 cols
for (const auto& row : tilemap_2d) {
for (int tile : row) {
tilemap_flat.push_back(tile);
}
}
return tilemap_flat;
}
// Carga un archivo de room en formato YAML
auto RoomLoader::loadYAML(const std::string& file_path, bool verbose) -> Room::Data {
Room::Data room;
// Extract filename for logging
const std::string FILE_NAME = file_path.substr(file_path.find_last_of("\\/") + 1);
try {
// Load YAML file using ResourceHelper (supports both filesystem and pack)
auto file_data = Resource::Helper::loadFile(file_path);
if (file_data.empty()) {
std::cerr << "Error: Unable to load file " << FILE_NAME << '\n';
return room;
}
// Parse YAML from string
std::string yaml_content(file_data.begin(), file_data.end());
YAML::Node yaml = YAML::Load(yaml_content);
// --- Parse room configuration ---
if (yaml["room"]) {
const YAML::Node& room_node = yaml["room"];
// Extract room number from filename (e.g., "01.yaml" → "01")
room.number = FILE_NAME.substr(0, FILE_NAME.find_last_of('.'));
// Basic properties
if (room_node["name"]) {
room.name = room_node["name"].as<std::string>();
}
if (room_node["bgColor"]) {
room.bg_color = room_node["bgColor"].as<std::string>();
}
if (room_node["border"]) {
room.border_color = room_node["border"].as<std::string>();
}
if (room_node["tileSetFile"]) {
room.tile_set_file = room_node["tileSetFile"].as<std::string>();
}
// Room connections
if (room_node["connections"]) {
const YAML::Node& conn = room_node["connections"];
if (conn["up"]) {
room.upper_room = convertRoomConnection(conn["up"].as<std::string>("null"));
} else {
room.upper_room = "0";
}
if (conn["down"]) {
room.lower_room = convertRoomConnection(conn["down"].as<std::string>("null"));
} else {
room.lower_room = "0";
}
if (conn["left"]) {
room.left_room = convertRoomConnection(conn["left"].as<std::string>("null"));
} else {
room.left_room = "0";
}
if (conn["right"]) {
room.right_room = convertRoomConnection(conn["right"].as<std::string>("null"));
} else {
room.right_room = "0";
}
}
// Item colors
if (room_node["itemColor1"]) {
room.item_color1 = room_node["itemColor1"].as<std::string>("yellow");
} else {
room.item_color1 = "yellow";
}
if (room_node["itemColor2"]) {
room.item_color2 = room_node["itemColor2"].as<std::string>("magenta");
} else {
room.item_color2 = "magenta";
}
// Conveyor belt direction
if (room_node["autoSurface"]) {
room.conveyor_belt_direction = room_node["autoSurface"].as<int>(0);
} else {
room.conveyor_belt_direction = 0;
}
}
// --- Parse tilemap ---
if (yaml["tilemap"]) {
const YAML::Node& tilemap_node = yaml["tilemap"];
// Read 2D array
std::vector<std::vector<int>> tilemap_2d;
tilemap_2d.reserve(16);
for (const auto& row_node : tilemap_node) {
std::vector<int> row;
row.reserve(32);
for (const auto& tile_node : row_node) {
row.push_back(tile_node.as<int>());
}
tilemap_2d.push_back(row);
}
// Convert to 1D flat array
room.tile_map = flattenTilemap(tilemap_2d);
if (verbose) {
std::cout << "Loaded tilemap: " << room.tile_map.size() << " tiles\n";
}
} else {
std::cerr << "Warning: No tilemap found in " << FILE_NAME << '\n';
}
// --- Parse enemies ---
if (yaml["enemies"] && !yaml["enemies"].IsNull()) {
const YAML::Node& enemies_node = yaml["enemies"];
for (const auto& enemy_node : enemies_node) {
Enemy::Data enemy;
// Animation path
if (enemy_node["animation"]) {
enemy.animation_path = enemy_node["animation"].as<std::string>();
}
// Position (in tiles, convert to pixels)
if (enemy_node["position"]) {
const YAML::Node& pos = enemy_node["position"];
if (pos["x"]) {
enemy.x = pos["x"].as<float>() * TILE_SIZE;
}
if (pos["y"]) {
enemy.y = pos["y"].as<float>() * TILE_SIZE;
}
}
// Velocity (already in pixels/second)
if (enemy_node["velocity"]) {
const YAML::Node& vel = enemy_node["velocity"];
if (vel["x"]) {
enemy.vx = vel["x"].as<float>();
}
if (vel["y"]) {
enemy.vy = vel["y"].as<float>();
}
}
// Boundaries (in tiles, convert to pixels)
if (enemy_node["boundaries"]) {
const YAML::Node& bounds = enemy_node["boundaries"];
if (bounds["x1"]) {
enemy.x1 = bounds["x1"].as<int>() * TILE_SIZE;
}
if (bounds["y1"]) {
enemy.y1 = bounds["y1"].as<int>() * TILE_SIZE;
}
if (bounds["x2"]) {
enemy.x2 = bounds["x2"].as<int>() * TILE_SIZE;
}
if (bounds["y2"]) {
enemy.y2 = bounds["y2"].as<int>() * TILE_SIZE;
}
}
// Color
if (enemy_node["color"]) {
enemy.color = enemy_node["color"].as<std::string>("white");
} else {
enemy.color = "white";
}
// Optional fields
if (enemy_node["flip"]) {
enemy.flip = enemy_node["flip"].as<bool>(false);
} else {
enemy.flip = false;
}
if (enemy_node["mirror"]) {
enemy.mirror = enemy_node["mirror"].as<bool>(false);
} else {
enemy.mirror = false;
}
if (enemy_node["frame"]) {
enemy.frame = enemy_node["frame"].as<int>(-1);
} else {
enemy.frame = -1;
}
room.enemies.push_back(enemy);
}
if (verbose) {
std::cout << "Loaded " << room.enemies.size() << " enemies\n";
}
}
// --- Parse items ---
if (yaml["items"] && !yaml["items"].IsNull()) {
const YAML::Node& items_node = yaml["items"];
for (const auto& item_node : items_node) {
Item::Data item;
// Tileset file
if (item_node["tileSetFile"]) {
item.tile_set_file = item_node["tileSetFile"].as<std::string>();
}
// Tile index
if (item_node["tile"]) {
item.tile = item_node["tile"].as<int>();
}
// Position (in tiles, convert to pixels)
if (item_node["position"]) {
const YAML::Node& pos = item_node["position"];
if (pos["x"]) {
item.x = pos["x"].as<float>() * TILE_SIZE;
}
if (pos["y"]) {
item.y = pos["y"].as<float>() * TILE_SIZE;
}
}
// Counter
if (item_node["counter"]) {
item.counter = item_node["counter"].as<int>(0);
} else {
item.counter = 0;
}
// Colors (assigned from room defaults)
item.color1 = stringToColor(room.item_color1);
item.color2 = stringToColor(room.item_color2);
room.items.push_back(item);
}
if (verbose) {
std::cout << "Loaded " << room.items.size() << " items\n";
}
}
if (verbose) {
std::cout << "Room loaded successfully: " << FILE_NAME << '\n';
}
} catch (const YAML::Exception& e) {
std::cerr << "YAML parsing error in " << FILE_NAME << ": " << e.what() << '\n';
} catch (const std::exception& e) {
std::cerr << "Error loading room " << FILE_NAME << ": " << e.what() << '\n';
}
return room;
}

View File

@@ -48,9 +48,9 @@ class RoomLoader {
private:
/**
* @brief Convierte room connection de YAML a formato legacy
* @brief Convierte room connection de YAML a formato con extensión
* @param value Valor del YAML (null o "02")
* @return String en formato legacy ("0" para null, "02.room" para "02")
* @return String con extensión YAML ("0" para null, "02.yaml" para "02")
*/
static auto convertRoomConnection(const std::string& value) -> std::string;

View File

@@ -38,10 +38,10 @@ Game::Game(Mode mode)
stats_(std::make_shared<Stats>(Resource::List::get()->get("stats.csv"), Resource::List::get()->get("stats_buffer.csv"))),
mode_(mode),
#ifdef _DEBUG
current_room_("03.room"),
current_room_("03.yaml"),
spawn_data_(Player::SpawnData(25 * TILE_SIZE, 13 * TILE_SIZE, 0, 0, 0, Player::State::ON_GROUND, SDL_FLIP_HORIZONTAL))
#else
current_room_("03.room"),
current_room_("03.yaml"),
spawn_data_(Player::SpawnData(25 * TILE_SIZE, 13 * TILE_SIZE, 0, 0, 0, Player::State::ON_GROUND, SDL_FLIP_HORIZONTAL))
#endif
{
@@ -602,7 +602,7 @@ void Game::keepMusicPlaying() {
// DEMO MODE: Inicializa las variables para el modo demo
void Game::demoInit() {
if (mode_ == Mode::DEMO) {
demo_ = DemoData(0.0F, 0, {"04.room", "54.room", "20.room", "09.room", "05.room", "11.room", "31.room", "44.room"});
demo_ = DemoData(0.0F, 0, {"04.yaml", "54.yaml", "20.yaml", "09.yaml", "05.yaml", "11.yaml", "31.yaml", "44.yaml"});
current_room_ = demo_.rooms.front();
}
}