feat(player): resol el solapament en aterrar damunt d'un altre jugador
This commit is contained in:
1 parent
a64f33fe43
commit
c4caa9021e
2 files changed
+82
-2
No files matched your search
@@ -502,12 +502,81 @@ auto Player::integrateJump(float delta_time) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Player::resolveLandingOverlap() {
|
||||
if (all_players_ == nullptr) { return; }
|
||||
for (Player* other : *all_players_) {
|
||||
if (other == nullptr || other == this) { continue; }
|
||||
const SDL_FRect MY_HIT = getHitBox();
|
||||
const SDL_FRect OT_HIT = other->getHitBox();
|
||||
SDL_FRect inter;
|
||||
if (!SDL_GetRectIntersectionFloat(&MY_HIT, &OT_HIT, &inter)) { continue; }
|
||||
|
||||
// Eix de separació: el que té els centres més separats. És
|
||||
// l'axis-aligned MTV "natural" — equivalent a empentar l'altre
|
||||
// cap a fora seguint la direcció centre→centre, projectada al
|
||||
// costat dominant. Coincideix amb la intuïció: si el saltador
|
||||
// li cau una mica per sobre i a la dreta, l'altre va cap a la
|
||||
// dreta-baix; si li cau directament al damunt (dx≈0), l'altre
|
||||
// s'aparta verticalment.
|
||||
const float MCX = MY_HIT.x + (MY_HIT.w * 0.5F);
|
||||
const float MCY = MY_HIT.y + (MY_HIT.h * 0.5F);
|
||||
const float OCX = OT_HIT.x + (OT_HIT.w * 0.5F);
|
||||
const float OCY = OT_HIT.y + (OT_HIT.h * 0.5F);
|
||||
const float DX = OCX - MCX;
|
||||
const float DY = OCY - MCY;
|
||||
float push_x = 0.0F;
|
||||
float push_y = 0.0F;
|
||||
if (std::fabs(DX) >= std::fabs(DY)) {
|
||||
push_x = (DX >= 0.0F ? 1.0F : -1.0F) * inter.w;
|
||||
} else {
|
||||
push_y = (DY >= 0.0F ? 1.0F : -1.0F) * inter.h;
|
||||
}
|
||||
|
||||
// 1r intent: empentar l'altre. Si la nova posició no col·lisiona
|
||||
// amb res (mur, sarc, tercer jugador), commit i marquem-lo com
|
||||
// a empentat per coherència de l'animació de l'altre frame.
|
||||
const float OSX = other->getPosX();
|
||||
const float OSY = other->getPosY();
|
||||
other->setPosX(OSX + push_x);
|
||||
other->setPosY(OSY + push_y);
|
||||
if (!other->collidesWithWorld(other->getBaseBox())) {
|
||||
other->setBeingPushed(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
// L'altre xocaria amb un mur: revertim i provem d'apartar el
|
||||
// saltador cap al sentit oposat. Així respectem la regla "mai
|
||||
// ficar ningú dins d'un mur": si no hi ha camí per a l'altre,
|
||||
// qui es desplaça és el qui ha triat saltar.
|
||||
other->setPosX(OSX);
|
||||
other->setPosY(OSY);
|
||||
const float MSX = getPosX();
|
||||
const float MSY = getPosY();
|
||||
setPosX(MSX - push_x);
|
||||
setPosY(MSY - push_y);
|
||||
if (!collidesWithWorld(getBaseBox())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cap dels dos pot apartar-se sense xocar amb un mur. Cas
|
||||
// degenerat (jugador encaixonat entre obstacles); el deixem com
|
||||
// estava i acceptem el solapament residual fins al pròxim frame
|
||||
// amb input.
|
||||
setPosX(MSX);
|
||||
setPosY(MSY);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::applyMovement(float delta_time) {
|
||||
// Integració del salt: si estem AIRBORNE, avança jump_z_/jump_vz_.
|
||||
// El facing i intended_v* es mantenen del moment del despegue (no es
|
||||
// recalculen). Si toquem el sòl aquest frame, transicionem a
|
||||
// LANDING_STUN ja al final d'`integrateJump`.
|
||||
integrateJump(delta_time);
|
||||
// LANDING_STUN i resolem el possible solapament amb un altre
|
||||
// jugador que estigués sota — apartem-lo (o, si no es pot, ens
|
||||
// apartem nosaltres).
|
||||
if (integrateJump(delta_time)) {
|
||||
resolveLandingOverlap();
|
||||
}
|
||||
|
||||
// En LANDING_STUN no movem el jugador horitzontalment (la velocitat
|
||||
// ja s'ha posat a 0 al `tick`). Encara així animem (per estar al
|
||||
|
||||
Reference in new issue
Block a user