Files
aee-arcade/docs/player-animations.md
T
JailDesignerandClaude Opus 4.7 510ab55a33 docs: actualitza estat post-refactor/options-class
- audit-game.md cabecera: contadors actualitzats (32 DONE, 1 DONE
  parcial, 5 WONTFIX, 0 DEFERRED) i frase dels DEFERRED en pretèrit
  perfecte. INCONS-01 queda com l'únic DONE (parcial), intencionalment.
- player-animations.md secció 4: el patró antic
  "AnimatedSprite::update integra + col·lisió eix-separada reverteix
  cada eix" es substitueix per "animate(dt) + tryMove(vx*dt, vy*dt,
  collidesFn) amb collisionBox() virtual" — coincidint amb el codi
  post-PATCH-01.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 09:22:38 +02:00

3.9 KiB

Animacions i direccionalitat del jugador

Documenta els afegits d'aquesta sessió a source/game/entities/player.*: sis animacions direccionals amb facing_ persistent, regla de flip només per al lateral i transició automàtica a stand quan la col·lisió bloqueja el moviment. Tot el canvi és local al Player; no s'ha tocat l'EntityManager ni el bus.

1. YAML — sis animacions

El fitxer data/player/player.yaml defineix ara sis animacions, agrupades en tres files de 4 frames sobre player.gif (convenció habitual: d'esquerra a dreta i de dalt a baix):

Nom Frames Descripció
stand_down [0] parat mirant cap avall
walk_down [0..3] caminant cap avall
stand_up [4] parat mirant cap amunt
walk_up [4..7] caminant cap amunt
stand [8] parat lateral
walk [8..11] caminant lateral

Les laterals (stand i walk) ja existien; les variants _up i _down són noves i permeten distingir visualment la direcció de moviment.

2. Facing persistent

S'ha afegit l'enum privat Facing { SIDE, UP, DOWN } amb el membre facing_{SIDE}. La tria es fa a cada update, amb prevalença lateral per si un dia es permetessin diagonals:

  • vx != 0 → SIDE (inclou diagonals).
  • vx == 0 && vy < 0 → UP.
  • vx == 0 && vy > 0 → DOWN.
  • Cap input → es conserva l'últim facing_ perquè l'animació stand_* coincideixi amb l'última direcció caminada.

3. Regla de flip

  • SIDE: el sprite es flipeja horitzontalment si vx < 0, i es restaura a FLIP_NONE si vx > 0. El sprite original mira a la dreta.
  • UP / DOWN: el flip es força explícitament a FLIP_NONE. Els sprites frontals/dorsals no s'han d'espillar només perquè l'últim lateral havia estat cap a l'esquerra.

4. stand automàtic a la col·lisió

Quan el jugador prem una tecla però la col·lisió (mapa o sarcòfag) li impedeix avançar, l'animació walk* s'atura i es força la variant stand_* corresponent al facing. L'algorisme:

  1. Al principi del frame es captura FRAME_START_X / FRAME_START_Y.
  2. S'aplica snap al passadís perpendicular si hi ha pur moviment H o V.
  3. animate(delta_time) avança el frame de l'animació actual sense tocar la posició.
  4. tryMove(vx*dt, vy*dt, collidesFn) (a MovingSprite) aplica el moviment per eix: si la collisionBox() resultant col·lisiona — el Player la sobreescriu retornant getBaseBox() —, l'eix es reverteix. Així el jugador llisca contra murs/sarcòfags en lloc de bloquejar-se en sec.
  5. Després de clampToPlayfield, es compara la posició final amb el valor capturat al pas 1. Si és idèntica, MOVED = false i es tria stand / stand_up / stand_down segons facing_. Si hi ha hagut moviment real (incloent-hi snap), s'aplica la variant walk* del mateix facing.

D'aquesta manera, xocar contra un mur o un sarcòfag fa que el jugador es quede immòbil en compte d'animar el caminat "en el lloc". El facing segueix reflectint la intenció (on vol anar), no el resultat, perquè l'stand_up d'empentar-se contra un mur ha de mostrar el personatge mirant amunt.

5. Estat

  • DONE: sis animacions al YAML, facing_ persistent, flip condicionat, stand automàtic a la col·lisió.
  • Build i smoke tests (13/13) verdes. (Aquesta nota deia "14/14" abans; el comptatge real al tests/test_entities_smoke.cpp són 13 funcions test* invocades des de main() — corregit a refactor/options-class.)
  • Sense smoke test dedicat: la lògica està entrellaçada amb teclat i Map::collides; l'smoke actual de Player no cobreix teclat simulat.
  • Pendent (ajornat): si algun dia es vol feedback auditiu de wall-bump (so en xocar), la condició natural és !MOVED && (vx != 0 || vy != 0) al final d'update.