RoomSaver ja no reventa els yamals

This commit is contained in:
2026-04-02 11:52:53 +02:00
parent 0e61b94848
commit 3a5b16346b
4 changed files with 214 additions and 662 deletions

View File

@@ -5,6 +5,7 @@
#include <cmath> // Para std::round
#include <fstream> // Para ifstream, ofstream, istreambuf_iterator
#include <iostream> // Para cout, cerr
#include <sstream> // Para ostringstream
#include "utils/defines.hpp" // Para Tile::SIZE
@@ -21,9 +22,144 @@ auto RoomSaver::loadYAML(const std::string& file_path) -> fkyaml::node {
return fkyaml::node::deserialize(content);
}
// Guarda el nodo YAML completo a disco
auto RoomSaver::saveYAML(const std::string& file_path, const fkyaml::node& yaml) -> std::string {
std::string content = fkyaml::node::serialize(yaml);
// Convierte una room connection al formato YAML
auto RoomSaver::roomConnectionToYAML(const std::string& connection) -> std::string {
if (connection == "0" || connection.empty()) { return "null"; }
return connection;
}
// Convierte la dirección del conveyor belt a string
auto RoomSaver::conveyorBeltToString(int direction) -> std::string {
if (direction < 0) { return "left"; }
if (direction > 0) { return "right"; }
return "none";
}
// Genera el YAML completo como texto con formato compacto
auto RoomSaver::buildYAML(const fkyaml::node& original_yaml, const Room::Data& room_data) -> std::string {
std::ostringstream out;
// --- Cabecera: nombre como comentario ---
out << "# " << room_data.name << "\n";
// --- Sección room ---
out << "room:\n";
// Escribir todos los campos name_* del YAML original (preserva name_ca, name_en, etc.)
if (original_yaml.contains("room")) {
const auto& room_node = original_yaml["room"];
for (auto it = room_node.begin(); it != room_node.end(); ++it) {
const std::string key = it.key().get_value<std::string>();
if (key.substr(0, 5) == "name_") {
out << " " << key << ": \"" << it.value().get_value<std::string>() << "\"\n";
}
}
}
out << " bgColor: " << room_data.bg_color << "\n";
out << " border: " << room_data.border_color << "\n";
out << " tileSetFile: " << room_data.tile_set_file << "\n";
// Conexiones
out << "\n";
out << " # Conexiones de la habitación (null = sin conexión)\n";
out << " connections:\n";
out << " up: " << roomConnectionToYAML(room_data.upper_room) << "\n";
out << " down: " << roomConnectionToYAML(room_data.lower_room) << "\n";
out << " left: " << roomConnectionToYAML(room_data.left_room) << "\n";
out << " right: " << roomConnectionToYAML(room_data.right_room) << "\n";
// Colores de items
out << "\n";
out << " # Colores de los objetos\n";
out << " itemColor1: " << (room_data.item_color1.empty() ? "yellow" : room_data.item_color1) << "\n";
out << " itemColor2: " << (room_data.item_color2.empty() ? "magenta" : room_data.item_color2) << "\n";
// Conveyor belt
out << "\n";
out << " # Dirección de la cinta transportadora: left, none, right\n";
out << " conveyorBelt: " << conveyorBeltToString(room_data.conveyor_belt_direction) << "\n";
// --- Tilemap (16 filas × 32 columnas, formato flow) ---
out << "\n";
out << "# Tilemap: 16 filas × 32 columnas (256×192 píxeles @ 8px/tile)\n";
out << "# Índices de tiles (-1 = vacío)\n";
out << "tilemap:\n";
constexpr int MAP_WIDTH = 32;
constexpr int MAP_HEIGHT = 16;
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;
}
if (col < MAP_WIDTH - 1) { out << ", "; }
}
out << "]\n";
}
// --- Enemigos ---
if (!room_data.enemies.empty()) {
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";
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.color.empty() && enemy.color != "white") {
out << " color: " << enemy.color << "\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";
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";
if (item.counter != 0) {
out << " counter: " << item.counter << "\n";
}
out << "\n";
}
}
return out.str();
}
// Guarda el YAML a disco
auto RoomSaver::saveYAML(const std::string& file_path, const fkyaml::node& original_yaml, const Room::Data& room_data) -> std::string {
std::string content = buildYAML(original_yaml, room_data);
std::ofstream file(file_path);
if (!file.is_open()) {
@@ -39,80 +175,4 @@ auto RoomSaver::saveYAML(const std::string& file_path, const fkyaml::node& yaml)
return "Saved " + FILE_NAME;
}
// Actualiza la posición inicial de un enemigo (pixels → tiles)
void RoomSaver::updateEnemyPosition(fkyaml::node& yaml, int index, float x, float y) {
if (!yaml.contains("enemies")) { return; }
auto& enemies = yaml["enemies"];
if (index < 0 || index >= static_cast<int>(enemies.size())) { return; }
auto& enemy = enemies[index];
int tile_x = static_cast<int>(std::round(x / Tile::SIZE));
int tile_y = static_cast<int>(std::round(y / Tile::SIZE));
if (!enemy.contains("position")) {
enemy["position"] = fkyaml::node::mapping();
}
enemy["position"]["x"] = tile_x;
enemy["position"]["y"] = tile_y;
}
// Actualiza boundary1 de un enemigo (pixels → tiles)
void RoomSaver::updateEnemyBound1(fkyaml::node& yaml, int index, int x, int y) {
if (!yaml.contains("enemies")) { return; }
auto& enemies = yaml["enemies"];
if (index < 0 || index >= static_cast<int>(enemies.size())) { return; }
auto& enemy = enemies[index];
int tile_x = x / Tile::SIZE;
int tile_y = y / Tile::SIZE;
if (!enemy.contains("boundaries")) {
enemy["boundaries"] = fkyaml::node::mapping();
}
auto& bounds = enemy["boundaries"];
if (!bounds.contains("position1")) {
bounds["position1"] = fkyaml::node::mapping();
}
bounds["position1"]["x"] = tile_x;
bounds["position1"]["y"] = tile_y;
}
// Actualiza boundary2 de un enemigo (pixels → tiles)
void RoomSaver::updateEnemyBound2(fkyaml::node& yaml, int index, int x, int y) {
if (!yaml.contains("enemies")) { return; }
auto& enemies = yaml["enemies"];
if (index < 0 || index >= static_cast<int>(enemies.size())) { return; }
auto& enemy = enemies[index];
int tile_x = x / Tile::SIZE;
int tile_y = y / Tile::SIZE;
if (!enemy.contains("boundaries")) {
enemy["boundaries"] = fkyaml::node::mapping();
}
auto& bounds = enemy["boundaries"];
if (!bounds.contains("position2")) {
bounds["position2"] = fkyaml::node::mapping();
}
bounds["position2"]["x"] = tile_x;
bounds["position2"]["y"] = tile_y;
}
// Actualiza la posición de un item (pixels → tiles)
void RoomSaver::updateItemPosition(fkyaml::node& yaml, int index, float x, float y) {
if (!yaml.contains("items")) { return; }
auto& items = yaml["items"];
if (index < 0 || index >= static_cast<int>(items.size())) { return; }
auto& item = items[index];
int tile_x = static_cast<int>(std::round(x / Tile::SIZE));
int tile_y = static_cast<int>(std::round(y / Tile::SIZE));
if (!item.contains("position")) {
item["position"] = fkyaml::node::mapping();
}
item["position"]["x"] = tile_x;
item["position"]["y"] = tile_y;
}
#endif // _DEBUG