feat(collisions): filtre per altura — saltar esquiva momies, roques i altres jugadors

This commit is contained in:
JailDesigner committed 2026-04-25 11:49:48 +02:00
1 parent 7b09a076b2
commit cd50626b88
11 files changed
+88 -1

No files matched your search

@@ -63,8 +63,15 @@ void EntityManager::checkPlayerCollisions(const std::vector<Player*>& players) {
for (const auto& entity : entities_) {
if (!entity->collides()) { continue; }
const auto BOX = entity->getCollisionRect();
const int E_HEIGHT = entity->getHeight();
for (auto* p : players) {
if (p == nullptr) { continue; }
// Filtre per altura: si el jugador està en l'aire i està per
// damunt de l'alçada del cos de l'entitat, no hi ha contacte.
// És el mecanisme del salt per esquivar momies, roques, etc.
// Quan height és 0 (entitat sense altura declarada), el filtre
// no es dispara mai i la col·lisió funciona com abans.
if (p->isAirborne() && E_HEIGHT > 0 && p->getJumpZ() > static_cast<float>(E_HEIGHT)) { continue; }
// Contacte actor-actor amb hit-box petita: la caixa base
// 16×16 servia per moure (xoc amb murs), però per a l'event
// "toca una entitat" volem precisió — que la momia mate quan
@@ -109,6 +116,18 @@ namespace {
return info;
}
// Llig `collision.height` (alçada del cos en píxels) de la plantilla.
// 0 si no està declarada — ho usen els filtres de col·lisió per altura
// del salt: un jugador per damunt d'aquest valor no col·lisiona amb
// l'entitat. Per a obstacles "tipus mur" (sarc, porta) el YAML els
// dóna un valor molt alt per fer-los infranquejables.
auto readHeight(const fkyaml::node& tmpl) -> int {
if (!tmpl.contains("collision")) { return 0; }
const auto& c = tmpl["collision"];
if (!c.contains("height")) { return 0; }
return c["height"].get_value<int>();
}
// Bloc `collision: { size: [w, h], base_size: [bw, bh]?, offset: [x, y]? }`
// de la plantilla d'entitat.
// - Sense `base_size` ni `offset`: la caja queda alineada a la vora
@@ -212,6 +231,7 @@ namespace {
if (const auto BOX = readCollisionBox(tmpl, sprite_out.width, sprite_out.height); BOX.has_value()) {
entity->setCollisionBox(*BOX);
}
entity->setHeight(readHeight(tmpl));
anchor_out = readAnchor(tmpl);
return entity;
}