feat(player): saltar travessa el caminant; rebot mid-aire entre dos saltadors

This commit is contained in:
JailDesigner committed 2026-04-25 14:20:38 +02:00
1 parent 3646e6a4aa
commit 188f035333
4 files changed
+78 -32

No files matched your search

+19 -9
View File
@@ -322,17 +322,27 @@ auto Player::collidesWithWorld(const SDL_FRect& box) const -> bool {
// (16×16) segueix topant amb murs/sarcs però els jugadors poden
// acostar-se fins al contacte real.
//
// Filtre per altura: si aquest jugador (this) està en l'aire i passa
// per damunt del cos de l'altre, no hi ha col·lisió — saltar permet
// sobrevolar l'altre. `body_height` és estàtic (compartit entre
// jugadors), però per al filtre val la pena consultar-lo per actor
// perquè en el futur cada character podria tenir-ne un de propi.
// Regla de col·lisió jugador↔jugador (segons el feel triat):
// - Tots dos a terra → col·lisió normal.
// - Un en l'aire i l'altre no → SENSE col·lisió. El saltador es
// travessa net del caminant; ningú actua de "muro" durant el
// vol, ni a la pujada ni a la baixada.
// - Tots dos en l'aire → col·lisió només si els rangs verticals
// [jump_z, jump_z + body_height] solapen. Així permetem el xoc
// mid-aire quan tots dos van un contra l'altre i estan a la
// mateixa franja d'alçada.
const SDL_FRect PROPOSED_HIT = hitBoxFromBase(box);
const float Z = jump_z_;
const bool AIRBORNE = (state_ == State::AIRBORNE);
return std::ranges::any_of(*all_players_, [this, &PROPOSED_HIT, AIRBORNE, Z](const Player* p) {
const bool MY_AIR = (state_ == State::AIRBORNE);
const float MY_Z = jump_z_;
return std::ranges::any_of(*all_players_, [this, &PROPOSED_HIT, MY_AIR, MY_Z](const Player* p) {
if (p == nullptr || p == this) { return false; }
if (AIRBORNE && body_height > 0 && Z > static_cast<float>(body_height)) { return false; }
if (MY_AIR != p->isAirborne()) { return false; }
// Aquí els dos estats coincideixen. Si tots dos volen, el filtre
// per altura mira que els rangs verticals encara solapin; si no,
// estan a prou distància en Y "real" i no es toquen.
if (MY_AIR && body_height > 0 && std::fabs(MY_Z - p->jump_z_) >= static_cast<float>(body_height)) {
return false;
}
const auto OTHER = p->getHitBox();
return SDL_HasRectIntersectionFloat(&PROPOSED_HIT, &OTHER);
});