refactor(em): un sol vector entities_ — polimorfisme per la
discriminació
Reverteix la separació en sacs introduïda al commit 62f4b85 (rama
anterior). Amb els virtuals afegits al commit precedent
(`onWhipHit`, `onJustSpawned`, `shouldReceiveContact`, `onRemoved`),
ja no cal separar `map_entities_` i `actors_`: cada entitat decideix
internament què fa, el manager itera un sol vector i confia en el
dispatch virtual.
Canvis:
- `entities_` torna a ser el contenidor únic. Es desfà el dispatch
`dynamic_cast<DynamicHazard*>` que `add()` feia per enrutar.
- `addSarcophagus`, `removeEntity`, `update`, `notifyPlayerTilePainted`,
`findFloorTriggerAt`, `renderAll`, `reload` simplificats: un sol
bucle, sense distingir categories.
- `checkPlayerCollisions` només recorre `entities_` cridant
`shouldReceiveContact` polimòrfic — la lògica de "saltar SPAWN"
viu a `DynamicHazard::shouldReceiveContact`.
- `getMapEntities()` i `getActors()` desapareixen. Es manté
`getEntities()` com a accessor únic.
- `WhipAttack::applyDamage` itera `getEntities()` cridant `onWhipHit`
polimòrfic. Les entitats no-whippables retornen false (cost: una
crida virtual buida) i el callsite no discrimina tipus.
- `GameScene::render` mergeja entities + players (dos transforms en
comptes de tres) per al z-order.
`pending_actors_` es manté: és un concepte ortogonal — entitats que
encara no s'han instanciat al món fins que GameScene les "spawneja"
al text-exit de ROOM_INTRO.
Beneficis del nou disseny:
- Cap dynamic_cast dispers per a la lògica de joc (només queden els
inevitables: validació de factory i ruteig de la Door).
- Afegir un nou enemic implica `class X : public DynamicHazard` i
override dels virtuals rellevants — res al manager.
- Si un sarc, antorxa, o decoració futura volgués reaccionar al
fueteig (trencar-se, encendre's), basta amb un `onWhipHit` override
i no cal tocar `WhipAttack::applyDamage`.
This commit is contained in:
1 parent
28ff425c89
commit
a29ea641ab
5 files changed
+61
-118
No files matched your search
@@ -1793,18 +1793,12 @@ void GameScene::render() {
|
||||
};
|
||||
std::vector<Renderable> order;
|
||||
order.reserve(entity_manager_.entityCount() + players_.size());
|
||||
// Mergem els dos sacs (map + actors) i els jugadors en un sol
|
||||
// vector temporal — el `stable_sort` per `feet_y` posterior fa el
|
||||
// z-order interleaving entre els tres orígens sense importar el
|
||||
// sac d'on venen.
|
||||
const auto MAP = entity_manager_.getMapEntities();
|
||||
std::ranges::transform(MAP, std::back_inserter(order), [](Entity* e) {
|
||||
// Mergem entitats i jugadors en un sol vector temporal — el
|
||||
// `stable_sort` per `feet_y` posterior fa el z-order interleaving.
|
||||
const auto ENTITIES = entity_manager_.getEntities();
|
||||
std::ranges::transform(ENTITIES, std::back_inserter(order), [](Entity* e) {
|
||||
return Renderable{.feet_y = e->getFeetY(), .entity = e, .player = nullptr};
|
||||
});
|
||||
const auto ACTORS = entity_manager_.getActors();
|
||||
std::ranges::transform(ACTORS, std::back_inserter(order), [](DynamicHazard* a) -> Renderable {
|
||||
return Renderable{.feet_y = a->getFeetY(), .entity = a, .player = nullptr};
|
||||
});
|
||||
// Tots els jugadors entren al z-sort. Els fora de joc fan no-op a
|
||||
// `render()`; els actius (inclosos AIRBORNE durant l'spawn aeri)
|
||||
// es pinten amb el seu feet_y normal. La sombra que afecta la
|
||||
|
||||
Reference in new issue
Block a user