2010-07-24 19 views
6

Sto scrivendo un progetto di gioco come un hobby e sto cercando alcuni consigli di architettura su come organizzare al meglio i miei oggetti di gioco e le loro varie animazioni.Modello di architettura di animazione

Ad esempio, ho una classe denominata Procedura guidata e una classe denominata Dragon. Un Wizard ha almeno 10 differenti animazioni specifiche associate, a seconda del suo stato, e lo stesso per Dragon.

Quindi la mia domanda è questa: v'è un modello standard per organizzare questi tipi di oggetti in modo che sia efficiente e semplice da estendere (vale a dire che dovrebbe essere facile aggiungere nuovi animazioni e nuovi oggetti)?

Ho varie idee su come andare avanti su questo, ma io non voglio sbagliare visto che è una parte così importante dell'architettura del gioco. Sembra facile ottenere questo lavoro per un piccolo gioco , ma ho paura della complessità ingestibile in quanto diventa più grande .

+0

Ruba idee da giochi open source esistenti. –

+0

std :: map - per archiviazione interna da stato a animazione e qualsiasi formato aperto per archiviazione esterna. – W55tKQbuRu28Q4xv

risposta

1

Suggerisco di avere un'interfaccia come "Carattere", che definisce ciò che tutte queste entità dovrebbero essere in grado di fare. Quindi le tue classi Dragon e Wizard sono solo implementazioni.

Un altro percorso consiste nell'avere una classe Base da cui ci si estende e utilizzarla per controllare lo "sprawl gerarchico" associato ai progetti di grandi dimensioni, disegnando una gerarchia dei propri oggetti e identificando le classi di base estese.

0

No, non esiste assolutamente un modello standard.

Il mio consiglio è di evitare il trabocchetto del progettista OO per i principianti cercando di trovare un'unica interfaccia di "classe base" comune per tutto. Il tuo drago è molto diverso dal tuo mago e non c'è nulla da guadagnare tentando di unire le due interfacce, tranne le astrazioni di codice. Ricorda, l'ereditarietà non è uno strumento per il riutilizzo del codice.

L'approccio più semplice è che ogni oggetto mantenga il proprio stato interno (come già descritto) e sia in grado di disegnare quello stato. Questo è il punto in cui un'istruzione switch vecchia scuola può essere più chiara dell'utilizzo del polimorfismo per lo stesso effetto. Esempio:

class Dragon { 
enum State { asleep, flying, breathing_fire }; 
public: 
void draw() { /* old-school switch */ 
    switch (cur_state){ 
    case asleep: draw_asleep(); 
    case flying: draw_flying(); 
    case breathing_fire: draw_breathing_fire(); 
    } 
    } 
private: 
    void draw_asleep(); 
    void draw_flying(); 
    void draw_breathing_fire(); 
}; 

esperti sviluppatori C++ si gasp al codice di cui sopra (come dovrebbero), perché l'istruzione switch è quasi esattamente quello che una chiamata di metodo polimorfico avrebbe compiuto - runtime spedizione. (O ancora più criptico: una tabella di indirizzi di metodo). La mia opinione personale è che per questo specifico tipo di classe, cioè una singola interfaccia pubblica che incapsula una macchina a stati, l'istruzione switch è più chiara e mantenibile perché rende la macchina a stati salta esplicitamente. Penso sia anche chiaro che riconosco che questo è generalmente design C++ non valido.

L'attrito di questo design è causato dalla linea divisoria tra la macchina a stati e la singola interfaccia pubblica. Un drago dormiente non è chiaramente lo stesso di un drago volante. In effetti, non avrà praticamente nulla in comune. Ma il design di livello più alto dice che i due sono il drago SAME. Che casino! Crei oggetti Dragon diversi per ogni stato? No, perché questo esporrebbe il concetto di stato al chiamante. Crei diversi oggetti helper interni per ogni stato e li spedisci a quelli? Forse, ma diventa molto veloce. L'approccio di cui sopra è un compromesso tra i due.Pensa all'affermazione dell'intervento come se isolasse la bruttezza. L'interfaccia pubblica è pulita, così come l'interfaccia privata. Solo l'istruzione switch contiene il pasticcio sporco. Considera questo approccio e considera anche altri suggerimenti.

Infine, per attirare la vostra Wizard e il vostro drago, un semplice modello di involucro o funtore sarà sufficiente:

struct Draw { 
    template <class S> 
    void operator()(S& s) { s.draw(); } 
}; 

Il punto è che non c'è bisogno di unire due classi diverse solo perché entrambi supportano il stessa operazione logica.