feat(player): hit-box 8×8 per a contacte actor-actor (player, momia, trampa)
This commit is contained in:
1 parent
511f8d5b09
commit
858e444842
6 files changed
+84
-8
No files matched your search
@@ -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,
|
||||
|
||||
Reference in new issue
Block a user