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.
This commit is contained in:
2026-06-24 20:42:35 +02:00
parent 3b72782225
commit e5c37c7c86
9 changed files with 499 additions and 352 deletions
+67 -17
View File
@@ -1,25 +1,75 @@
# Architettura di Base
## Organizzazione del Progetto
## Overview
Il progetto è strutturato in modo da separare logicamente gli asset visivi dal codice sorgente:
- `assets/`: Contiene le immagini PNG (sprite, tileset) create dagli script.
- `scripts/`: Script Python per la generazione procedurale di grafica (es. metasprite del fantasma o del game over).
- `src/`: Tutto il codice sorgente C e gli header generati.
- `build/`: Risultato della compilazione (i file `.o` e il ROM `.gb` finale).
Il progetto è un gioco completo per Game Boy (DMG/CGB) con 8 livelli di difficoltà crescente, multi-nemico, audio polifonico e finale tragico. Tutto in 32 KB di ROM e 8 KB di WRAM.
## Modularizzazione del Codice C
## Organizzazione del progetto
Inizialmente, l'intero gioco risiedeva in un unico file `engine.c` di oltre 1000 righe. Per facilitare la manutenzione, è stato rifattorizzato in moduli a singola responsabilità:
```
gameboy-hello-iso/
├── assets/ # PNG sorgenti (sprite, tileset, schermate)
├── scripts/ # Script Python per generazione/quantizzazione asset
├── src/ # Codice C + asset generati da png2asset
├── doc/ # Documentazione tecnica
├── build/ # Output compilazione (ROM .gb)
├── Makefile # Build system (GBDK lcc + png2asset)
└── README.md
```
- `maze.c`: Gestisce puramente i dati della mappa e la loro generazione.
- `sound.c`: Isola tutte le interazioni con l'hardware audio (APU).
- `render.c`: Isola l'hardware visivo (PPU), la memoria video (VRAM) e lo scrolling (SCX/SCY).
- `player_logic.c` ed `enemy_logic.c`: Contengono le regole fisiche e l'AI.
- `engine.c`: Agisce da "Direttore d'Orchestra", richiamando i vari `update` in sequenza.
## Modularizzazione del codice C
## Gestione dello Stato Globale (`globals.h`)
Il gioco nasceva da un monolite `engine.c` di 1000+ righe, poi rifattorizzato in moduli a singola responsabilità:
Un problema ricorrente nei giochi C in più moduli sono le "dipendenze circolari" (es. il render ha bisogno delle coordinate del player, ma il player ha bisogno della mappa per le collisioni).
Per risolvere questo, lo stato mutabile del gioco è centralizzato in `globals.c` ed esposto tramite `globals.h`.
Tutti i moduli includono `globals.h` e leggono/scrivono sulle variabili `extern` (come `stamina`, `game_over`, `player_lx`), evitando grovigli di include e rendendo il passaggio dei dati estremamente leggero e globale, un approccio molto comune ed efficiente nello sviluppo retro-console.
| File | Righe | Ruolo |
|------|-------|-------|
| `main.c` | ~30 | Entry point, loop VBL, macchina a stati `app_state` (0=title, 1=game). |
| `engine.c` | ~290 | "Direttore d'orchestra": `title_init/update`, `engine_init`, `engine_update`. Gestisce game over (sconfitta/vittoria/finale), schermate di transizione. |
| `globals.c/h` | ~80 | Stato globale centralizzato: mappa, camera, player, enemy (array), stamina, level, fog_radius, map_size. |
| `maze.c` | ~140 | Generazione procedurale DFS + loop + botola. |
| `player_logic.c` | ~200 | Input, DAS, state machine, camminata, corsa, salto, stamina. |
| `enemy_logic.c` | ~140 | AI greedy multi-entity, cooldown scalabile, rendering nemici, hitbox. |
| `render.c` | ~280 | Proiezione isometrica, fog of war scalabile, auto-tiling multi-pass, flush dinamico, stamina UI, level HUD, sprite player. |
| `sound.c` | ~430 | Sequencer audio via VBL: title (112 note), gameplay (96), gameover (128), finale (192, loop). |
Asset generati da `png2asset`: `tiles.c`, `player.c`, `enemy.c`, `gameover.c`, `stamina.c`, `level.c`, `claimed.c`, `title_bg.c`.
## Stato globale (`globals.h`)
Tutte le variabili mutabili sono centralizzate in `globals.c` ed esposte via `extern` in `globals.h`. Questo evita dipendenze circolari tra moduli C (render ha bisogno di player, player ha bisogno di maze, ecc.).
### Variabili chiave
| Variabile | Tipo | Descrizione |
|-----------|------|-------------|
| `app_state` | uint8_t | 0 = title, 1 = gameplay |
| `game_over` | volatile uint8_t | 0 = playing, 1 = defeat, 2 = victory/Going Deeper, 3 = finale |
| `game_over_timer` | volatile uint8_t | Delay drammatico prima della schermata di fine |
| `map_size` | uint8_t | Dimensione corrente del labirinto (7..21, cresce col livello) |
| `maze[21][21]` | uint8_t | 0 = muro, 1 = pavimento, 2 = botola |
| `fog_radius` | uint8_t | Raggio visibilità Chebyshev (2 normalmente, 1 dal livello 7) |
| `level` | uint8_t | Livello corrente (1..8) |
| `num_enemies` | uint8_t | Numero fantasmi attivi (= livello, capped 8) |
| `enemy_step_cooldown` | uint8_t | Pausa tra passi del fantasma (60..11, scala col livello) |
| `stamina_recharge_rate` | uint8_t | Frame per +1 stamina (60..144, scala col livello) |
| `stamina` | uint8_t | 0..100, potenzia salto (60) e corsa (10/tile) |
| `enemy_lx[8]` ecc. | array | Stato multi-nemico (fino a 8 fantasmi) |
## Pipeline asset (Python → C)
1. **Script Python** (`scripts/generate_assets.py`, `generate_enemy.py`, `generate_level.py`) creano i PNG sorgenti da matrici di pixel, usando la palette GB a 4 colori.
2. **`png2asset`** (tool GBDK) converte ogni PNG in `src/*.c` (tile data + map + metasprite).
3. **`lcc`** (frontend SDCC) compila e linka tutti i `.c` nella ROM finale `build/hello_iso.gb`.
Il `Makefile` orchestra questo processo: `make clean && make` rigenera tutto da zero.
## Vincoli hardware
| Risorsa | Limite | Utilizzo attuale |
|---------|--------|------------------|
| ROM | 32 KB | ~32 KB (pieno) |
| WRAM | 8 KB | ~3 KB (maze 441B + map_buffer 1KB + enemy arrays 88B + statici maze.c ~1KB + globals) |
| VRAM tile data | 384 tile (6 KB) | ~200 tile (BG + sprite condivisi) |
| OAM (sprite) | 40 sprite | ~27 (player 2 + enemies 16 + stamina 5 + HUD 3 + gameover 10) |
| Sprite/scanline | 10 | Rispettato (HUD in alto, player al centro, nemici sparsi) |
| CPU | 4.19 MHz | LERP a punto fisso, no float, no sqrt |