refactor(entities): rename notifyTileEntered → notifyTilePainted i escolta tile_painted

This commit is contained in:
JailDesigner committed 2026-04-23 13:22:02 +02:00
1 parent 0f56ce7567
commit e3cf2eb773
7 files changed
+33 -28

No files matched your search

@@ -112,7 +112,7 @@ void Sarcophagus::update(float delta_time) {
}
}
void Sarcophagus::notifyTileEntered(int col, int row) {
void Sarcophagus::notifyTilePainted(int col, int row) {
if (state_ != State::CLOSED) { return; }
const TileKey KEY{.col = col, .row = row};
if (perimeter_tiles_.find(KEY) == perimeter_tiles_.end()) { return; }
@@ -42,7 +42,7 @@ class Sarcophagus : public Interactable {
void place(int anchor_col, int anchor_row, const BlockedPredicate& is_blocked);
void update(float delta_time) override;
void notifyTileEntered(int col, int row) override;
void notifyTilePainted(int col, int row) override;
[[nodiscard]] auto getState() const -> State { return state_; }
[[nodiscard]] auto getPerimeterSize() const -> std::size_t { return perimeter_tiles_.size(); }
+1 -1
View File
@@ -23,7 +23,7 @@ void Entity::onPlayerContact(Player* /*player*/) {
// No-op per defecte.
}
void Entity::notifyTileEntered(int /*col*/, int /*row*/) {
void Entity::notifyTilePainted(int /*col*/, int /*row*/) {
// No-op per defecte; només `Sarcophagus` l'usa.
}
+4 -3
View File
@@ -77,9 +77,10 @@ class Entity {
virtual void onPlayerContact(Player* player);
// Hook que el `EntityManager` invoca per a cada entitat cada vegada
// que el jugador entra en un tile nou. Només `Sarcophagus` ho consumeix
// (per marcar perímetre visitat); per defecte no-op.
virtual void notifyTileEntered(int col, int row);
// que un tile es pinta (via PaintLayer, com a conseqüència d'un
// jugador trepitjant un sòl pintable). Només `Sarcophagus` ho consumeix
// (per marcar perímetre); per defecte no-op.
virtual void notifyTilePainted(int col, int row);
[[nodiscard]] auto getName() const -> const std::string& { return name_; }
[[nodiscard]] auto getTilePos() const -> TilePos { return tile_; }
+8 -7
View File
@@ -24,12 +24,13 @@ EntityManager::EntityManager() {
}
});
// Subscripció al moviment del jugador: quan publica `on_tile_entered`
// amb payload `TilePos`, fem fan-out a totes les entitats perquè els
// sarcòfags puguin actualitzar el seu `visited_`.
tile_sub_id_ = bus_.subscribe("on_tile_entered", [this](const Event& ev) {
// Subscripció al pintat: el PaintLayer publica `tile_painted` amb
// payload `TilePos` un cop ha filtrat pintabilitat i aplicat la regla
// "primer que pinta guanya". Fem fan-out a totes les entitats perquè
// els sarcòfags puguin actualitzar el seu `visited_`.
tile_sub_id_ = bus_.subscribe("tile_painted", [this](const Event& ev) {
const auto* tile = std::get_if<TilePos>(&ev.payload);
if (tile != nullptr) { notifyPlayerEnteredTile(tile->col, tile->row); }
if (tile != nullptr) { notifyPlayerTilePainted(tile->col, tile->row); }
});
}
@@ -66,8 +67,8 @@ void EntityManager::update(float delta_time) {
for (auto& e : entities_) { e->update(delta_time); }
}
void EntityManager::notifyPlayerEnteredTile(int col, int row) {
for (auto& e : entities_) { e->notifyTileEntered(col, row); }
void EntityManager::notifyPlayerTilePainted(int col, int row) {
for (auto& e : entities_) { e->notifyTilePainted(col, row); }
}
auto EntityManager::getEntities() const -> std::vector<Entity*> {
+7 -6
View File
@@ -17,9 +17,9 @@ class Player;
// 2. `update(dt)` propaga el tick a totes.
// 3. Comptador de sarcòfags oberts — quan iguala el total registrat,
// crida `door_->open()` automàticament.
// 4. `notifyPlayerEnteredTile(col, row)` — fan-out del hook per a tots
// 4. `notifyPlayerTilePainted(col, row)` — fan-out del hook per a tots
// els sarcòfags (i qualsevol entitat futura que s'hi subscrigui via
// `notifyTileEntered`).
// `notifyTilePainted`).
//
// NO és un singleton: es crea una instància per nivell. De moment no
// s'usa encara al GameScene (andamiatge pur).
@@ -74,10 +74,11 @@ class EntityManager {
// reflecteixi l'estat del frame actual.
void checkPlayerCollisions(const std::vector<Player*>& players);
// Fan-out del hook de moviment de jugador: per a cada sarcòfag,
// cridar notifyTileEntered. Les entitats no-sarcòfag ho ignoren per
// defecte (veure Entity::notifyTileEntered).
void notifyPlayerEnteredTile(int col, int row);
// Fan-out del hook de pintat: per a cada sarcòfag, cridar
// notifyTilePainted. Les entitats no-sarcòfag ho ignoren per defecte
// (veure Entity::notifyTilePainted). Invocat com a reacció a
// `tile_painted` al bus (re-publicat pel PaintLayer un cop filtrat).
void notifyPlayerTilePainted(int col, int row);
// Carrega els spawns d'un YAML de nivell i els afegeix al manager:
// 1. Llegeix el bloc `entities:` via EntityLoader.
+11 -9
View File
@@ -4,7 +4,7 @@
// T1 factory — tots els tipus es registren i es creen.
// T2 loader — llegeix `data/maps/test_entities.yaml` i retorna els spawns.
// T3 event bus — subscribe + publish + payload (entity*, int).
// T4 sarcòfag — perímetre computat correctament; notifyTileEntered
// T4 sarcòfag — perímetre computat correctament; notifyTilePainted
// passa a OPENING quan es visiten tots els tiles.
// T5 manager — 2 sarcs + 1 door: forçant l'obertura dels sarcs, la porta
// s'obri sola; contactar la porta OPEN emet `level_complete`.
@@ -138,14 +138,14 @@ namespace {
REQUIRE(sarc->getState() == Sarcophagus::State::CLOSED);
// Visitem un tile que NO és al perímetre: res canvia.
sarc->notifyTileEntered(5, 5);
sarc->notifyTilePainted(5, 5);
REQUIRE(sarc->getVisitedCount() == 0);
// Visitem tots els del perímetre.
const std::vector<std::pair<int, int>> PERIM = {
{1, 0}, {2, 0}, {3, 0}, {1, 2}, {2, 2}, {3, 2}, {0, 1}, {4, 1},
};
for (const auto& [c, r] : PERIM) { sarc->notifyTileEntered(c, r); }
for (const auto& [c, r] : PERIM) { sarc->notifyTilePainted(c, r); }
REQUIRE(sarc->getVisitedCount() == 8);
REQUIRE(sarc->getState() == Sarcophagus::State::OPENING);
@@ -186,12 +186,12 @@ namespace {
const int W = s->getTileWidth();
const int H = s->getTileHeight();
for (int dc = 0; dc < W; ++dc) {
s->notifyTileEntered(COL0 + dc, ROW0 - 1);
s->notifyTileEntered(COL0 + dc, ROW0 + H);
s->notifyTilePainted(COL0 + dc, ROW0 - 1);
s->notifyTilePainted(COL0 + dc, ROW0 + H);
}
for (int dr = 0; dr < H; ++dr) {
s->notifyTileEntered(COL0 - 1, ROW0 + dr);
s->notifyTileEntered(COL0 + W, ROW0 + dr);
s->notifyTilePainted(COL0 - 1, ROW0 + dr);
s->notifyTilePainted(COL0 + W, ROW0 + dr);
}
};
forceOpen(s1);
@@ -310,7 +310,9 @@ namespace {
REQUIRE(ANCHOR_ROW == 4);
// 4) Fan-out del bus: un sarcòfag ancorat a (3,4) mida 3×1 rep via
// on_tile_entered una visita sobre el seu perímetre → state canvia.
// tile_painted una notificació sobre cada tile del seu perímetre
// → state canvia. Publiquem directament `tile_painted` (sense
// passar pel PaintLayer) per aïllar el fan-out de l'EntityManager.
EntityManager manager;
auto sarc = std::make_unique<Sarcophagus>(EntityLoader::loadTemplate("sarcophagus"));
sarc->place(3, 4, {});
@@ -323,7 +325,7 @@ namespace {
{2, 4}, {6, 4},
};
for (const auto& [c, r] : PERIM) {
manager.getBus().publish("on_tile_entered", TilePos{.col = c, .row = r});
manager.getBus().publish("tile_painted", TilePos{.col = c, .row = r});
}
REQUIRE(sarc_raw->getState() == Sarcophagus::State::OPENING);
}