feat(player): estat EXITED i porta oberta despawna jugadors via player_exited
This commit is contained in:
1 parent
377e5d0b97
commit
5c5cd1d5da
5 files changed
+93
-22
No files matched your search
@@ -328,6 +328,10 @@ void Player::update(float delta_time) {
|
||||
}
|
||||
|
||||
auto Player::collidesWithWorld(const SDL_FRect& box) const -> bool {
|
||||
// EXITED: jugador despawnat. No xoca amb res ni res xoca amb ell.
|
||||
// També salta jugadors EXITED del check actor↔actor més avall via
|
||||
// el filtre de `isExited` (vegeu el predicat any_of).
|
||||
if (state_ == State::EXITED) { return false; }
|
||||
if (map_.collides(box)) { return true; }
|
||||
if (all_players_ == nullptr) { return false; }
|
||||
// Per al contacte actor-actor usem la hit-box petita a banda i banda:
|
||||
@@ -353,6 +357,7 @@ auto Player::collidesWithWorld(const SDL_FRect& box) const -> bool {
|
||||
const float MY_Z = jump_z_;
|
||||
return std::ranges::any_of(*all_players_, [this, &PROPOSED_HIT, MY_AIR, MY_HURT, MY_Z](const Player* p) {
|
||||
if (p == nullptr || p == this) { return false; }
|
||||
if (p->isExited()) { return false; }
|
||||
if (MY_HURT || p->isHurt()) { return false; }
|
||||
if (MY_AIR != p->isAirborne()) { return false; }
|
||||
// Aquí els dos estats coincideixen. Si tots dos volen, el filtre
|
||||
@@ -398,7 +403,15 @@ void Player::integrateAxis(float& phys, float input, float delta_time, float mot
|
||||
}
|
||||
}
|
||||
|
||||
// Pipeline d'estats i input separats; extracció a helpers empitjoraria la
|
||||
// llegibilitat. La complexitat puja 1 per la guarda EXITED.
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
void Player::tick(float delta_time) {
|
||||
// EXITED: jugador despawnat, no fa res. Cap input, cap física, cap
|
||||
// bus event. Continua sent al vector de jugadors per simplicitat
|
||||
// (no s'esborra) però queda completament inert fins al respawn.
|
||||
if (state_ == State::EXITED) { return; }
|
||||
|
||||
// Reset per frame: el resolver del GameScene el tornarà a posar a
|
||||
// true si aquest frame hi ha push actiu. Així quan el push acaba
|
||||
// (un deixa d'empentar, l'altre comença a caminar), l'animació torna
|
||||
@@ -740,6 +753,9 @@ void Player::resolveLandingOverlap() {
|
||||
}
|
||||
|
||||
void Player::applyMovement(float delta_time) {
|
||||
// EXITED: cap moviment ni col·lisió. Idèntic al gating de `tick`.
|
||||
if (state_ == State::EXITED) { return; }
|
||||
|
||||
// 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
|
||||
@@ -859,6 +875,10 @@ void Player::publishTileEnteredIfChanged() {
|
||||
}
|
||||
|
||||
void Player::render() {
|
||||
// EXITED: invisible. La crida al render base es salta sencera; el
|
||||
// jugador no apareix al z-sort tot i seguir vivint al vector.
|
||||
if (state_ == State::EXITED) { return; }
|
||||
|
||||
// Mentre el jugador està enlaire, el sprite es desplaça visualment
|
||||
// cap amunt `jump_z_` píxels. Modifiquem `pos_.y` (la posició entera
|
||||
// de render) abans de cridar el render base, i la restaurem després
|
||||
@@ -1010,6 +1030,19 @@ void Player::clampToPlayfield() {
|
||||
setPosY(std::clamp(getPosY(), min_y, MAX_Y));
|
||||
}
|
||||
|
||||
void Player::respawn(float x, float y) {
|
||||
state_ = State::GROUNDED;
|
||||
intended_vx_ = 0.0F;
|
||||
intended_vy_ = 0.0F;
|
||||
being_pushed_ = false;
|
||||
jump_z_ = 0.0F;
|
||||
jump_vz_ = 0.0F;
|
||||
landing_stun_remaining_ms_ = 0.0F;
|
||||
turning_remaining_ms_ = 0.0F;
|
||||
setPosX(x);
|
||||
setPosY(y);
|
||||
}
|
||||
|
||||
auto Player::getBaseBox() const -> SDL_FRect {
|
||||
return {
|
||||
.x = getPosX() + static_cast<float>(collision_x_offset),
|
||||
|
||||
Reference in new issue
Block a user