Files
aee-arcade/docs/player-animations.md
T
JailDesignerandClaude Opus 4.7 b19a6e25da docs(audit-game): close refactor/options-class — final commit log
- Registre de commits omplert amb els hashes reals dels 3 commits de la
  rama (a3b03b8 / 64e0178 / d9f6fb4).
- player-animations.md: el recompte de smoke tests deia "14/14" però
  `tests/test_entities_smoke.cpp` només invoca 13 funcions `test*` des
  de `main()`. Nota corregida a "13/13" amb explicació.

Tanca els 4 ítems DEFERRED de `audit/game` (COUP-02, COUP-03,
CONV-02 part Options, PATCH-01).

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

81 lines
3.7 KiB
Markdown

# 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. `AnimatedSprite::update` integra la velocitat; la col·lisió
eix-separada reverteix cada eix si `Map::collides(baseBox())`.
4. 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_`.
5. 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`.