refactor(entities): rename notifyTileEntered → notifyTilePainted i escolta tile_painted
This commit is contained in:
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(); }
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
|
||||
|
||||
@@ -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_; }
|
||||
|
||||
@@ -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*> {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user