diff --git a/source/game/entities/player.cpp b/source/game/entities/player.cpp index a1ba91a..dc8b54a 100644 --- a/source/game/entities/player.cpp +++ b/source/game/entities/player.cpp @@ -256,6 +256,11 @@ auto Player::collidesWithWorld(const SDL_FRect& box) const -> bool { } void Player::tick(float delta_time) { + // 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 + // a governar-se per la velocitat real sense estat romanent. + being_pushed_ = false; // Via `InputState` en lloc de `SDL_GetKeyboardState` directe: quan el // service menu (o qualsevol UI modal) està obert, el wrapper retorna // un buffer tot-a-zero perquè el jugador no es mogui mentre l'usuari @@ -318,7 +323,10 @@ void Player::applyMovement(float delta_time) { clampToPlayfield(); const bool MOVED = (getPosX() != FRAME_START_X) || (getPosY() != FRAME_START_Y); - const bool ANIM_AS_MOVING = MOVED && (turning_remaining_ms_ <= 0.0F); + // `being_pushed_` força `stand_*`: el jugador es desplaça sense input, + // animar-lo com a caminant faria creure que està caminant quan de + // fet és arrossegat per l'altre. + const bool ANIM_AS_MOVING = MOVED && (turning_remaining_ms_ <= 0.0F) && !being_pushed_; setCurrentAnimation(animationName(ANIM_AS_MOVING)); // Detecció de canvi de tile. Es calcula *després* del clamp i de les diff --git a/source/game/entities/player.hpp b/source/game/entities/player.hpp index 00de35b..4c17985 100644 --- a/source/game/entities/player.hpp +++ b/source/game/entities/player.hpp @@ -87,6 +87,14 @@ class Player : public AnimatedSprite { // contra mur) s'emparen automàticament. void setOtherPlayers(const std::vector* all) { all_players_ = all; } + // Marcat pel resolver jugador↔jugador quan aquest frame el jugador + // és arrossegat per una empenta (no té input propi; es desplaça + // perquè l'altre l'empeny). Determina que l'animació del frame siga + // `stand_*` encara que la posició canvie. El flag es reseteja a + // l'inici de cada `tick`, així que el resolver l'ha de tornar a + // posar cada frame que el push s'haja de mantenir. + void setBeingPushed(bool pushed) { being_pushed_ = pushed; } + // Y de la base del jugador (cara inferior de la caixa de colisió). Usada // per al Z-order contra els sarcs: peus per sobre d'un sarc → darrere; // per sota → davant. @@ -162,6 +170,11 @@ class Player : public AnimatedSprite { // Punter a la llista de tots els jugadors del nivell (propietat del // GameScene). `nullptr` = jugador aïllat, sense col·lisió inter-P. const std::vector* all_players_{nullptr}; + + // Frame actual el jugador està sent empentat (no té input propi). + // Serveix només per a l'elecció d'animació — la posició ja la + // gestiona `intended_vx_/vy_` escalats pel resolver. + bool being_pushed_{false}; // Còpia plana de la geometria del mapa + punters a `collides`/ // `inside_playfield`. POD trivial; copiada al ctor i no muta durant // la vida del Player. Vol dir que aquest Player només és vàlid per diff --git a/source/game/scenes/game_scene.cpp b/source/game/scenes/game_scene.cpp index 363dd49..629c9b8 100644 --- a/source/game/scenes/game_scene.cpp +++ b/source/game/scenes/game_scene.cpp @@ -130,6 +130,9 @@ namespace { const float VY = pusher->getIntendedVY() * push_factor; pusher->setIntendedVelocity(VX, VY); pushed->setIntendedVelocity(VX, VY); + // El pushed es mourà sense input propi: marquem-ho perquè + // `applyMovement` no active la variant `walk` de l'animació. + pushed->setBeingPushed(true); } // Ordre d'`applyMovement`: en push, el pushed ha de moure's abans