Files
ascreamfromthedark-gb/doc/gameplay.md
T
enne2 e5c37c7c86 Aggiorna e approfondisci tutta la documentazione
Riscritti tutti i file doc/ e README.md per riflettere lo stato attuale
del gioco (8 livelli, multi-nemico, corsa, finale tragico, musica
dedicata, fog scalabile, flush dinamico, claimed.png death screen, ecc.):

- index.md: nuovo indice con riferimenti ai 7 capitoli aggiornati.
- architecture.md: tabella moduli con righe, variabili chiave globals,
  pipeline asset, vincoli hardware (ROM/WRAM/VRAM/OAM).
- graphics.md: proiezione iso, fog scalabile (fog_radius), auto-tiling
  multi-pass, flush dinamico 16-righe con wrap, HUD stamina + livello.
- generation.md: DFS con stack WRAM, dimensioni crescenti 7->21, botola
  a distanza scalabile, spawn multi-nemico.
- gameplay.md: DAS, camminata, corsa, salto, stamina scalabile,
  progressione 8 livelli, schermate (death/going deeper/finale).
- ai.md: multi-entity (8 fantasmi), greedy, cooldown scalabile, hitbox,
  culling.
- audio.md: 4 canali APU, 5 tracce (title 112/3canali, gameplay 96,
  gameover 128, finale 192 loop, going deeper 96), SFX.
- AScreamFromTheDark_report.md: riscritto completamente (~200 righe),
  tutte le sezioni aggiornate, workaround storici, debiti tecnici.
- README.md: intro, caratteristiche, soundtrack, architettura, test.
2026-06-24 20:42:35 +02:00

92 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Fisica e Controlli del Giocatore
## State Machine (Grid-Based)
Il movimento è rigidamente vincolato alla griglia (stile Zelda/Pokémon). Durante `is_moving` (interpolazione LERP su 16 frame, o 8 in corsa) ogni input è ignorato. Questo garantisce movimento perfettamente allineato, senza scivolamenti diagonali.
## LERP a Punto Fisso
```c
px = start_px + ((target_px - start_px) * move_progress) >> 4; // >>4 = /16
```
Tutto a punto fisso (no float, no divisione hardware). In corsa `move_progress += 2` → il passo dura 8 frame invece di 16, ma la formula LERP `>>4` resta invariata (raggiunge il target in metà tempo).
## Delayed Auto-Shift (DAS)
Come in Tetris: il primo tocco muove subito; tenendo premuto, l'input è ignorato per `DAS_DELAY = 12` frame, poi si ripete ogni `DAS_REPEAT = 6` frame (camminata) o `DAS_REPEAT_RUN = 2` (corsa, per incatenare i tile fluidamente).
`keys_pressed = keys & ~prev_keys` rileva il fronte di salita (pressione esatta).
## Camminata
Direzione → `move_lx/move_ly` (±1 su un asse). Validazione: `maze[new_ly][new_lx] == 1 || == 2` (pavimento o botola). Se valida, `is_moving = 1`, `move_progress = 0`, start/target impostati.
## Corsa (B + direzione)
Tenendo **B** + direzione con stamina ≥ 10:
- Il passo dura **8 frame** invece di 16 (`is_running = 1`, `move_progress += 2`).
- Costo: **10 stamina per tile**.
- DAS più rapido (`DAS_REPEAT_RUN = 2`) per incatenare i tile fluidamente.
- Se stamina < 10: ripiega silenziosamente su camminata normale (0 costo).
- La corsa si riattiva da sola quando la stamina torna ≥ 10.
La stamina si ricarica di 1 punto ogni `stamina_recharge_rate` frame (60 al livello 1, 144 al livello 8 — più lenta ai livelli alti).
## Salto Evasivo (A + direzione)
A+direzione → atterraggio **2 tile** più in là. Condizioni:
1. La cella intermedia (+1) **DEVE** essere un muro (`maze == 0`).
2. La cella di arrivo (+2) deve essere pavimento o botola.
3. Stamina ≥ 60.
Costo: 60 stamina. Arco parabolico solo visivo: `y_offset = (move_progress * (16 - move_progress)) >> 2` (apice 16px a frame 8). La logica resta 2D grid-based.
## Stamina
- 100 punti massimi.
- Ricarica: 1 punto ogni `stamina_recharge_rate` frame (60..144, scala col livello).
- Salto: costa 60 (disabilita ulteriori balzi per ~1 min).
- Corsa: costa 10/tile (da pieno, ~10 tile di corsa).
- Barra UI: 5 sprite in alto a destra, conversione `stamina*40/100` → pixel.
## Progressione Livelli (8 livelli + finale)
### Transizioni
- **Titolo → gioco**: `level = 1`, `engine_init()` genera il primo labirinto.
- **Vittoria (botola) + START**: `level++`, `engine_init()` genera il livello successivo.
- **Sconfitta + START**: si ricomincia dallo **stesso livello** raggiunto (non si azzera).
- **Finale (livello 8 superato)**: `game_over = 3` invece di 2.
### Indicatore HUD
`L<n>` in alto a sinistra via 3 sprite (OAM 23-25) dall'asset `level.png` (glifi L, 0-9). Aggiornato ogni frame in `engine_update`; nascosto durante game over.
### Difficoltà scalabile (vedi anche `generation.md` e `ai.md`)
| Assi | Livello 1 | Livello 8 |
|------|-----------|-----------|
| Dimensione labirinto | 7×7 | 21×21 |
| Numero fantasmi | 1 | 8 |
| Cooldown fantasma | 60 frame | 11 frame |
| Ricarica stamina | 60 frame/pt | 144 frame/pt |
| Nebbia | 5×5 | 3×3 (dal L7) |
## Schermate di Fine Gioco
### Sconfitta (`game_over = 1`)
- 45 frame di "fermo immagine" drammatico.
- Poi: schermata `claimed.png` a tutto schermo + metasprite "GAME OVER".
- Musica: concerto tragico polifonico (128 note, noise percussion).
- START → ricomincia dallo stesso livello.
### Going Deeper (`game_over = 2`, livelli 1-7)
- 30 frame di dissolvenza.
- Schermata testuale col font IBM: "GOING DEEPER / LEVEL N".
- Musica: melodia misteriosa discendente (96 step).
- START → livello successivo.
### Finale tragico (`game_over = 3`, livello 8)
- 30 frame di dissolvenza.
- Sfondo nero (BGP invertito 0x1B), font IBM ricaricato.
- Testo: "YOUR TORCH HAS / RUN OUT, / YOU ARE TRAPPED. / JUST ANOTHER SCREAM / FROM THE DARK. / GAME OVER".
- Musica dedicata: 192 step (24 accordi), lamento discendente in Re minore che cola nell'abisso, in loop.
- START → torna al titolo (nuova partita dal livello 1).