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:
+67
-17
@@ -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 |
|
||||
Reference in New Issue
Block a user