feat(player): hit-box 8×8 per a contacte actor-actor (player, momia, trampa)

This commit is contained in:
JailDesigner committed 2026-04-24 19:23:30 +02:00
1 parent 511f8d5b09
commit 858e444842
6 files changed
+84 -8

No files matched your search

+38 -3
View File
@@ -77,6 +77,14 @@ void Player::loadFrom(const std::string& yaml_path) {
collision_x_offset = -collision_padding;
collision_y_offset = (sprite_h - base_size) - collision_padding;
// Hit-box opcional (actor-actor). Si no hi és, s'iguala a la base
// per preservar compatibilitat amb YAMLs antics. Concèntrica amb la
// caixa de col·lisió: offset interior = (collision_size - hit_size) / 2.
hit_size = c.contains("hit_size") ? c["hit_size"].get_value<int>() : collision_size;
const int HIT_INSET = (collision_size - hit_size) / 2;
hit_x_offset = collision_x_offset + HIT_INSET;
hit_y_offset = collision_y_offset + HIT_INSET;
// Bloc opcional `turn:` — si manca, `duration_ms` queda a 0 i la
// mecànica del gir de 180° no s'activa (canvis de direcció instantanis).
turn_config = TurnConfig{};
@@ -248,10 +256,16 @@ void Player::update(float delta_time) {
auto Player::collidesWithWorld(const SDL_FRect& box) const -> bool {
if (map_.collides(box)) { return true; }
if (all_players_ == nullptr) { return false; }
return std::ranges::any_of(*all_players_, [this, &box](const Player* p) {
// Per al contacte actor-actor usem la hit-box petita a banda i banda:
// projectem la hit-box des de la posició base proposada i la comparem
// amb la hit-box actual de l'altre jugador. Així la caixa de moviment
// (16×16) segueix topant amb murs/sarcs però els jugadors poden
// acostar-se fins al contacte real.
const SDL_FRect PROPOSED_HIT = hitBoxFromBase(box);
return std::ranges::any_of(*all_players_, [this, &PROPOSED_HIT](const Player* p) {
if (p == nullptr || p == this) { return false; }
const auto OTHER = p->getBaseBox();
return SDL_HasRectIntersectionFloat(&box, &OTHER);
const auto OTHER = p->getHitBox();
return SDL_HasRectIntersectionFloat(&PROPOSED_HIT, &OTHER);
});
}
@@ -397,6 +411,27 @@ auto Player::getBaseBox() const -> SDL_FRect {
};
}
auto Player::getHitBox() const -> SDL_FRect {
return {
.x = getPosX() + static_cast<float>(hit_x_offset),
.y = getPosY() + static_cast<float>(hit_y_offset),
.w = static_cast<float>(hit_size),
.h = static_cast<float>(hit_size),
};
}
auto Player::hitBoxFromBase(const SDL_FRect& base) -> SDL_FRect {
// Desplaçament intern respecte al cantó de la caixa base: mateixos
// offsets que `getHitBox()` però partint d'una caixa arbitrària.
const int INSET = (collision_size - hit_size) / 2;
return {
.x = base.x + static_cast<float>(INSET),
.y = base.y + static_cast<float>(INSET),
.w = static_cast<float>(hit_size),
.h = static_cast<float>(hit_size),
};
}
void Player::snapToLane(
float delta_time,
float base,