55 lines
2.4 KiB
C++
55 lines
2.4 KiB
C++
#include "game/entities/concrete/hole.hpp"
|
||
|
||
#include <SDL3/SDL.h>
|
||
|
||
#include <string>
|
||
|
||
#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>() : 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)
|