|
From: Bernardo I. <be...@de...> - 2002-03-08 13:21:44
|
Ciao a tutti,
ecco il seguito della documentazione per il progetto.
Federico, per favore stampa questa mail e COSTRINGI Alexio
a leggerla! ;-)
Come al solito, se avete domande, dubbi o idee, siete invitati
a rispondere nella mailing list.
Mi raccomando I COMMENTI e la MASSIMA PULIZIA nel codice. Queste
cose dovranno essere facili da leggere PER TUTTI.
Buon lavoro.
-------------------------------------------------------------------------
3. Fase 3: Suddivisione in moduli
---------------------------------
La seguente specifica ha lo scopo di garantire fin dall'inizio una
elevata modularita' dei sorgenti, in modo da aumentare il grado di
parallelismo nella successiva fase di sviluppo, quando il progetto
sara' portato avanti da un gruppo di circa 20 sviluppatori.
3.1. Moduli di alto livello
---------------------------
Questi moduli gestiscono la logica del gioco al livello di astrazione
piu' elevato possibile, avvalendosi dei moduli di basso livello per
implementare la maggior parte delle funzionalita' necessarie.
Ciascun modulo possiede un file header (.h) che ne definisce l'interfacci=
a
verso gli altri moduli.
main
Contiene il main() del programma che chiama le funzioni del modulo
init e, se l'inizializzazione ha avuto successo, mostra la intro del
gioco (modulo intro) e entra nel ciclo principale del programma.
Il ciclo principale (funzione mainloop()) mostra lo schermo dei titoli
(modulo title) e, in base alla selezione dell'utente, decide se
uscire (quit), avviare il gioco (modulo game), etc.
Questo modulo non ha bisogno di un proprio header perche' non viene
chiamato da nessun altro modulo.
init
Contiene una funzione init() che inizializza la SDL e chiama una
funzione init_XYZ() per ogni altro modulo che richiede ulteriori
inizializzazioni. Ciascuna funzione di inizializzazione ritorna TRUE
in caso di successo e FALSE in caso di errore. A sua volta, init()
controlla l'esito di tutte le operazioni e ritorna FALSE al main in
caso di errore.
Alla funzione init() corrisponde la funzione cleanup() [pulizia] che
libera tutte le risorse allocate durante l'inizializzazione. Questa
funzione deve essere scritta in modo da funzionare correttamente anche
se viene chiamata quando l'inizializzazione non e' terminata
intro
Questo modulo mostrera' la intro del gioco. Per adesso, e' sufficiente
una funzione vuota che ritorna immediatamente o, al limite, un'immagine
di sfondo con scritto "questa e' la intro" che viene visualizzata per
qualche secondo.
title
Schermata principale del gioco contenente un semplice menu di opzioni
(nuova partita, esci, etc.). La funzione title() ritorna al main un
codice che indica quale scelta e' stata effettuata dall'utente. Per
evitare codici numerici da mandare giu' a mente, consiglio di usare
un enum oppure po' di define (TITLE_SELECT_GAME, TITLE_SELECT_QUIT, etc=
=2E)
Come per la intro, anche in questo caso ci basta caricare un'immagine
a caso e ritornare sempre lo stesso valore.
options
schermata per le opzioni del gioco. Immagine a caso etc. etc.
game
Questo modulo contiene il loop principale del gioco, dal quale si esce
solo a fine partita. Ogni iterazione del loop principale costituisce un
frame (fotogramma) del gioco. Il modulo game mantiene una struttura dat=
i
che contiene i dati globali della partita in corso (giocatori attivi,
livello corrente, oggetti presenti sullo schermo, etc.). La maggior par=
te
del lavoro sara' svolta chiamando le funzioni dei moduli input, sprite,
music, display, etc.
inter
Questo modulo gestisce gli "intermezzi" tra uno schema ed il successivo=
=2E
level
Questo modulo gestisce i dati che descrivono ciascuno schema del gioco.
In questo momento non e' necessario decidere se questi dati sarnno lett=
i
da file esterni, calcolati algoritmicamente o memorizzati in strutture
dati.
draw
Questo modulo si occupa del ridisegno del campo di gioco (playfield).
La funzione draw() viene chiamata ad ogni frame dopo aver aggiornato
la posizione e lo stato degli oggetti visibili. Questa funzione delega
la maggior parte del lavoro ad altre funzioni di disegno specifiche per
ogni elemento del gioco (sprites, background, scritte in sovrimpression=
e,
etc.).
super
Questo modulo si occupa del ridisegno dei testi in sovrimpressione
(superimposed). Viene chiamato per ultimo ad ogni fotogramma in modo da
aggiornare sullo schermo il punteggio e le altre informazioni che devon=
o
essere visualizzate.
engine
Questo modulo mantiene i dati sugli oggetti (sprite) presenti sullo sch=
ermo
e si occupa di chiamare le routine di movimento di ciascuno di essi.
=20
sprite
Questo modulo definisce un'infrastruttura generica per gli oggetti in
movimento sullo schermo. Uno sprite e' un rettangolo di grafica dotato =
di
un'area trasparente che puo' essere disegnato e spostato sullo schermo.
Il suo aspetto e comportamento variano in funzione del tipo di oggetto
rappresentato (giocatore, nemico, sparo, etc.).
player
Oggetto che rappresenta un giocatore ed lo sprite ad esso associato. Qu=
esto
oggetto mantiene inoltre il punteggio e lo stato attuale del giocatore.
collision
Questo modulo gestisce le collisioni tra oggetti nel gioco. Le collisio=
ni
verranno calcolate solo tra gli oggetti che ne hanno necessita' e l'azi=
one
da compiere in caso di collisione e' rimandata agli oggetti stessi.
3.2. Moduli di alto livello
---------------------------
sound
Questo modulo gestisce il sonoro del gioco. Le funzioni che offre devon=
o
permettere di riprodurre effetti sonori in qualsiasi momento e controll=
are
la musica di sottofondo. Questo modulo utilizzera' la libreria SDL_mixe=
r
per il caricamento e la riproduzione dei formati audio.
gfx
Questo modulo contiene alcune routine grafiche generiche utilizzate in
tutto il gioco per il disegno sullo schermo.
net
Questo modulo gestira' la connessione via TCP/IP con altri computer per=
il
gioco via rete. Nella prima versione del gioco, questa caratteristica n=
on
sara' implementata. Per ridurre la complessita' ed aumentare la
portabilita', questo modulo utilizzera' la libreria SDL_net anziche'
l'API di sistema per i socket.
input
Questo modulo utilizza la libreria SDL per ricevere l'input da vari
dispositivi (tastiera, mouse, joypad, etc.) e tradurre gli eventi
grezzi (codice del tasto premuto) in eventi che hanno significato solo
per il gioco (bottone di fuoco del player 1, spostamento a sinistra del
player 2, etc.). La conversione verra' effettuata utilizzando una mappa
configurabile dal menu delle opzioni.
settings
Gestisce il caricamento ed il salvataggio su un file delle opzioni del
gioco. Questo modulo viene utilizzato dal menu delle opzioni e offre
agli altri moduli diverse funzioni per ottenere il valore attuale di
ciascuna opzione attiva.
3.3. Modello di oggetti
-----------------------
Come gia' detto, il comportamento dei diversi oggetti presenti nel gioco
viene stabilito indipendentemente per ciascuna classe. Tutti gli ottetti
sono degli sprite, ma ridefiniscono dei puntatori a funzioni (simili alle
funzioni virtuali del C++) che determinano il modo in cui l'oggetto si
muove, i suoni che produce e l'aspetto che ha sullo schermo. Ogni classe
permette di creare un numero qualsiasi di oggetti concreti, che prendono
il nome di _istanze_. Ciascuna istanza e' una struttura dati contenente
lo stato attuale dell'oggetto: posizione, velocita', azione intrapresa,
etc.
Tutti gli oggetti hanno delle proprieta' comuni che vengono descritte
da una struttura comune. Per esempio:
struct Sprite
{
=09 struct Node link; /* collegamento alla lista degli
* oggetti attivi
*/
struct Point position; /* posizione attuale */
struct Rect dimensions; /* dimensioni */
void (*move)(); /* funzione per il movimento */
void (*draw)(); /* funzione per il ridisegno */
void (*collide)(); /* funzione per la collisione */
void (*play)(); /* funzione per l'elaborazione delle
* azioni da compiere ad ogni frame
=09=09=09=09 */
};
Un esempio di struttura generica per un oggetto che rappresenta una
automobile gestita dal computer potrebbe essere:
struct Car
{
struct Sprite sprite; /* dati comuni a tutti gli sprite =
*/
=09 int speed; /* velocita' attuale */
=09 int steering; /* posizione sterzo (0 =3D centro) */
int fuel; /* carburante rimasto */
int damage; /* danni alla carrozzeria */
=09 int engine; /* stato motore (0 =3D ok) */
=09 int accel; /* accelerazione massima */
=09 int wheel_pos; /* rotazione ruote (da 0 a 7) */
=09 int gear; /* marcia attuale (0-5) */
=09 CarStatus status; /* stato attuale (vedi definizione) */
};
Alcuni oggetti dal comportamento piu' complesso hanno bisogno di mantener=
e
uno stato attuale o piu' variabili di stato per tenere traccia delle azio=
ni
che stanno compiendo. Per esempio, un oggetto Giocatore in un gioco di ca=
lcio
potrebbe essere nello stato "ROVESCIATA", che dura 10 fotogrammi. Mentre =
il
giocatore e' in questo stato, non puo' muoversi e, ad ogni fotogramma, de=
ve
disegnare i fotogrammi di animazione che costituiscono la rovesciata. Se
la palla si trova in collisione con il giocatore durante questo stato, la
palla viene accelerata nella direzione opposta a quella del giocatore.
A fine rovesciata, il giocatore torna nello stato "NORMALE" e puo' muover=
si
normalmente. In questo stato, se si preme il tasto di fuoco, il giocatore
deve andare in stato "SCIVOLATA" se non ha la palla, oppure "TIRO" se ha
la palla.
Ovviamente ogni classe di oggetti ha una sua serie di stati diversi da q=
uelli
degli altri stati. Un'astronave avra' gli stati NORMAL, EXPLODING, SHOOTI=
NG,
etc.
Per ogni oggetto sara' necessario scrivere una macchina a stati dedicata
che implementa il comportamento specifico dell'oggetto.
Ciascun oggetto, eccetto quelli piu' banali come uno sparo, risiedera' i=
n
un modulo C distinto. Anche il giocatore (o i giocatori) sono degli ogget=
ti
che si comportano in un certo modo, ma alcune caratteristiche del loro
movimento dipenderanno dagli eventi riportati dal modulo input.
|