#include "game/entities/concrete/hole.hpp" #include #include #include "game/entities/entity_factory.hpp" #include "game/entities/player.hpp" Hole::Hole(const fkyaml::node& yaml) { name_ = yaml.contains("name") ? yaml["name"].get_value() : std::string("hole"); // Sense xoc físic ni interacció — només trigger d'àrea. El bucle de // contacte ens admet via `triggers_on_overlap_=true`. Damage queda a // 0 (no publiquem `player_hit`); la mort la dispara `integrateJump` // del jugador quan supera `HOLE_FALL_DEPTH`. collides_ = false; interactable_ = false; triggers_on_overlap_ = true; // Decal de sòl: `Entity::getFeetY()` torna sentinel mínim si aquest // flag està actiu — així el forat es pinta abans que qualsevol actor. is_floor_decal_ = true; setDamage(0); } void Hole::onPlayerContact(Player* player) { if (player == nullptr) { return; } // Només mossega quan el jugador trepitja el forat de peu (GROUNDED). // En l'aire, el filtre d'altura del bucle ja l'ha rebutjat (height_=0 // i jump_z_>0 prou per superar-ho); però mantenim el gat per defensa // davant de futurs canvis al filtre. if (player->getState() != Player::State::GROUNDED) { return; } // Re-verificació estricta: la hit-box interna del jugador (8×8) ha // d'estar COMPLETAMENT continguda dins del rect del forat (16×16). El // bucle de col·lisió del manager ja ens ha cridat per qualsevol solape; // ací filtrem perquè la caiguda només es dispari quan els "dos peus" // estan dins del forat, no quan només la vora frega — sinó es percep // com un imant que succiona el jugador al centre. const SDL_FRect HIT = player->getHitBox(); const SDL_FRect BOX = getCollisionRect(); const bool CONTAINED = HIT.x >= BOX.x && HIT.y >= BOX.y && HIT.x + HIT.w <= BOX.x + BOX.w && HIT.y + HIT.h <= BOX.y + BOX.h; if (!CONTAINED) { return; } // Snap al centre XY del forat + Y de la base del tile (per al clip // rect del sprite mentre cau). `enterHoleFall` rep coordenades // absolutes en el canvas — el player s'encarrega de convertir a la // seua convenció (cantó superior-esquerra del sprite). const float CENTER_X = BOX.x + (BOX.w * 0.5F); const float CENTER_Y = BOX.y + (BOX.h * 0.5F); const float FLOOR_Y = BOX.y + BOX.h; player->enterHoleFall(CENTER_X, CENTER_Y, FLOOR_Y); } REGISTER_ENTITY("hole", Hole)