refactor room_format: write*Section per cada part del YAML

This commit is contained in:
2026-05-17 22:02:49 +02:00
parent 3f4ead40e1
commit cbd7f17978
2 changed files with 123 additions and 147 deletions
+113 -145
View File
@@ -548,31 +548,17 @@ auto RoomFormat::roomConnectionToYAML(const std::string& connection) -> std::str
return connection;
}
auto RoomFormat::buildContent(const Room::Data& room_data) -> std::string { // NOLINT(readability-function-cognitive-complexity)
std::ostringstream out;
// --- Sección room ---
void RoomFormat::writeRoomSection(std::ostringstream& out, const Room::Data& room_data) {
out << "room:\n";
// zone es siempre obligatoria
out << " zone: " << room_data.zone << "\n";
// tileSetFile solo si es override explícito del valor heredado de la zona
if (room_data.tile_set_overridden) {
out << " tileSetFile: " << room_data.tile_set_file << "\n";
}
// tileSetFile/music/bgColor solo si son override explícito del valor heredado de la zona
if (room_data.tile_set_overridden) { out << " tileSetFile: " << room_data.tile_set_file << "\n"; }
if (room_data.music_overridden) { out << " music: " << room_data.music << "\n"; }
if (room_data.bg_color_overridden) { out << " bgColor: " << static_cast<int>(room_data.bg_color) << "\n"; }
// music solo si es override explícito del valor heredado de la zona
if (room_data.music_overridden) {
out << " music: " << room_data.music << "\n";
}
// bgColor solo si es override explícito del valor heredado de la zona
if (room_data.bg_color_overridden) {
out << " bgColor: " << static_cast<int>(room_data.bg_color) << "\n";
}
// Conexiones
out << "\n";
out << " # Conexiones de la habitación (null = sin conexión)\n";
out << " connections:\n";
@@ -580,155 +566,137 @@ auto RoomFormat::buildContent(const Room::Data& room_data) -> std::string { //
out << " down: " << roomConnectionToYAML(room_data.lower_room) << "\n";
out << " left: " << roomConnectionToYAML(room_data.left_room) << "\n";
out << " right: " << roomConnectionToYAML(room_data.right_room) << "\n";
}
// --- Tilemap (MAP_HEIGHT filas × MAP_WIDTH columnas, formato flow) ---
void RoomFormat::writeTilemapSection(std::ostringstream& out, const Room::Data& room_data) {
out << "\n";
out << "# Tilemap: " << Map::HEIGHT << " filas x " << Map::WIDTH << " columnas @ " << Tile::SIZE << "px/tile\n";
out << "tilemap:\n";
// Mapa de dibujo
out << " # Mapa de dibujo (indices de tiles, -1 = vacio)\n";
out << " draw:\n";
for (int row = 0; row < Map::HEIGHT; ++row) {
out << " - [";
for (int col = 0; col < Map::WIDTH; ++col) {
int index = (row * Map::WIDTH) + col;
if (index < static_cast<int>(room_data.tile_map.size())) {
out << room_data.tile_map[index];
} else {
out << -1;
auto write_grid = [&out](const auto& tilemap, const char* header, int empty_value) {
out << header;
for (int row = 0; row < Map::HEIGHT; ++row) {
out << " - [";
for (int col = 0; col < Map::WIDTH; ++col) {
const int INDEX = (row * Map::WIDTH) + col;
out << (INDEX < static_cast<int>(tilemap.size()) ? tilemap[INDEX] : empty_value);
if (col < Map::WIDTH - 1) { out << ", "; }
}
if (col < Map::WIDTH - 1) { out << ", "; }
out << "]\n";
}
out << "]\n";
}
};
// Mapa de colisiones
out << " # Mapa de colisiones (0 = vacio, 1 = solido)\n";
out << " collision:\n";
for (int row = 0; row < Map::HEIGHT; ++row) {
out << " - [";
for (int col = 0; col < Map::WIDTH; ++col) {
int index = (row * Map::WIDTH) + col;
if (index < static_cast<int>(room_data.collision_tile_map.size())) {
out << room_data.collision_tile_map[index];
} else {
out << 0;
}
if (col < Map::WIDTH - 1) { out << ", "; }
}
out << "]\n";
}
write_grid(room_data.tile_map, " # Mapa de dibujo (indices de tiles, -1 = vacio)\n draw:\n", -1);
write_grid(room_data.collision_tile_map, " # Mapa de colisiones (0 = vacio, 1 = solido)\n collision:\n", 0);
}
// --- Enemigos ---
if (!room_data.enemies.empty()) {
void RoomFormat::writeEnemiesSection(std::ostringstream& out, const Room::Data& room_data) {
if (room_data.enemies.empty()) { return; }
out << "\n";
out << "# Enemigos en esta habitación\n";
out << "enemies:\n";
for (const auto& enemy : room_data.enemies) {
out << " - animation: " << enemy.animation_path << "\n";
if (enemy.type != "path") { out << " type: " << enemy.type << "\n"; }
const int POS_X = static_cast<int>(std::round(enemy.x / Tile::SIZE));
const int POS_Y = static_cast<int>(std::round(enemy.y / Tile::SIZE));
out << " position: {x: " << POS_X << ", y: " << POS_Y << "}\n";
out << " velocity: {x: " << enemy.vx << ", y: " << enemy.vy << "}\n";
const int B1_X = enemy.x1 / Tile::SIZE;
const int B1_Y = enemy.y1 / Tile::SIZE;
const int B2_X = enemy.x2 / Tile::SIZE;
const int B2_Y = enemy.y2 / Tile::SIZE;
out << " boundaries:\n";
out << " position1: {x: " << B1_X << ", y: " << B1_Y << "}\n";
out << " position2: {x: " << B2_X << ", y: " << B2_Y << "}\n";
if (enemy.flip) { out << " flip: true\n"; }
if (enemy.mirror) { out << " mirror: true\n"; }
if (enemy.frame != -1) { out << " frame: " << enemy.frame << "\n"; }
out << "\n";
out << "# Enemigos en esta habitación\n";
out << "enemies:\n";
for (const auto& enemy : room_data.enemies) {
out << " - animation: " << enemy.animation_path << "\n";
if (enemy.type != "path") { out << " type: " << enemy.type << "\n"; }
int pos_x = static_cast<int>(std::round(enemy.x / Tile::SIZE));
int pos_y = static_cast<int>(std::round(enemy.y / Tile::SIZE));
out << " position: {x: " << pos_x << ", y: " << pos_y << "}\n";
out << " velocity: {x: " << enemy.vx << ", y: " << enemy.vy << "}\n";
int b1_x = enemy.x1 / Tile::SIZE;
int b1_y = enemy.y1 / Tile::SIZE;
int b2_x = enemy.x2 / Tile::SIZE;
int b2_y = enemy.y2 / Tile::SIZE;
out << " boundaries:\n";
out << " position1: {x: " << b1_x << ", y: " << b1_y << "}\n";
out << " position2: {x: " << b2_x << ", y: " << b2_y << "}\n";
if (enemy.flip) { out << " flip: true\n"; }
if (enemy.mirror) { out << " mirror: true\n"; }
if (enemy.frame != -1) { out << " frame: " << enemy.frame << "\n"; }
out << "\n";
}
}
}
// --- Items ---
if (!room_data.items.empty()) {
out << "# Objetos en esta habitación\n";
out << "items:\n";
for (const auto& item : room_data.items) {
out << " - tileSetFile: " << item.tile_set_file << "\n";
out << " tile: " << item.tile << "\n";
void RoomFormat::writeItemsSection(std::ostringstream& out, const Room::Data& room_data) {
if (room_data.items.empty()) { return; }
out << "# Objetos en esta habitación\n";
out << "items:\n";
for (const auto& item : room_data.items) {
out << " - tileSetFile: " << item.tile_set_file << "\n";
out << " tile: " << item.tile << "\n";
int item_x = static_cast<int>(std::round(item.x / Tile::SIZE));
int item_y = static_cast<int>(std::round(item.y / Tile::SIZE));
out << " position: {x: " << item_x << ", y: " << item_y << "}\n";
const int ITEM_X = static_cast<int>(std::round(item.x / Tile::SIZE));
const int ITEM_Y = static_cast<int>(std::round(item.y / Tile::SIZE));
out << " position: {x: " << ITEM_X << ", y: " << ITEM_Y << "}\n";
if (item.counter != 0) {
out << " counter: " << item.counter << "\n";
}
// color1/color2 solo si son override explícito del default
if (item.color1_overridden) {
out << " color1: " << static_cast<int>(item.color1) << "\n";
}
if (item.color2_overridden) {
out << " color2: " << static_cast<int>(item.color2) << "\n";
}
out << "\n";
}
if (item.counter != 0) { out << " counter: " << item.counter << "\n"; }
if (item.color1_overridden) { out << " color1: " << static_cast<int>(item.color1) << "\n"; }
if (item.color2_overridden) { out << " color2: " << static_cast<int>(item.color2) << "\n"; }
out << "\n";
}
}
// --- Plataformas ---
if (!room_data.platforms.empty()) {
out << "# Plataformas móviles en esta habitación\n";
out << "platforms:\n";
for (const auto& plat : room_data.platforms) {
out << " - animation: " << plat.animation_path << "\n";
out << " speed: " << plat.speed << "\n";
out << " loop: " << (plat.loop == LoopMode::CIRCULAR ? "circular" : "pingpong") << "\n";
if (plat.easing != "linear") { out << " easing: " << plat.easing << "\n"; }
if (plat.frame != -1) { out << " frame: " << plat.frame << "\n"; }
out << " path:\n";
for (const auto& wp : plat.path) {
int wx = static_cast<int>(std::round(wp.x / Tile::SIZE));
int wy = static_cast<int>(std::round(wp.y / Tile::SIZE));
out << " - {x: " << wx << ", y: " << wy;
if (wp.wait > 0.0F) { out << ", wait: " << wp.wait; }
out << "}\n";
}
out << "\n";
void RoomFormat::writePlatformsSection(std::ostringstream& out, const Room::Data& room_data) {
if (room_data.platforms.empty()) { return; }
out << "# Plataformas móviles en esta habitación\n";
out << "platforms:\n";
for (const auto& plat : room_data.platforms) {
out << " - animation: " << plat.animation_path << "\n";
out << " speed: " << plat.speed << "\n";
out << " loop: " << (plat.loop == LoopMode::CIRCULAR ? "circular" : "pingpong") << "\n";
if (plat.easing != "linear") { out << " easing: " << plat.easing << "\n"; }
if (plat.frame != -1) { out << " frame: " << plat.frame << "\n"; }
out << " path:\n";
for (const auto& wp : plat.path) {
const int WX = static_cast<int>(std::round(wp.x / Tile::SIZE));
const int WY = static_cast<int>(std::round(wp.y / Tile::SIZE));
out << " - {x: " << WX << ", y: " << WY;
if (wp.wait > 0.0F) { out << ", wait: " << wp.wait; }
out << "}\n";
}
out << "\n";
}
}
// --- Llaves ---
if (!room_data.keys.empty()) {
out << "# Llaves en esta habitación\n";
out << "keys:\n";
for (const auto& key : room_data.keys) {
out << " - animation: " << key.animation_path << "\n";
out << " id: \"" << key.id << "\"\n";
int kx = static_cast<int>(std::round(key.x / Tile::SIZE));
int ky = static_cast<int>(std::round(key.y / Tile::SIZE));
out << " position: {x: " << kx << ", y: " << ky << "}\n";
out << "\n";
}
void RoomFormat::writeKeysSection(std::ostringstream& out, const Room::Data& room_data) {
if (room_data.keys.empty()) { return; }
out << "# Llaves en esta habitación\n";
out << "keys:\n";
for (const auto& key : room_data.keys) {
out << " - animation: " << key.animation_path << "\n";
out << " id: \"" << key.id << "\"\n";
const int KX = static_cast<int>(std::round(key.x / Tile::SIZE));
const int KY = static_cast<int>(std::round(key.y / Tile::SIZE));
out << " position: {x: " << KX << ", y: " << KY << "}\n";
out << "\n";
}
}
// --- Puertas ---
if (!room_data.doors.empty()) {
out << "# Puertas en esta habitación\n";
out << "doors:\n";
for (const auto& door : room_data.doors) {
out << " - animation: " << door.animation_path << "\n";
out << " id: \"" << door.id << "\"\n";
int dx = static_cast<int>(std::round(door.x / Tile::SIZE));
int dy = static_cast<int>(std::round(door.y / Tile::SIZE));
out << " position: {x: " << dx << ", y: " << dy << "}\n";
out << "\n";
}
void RoomFormat::writeDoorsSection(std::ostringstream& out, const Room::Data& room_data) {
if (room_data.doors.empty()) { return; }
out << "# Puertas en esta habitación\n";
out << "doors:\n";
for (const auto& door : room_data.doors) {
out << " - animation: " << door.animation_path << "\n";
out << " id: \"" << door.id << "\"\n";
const int DX = static_cast<int>(std::round(door.x / Tile::SIZE));
const int DY = static_cast<int>(std::round(door.y / Tile::SIZE));
out << " position: {x: " << DX << ", y: " << DY << "}\n";
out << "\n";
}
}
auto RoomFormat::buildContent(const Room::Data& room_data) -> std::string {
std::ostringstream out;
writeRoomSection(out, room_data);
writeTilemapSection(out, room_data);
writeEnemiesSection(out, room_data);
writeItemsSection(out, room_data);
writePlatformsSection(out, room_data);
writeKeysSection(out, room_data);
writeDoorsSection(out, room_data);
return out.str();
}
+10 -2
View File
@@ -1,7 +1,8 @@
#pragma once
#include <string> // Para string
#include <vector> // Para vector
#include <sstream> // Para ostringstream
#include <string> // Para string
#include <vector> // Para vector
#include "external/fkyaml_node.hpp" // Para fkyaml::node
#include "game/entities/door.hpp" // Para Door::Data
@@ -90,5 +91,12 @@ class RoomFormat {
// --- Serialization helpers (solo en debug, los usa saveYAML) ---
static auto buildContent(const Room::Data& room_data) -> std::string;
static auto roomConnectionToYAML(const std::string& connection) -> std::string;
static void writeRoomSection(std::ostringstream& out, const Room::Data& room_data);
static void writeTilemapSection(std::ostringstream& out, const Room::Data& room_data);
static void writeEnemiesSection(std::ostringstream& out, const Room::Data& room_data);
static void writeItemsSection(std::ostringstream& out, const Room::Data& room_data);
static void writePlatformsSection(std::ostringstream& out, const Room::Data& room_data);
static void writeKeysSection(std::ostringstream& out, const Room::Data& room_data);
static void writeDoorsSection(std::ostringstream& out, const Room::Data& room_data);
#endif
};