feat(player): saltar travessa el caminant; rebot mid-aire entre dos saltadors
This commit is contained in:
1 parent
3646e6a4aa
commit
188f035333
4 files changed
+78
-32
No files matched your search
@@ -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);
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user