feat(editor): col·locació d'entitats amb snap per tipus i bloqueig de solapaments

This commit is contained in:
JailDesigner committed 2026-05-02 11:21:05 +02:00
1 parent 94213f9fd6
commit 9b09ccb765
5 files changed
+165 -38

No files matched your search

+10
View File
@@ -7,6 +7,7 @@
#include <string>
#include <vector>
#include "external/fkyaml_node.hpp"
#include "game/entities/event_bus.hpp"
class Entity;
@@ -102,6 +103,15 @@ class EntityManager {
// `Map::tile_size`, `tilemap_origin_*` i `getSarcRect`).
void loadFromLevel(const std::string& level_yaml_path);
// Crea i afegeix una entitat a partir d'un node spawn (mateix format
// que els items del bloc `entities:` del YAML del nivell). Retorna el
// punter observacional a l'entitat creada, o `nullptr` si la plantilla
// no es pot carregar, el tipus no està registrat o el spawn no té els
// camps requerits (`position`, `sarc_position`, etc. segons el tipus).
// Pensat per al editor de Debug: construeix un node sintètic des
// d'una posició del cursor i el passa.
auto addSpawn(const fkyaml::node& spawn) -> Entity*;
// Reset complet del nivell: destrueix totes les entitats, reseteja
// els comptadors interns (sarcòfags oberts, total, exited, flag de
// level_complete) i torna a cridar `loadFromLevel` per regenerar les
@@ -395,30 +395,31 @@ void EntityManager::reload(const std::string& level_yaml_path) {
loadFromLevel(level_yaml_path);
}
auto EntityManager::addSpawn(const fkyaml::node& spawn) -> Entity* {
if (!spawn.contains("type")) { return nullptr; }
const auto TYPE = spawn["type"].get_value<std::string>();
SpriteInfo sprite;
std::string anchor;
auto entity = buildEntity(TYPE, sprite, anchor);
if (entity == nullptr) { return nullptr; }
Entity* observer = entity.get();
bool ok = false;
if (TYPE == "sarcophagus") {
ok = placeSarcophagus(*this, std::move(entity), sprite, spawn);
} else if (TYPE == "door") {
ok = placeDoor(*this, std::move(entity), sprite);
} else {
ok = placeGeneric(*this, std::move(entity), TYPE, sprite, anchor, spawn);
}
return ok ? observer : nullptr;
}
void EntityManager::loadFromLevel(const std::string& level_yaml_path) {
const auto SPAWNS = EntityLoader::readSpawns(level_yaml_path);
int loaded = 0;
for (const auto& spawn : SPAWNS) {
if (!spawn.contains("type")) { continue; }
const auto TYPE = spawn["type"].get_value<std::string>();
SpriteInfo sprite;
std::string anchor;
auto entity = buildEntity(TYPE, sprite, anchor);
if (entity == nullptr) { continue; }
bool ok = false;
if (TYPE == "sarcophagus") {
ok = placeSarcophagus(*this, std::move(entity), sprite, spawn);
} else if (TYPE == "door") {
ok = placeDoor(*this, std::move(entity), sprite);
} else {
ok = placeGeneric(*this, std::move(entity), TYPE, sprite, anchor, spawn);
}
const bool OK = ok;
if (OK) { ++loaded; }
}
const int LOADED = static_cast<int>(std::ranges::count_if(SPAWNS,
[this](const fkyaml::node& spawn) { return addSpawn(spawn) != nullptr; }));
// Broadcast inicial: marca com a "pintats" tots els tiles ocupats per
// decals de sòl (Hole, i futurs pinchos plans, plaques, charcos...).
@@ -446,6 +447,6 @@ void EntityManager::loadFromLevel(const std::string& level_yaml_path) {
<< " tile_painted broadcast inicial (decals de sòl)\n";
}
std::cout << "EntityManager: " << loaded << " entitats carregades des de "
std::cout << "EntityManager: " << LOADED << " entitats carregades des de "
<< level_yaml_path << '\n';
}