Quali sono alcuni schemi di progettazione di programmazione che sono utili nello sviluppo del gioco? [chiuso]


129

Ho alcuni libri su Design Patterns e ho letto alcuni articoli, ma non riesco a capire intuitivamente quali schemi di design di programmazione sarebbero utili nello sviluppo del gioco.

Ad esempio, ho un libro chiamato ActionScript 3 con motivi di progettazione che descrive in dettaglio diversi motivi di progettazione come Model View Controller, Singleton, Factory, Command, ecc.

Come nuovo per questo, non riesco a capire quale di questi sarebbe utile, o in effetti se uno di questi è lo schema di progettazione che dovrei imparare e provare a usare. Forse ci sono altri schemi di progettazione più specifici per la programmazione di giochi di cui non sono nemmeno a conoscenza?

Se hai esperienza con un certo modello di progettazione nello sviluppo del gioco, mi piacerebbe ascoltarlo. Ragionare sul motivo per cui è stato utilizzato, esempi di codice o risorse online sarebbe molto utile anche se li hai. Al momento sono più interessato alle implementazioni di ActionScript 3 e C ++, ma potrei sicuramente beneficiare dell'esperienza e degli esempi di qualsiasi lingua.

Grazie!


"Forse ci sono altri schemi di progettazione più specifici per la programmazione di giochi di cui non sono nemmeno a conoscenza?" - no, questi schemi sono generici e si applicano di più per estendere le capacità della lingua che stai utilizzando. Non hanno nulla a che fare con l'oggetto della tua domanda.
Kylotan,

3
@Kylotan Sembra dal mio punto di vista limitato che, poiché ogni modello di progettazione è inteso a risolvere un problema particolare in modo efficace, per sua natura alcuni modelli di progettazione sarebbero più utili di altri, dato un determinato set di problemi, vale a dire in questo caso, questi problemi sono unici per lo sviluppo del gioco. Sicuramente ci sono alcune linee guida, o in base alla tua esperienza, particolari modelli di design che ti ritrovi a utilizzare più frequentemente di altri?
jcurrie33,

Prima che qualcuno si spenga e apprenda 1000 diversi modelli di design, leggi questo e questo
BlueRaja - Danny Pflughoeft

@ Link BlueRaja-DannyPflughoeft Secon non valido. Puoi inviarlo di nuovo
Emadpres,

Risposte:


163

Ora per una risposta meno irriverente, con alcuni suggerimenti. Non prenderli come raccomandazioni di implementazione, più come esempi di possibile utilizzo.

  • Builder: imposta un'entità basata su componenti un componente alla volta, in base ai dati
  • Metodo di fabbrica: crea widget NPC o GUI basati su una stringa letta da un file
  • Prototipo: memorizza un carattere "Elfo" generico con proprietà iniziali e crea istanze di Elfo clonandolo.
  • Singleton: questo spazio è stato lasciato deliberatamente in bianco.
  • Adattatore: incorporare una libreria di terze parti opzionale avvolgendola in un livello simile al codice esistente. Molto utile con le DLL.
  • Composito: crea un grafico di scena di oggetti renderizzabili o crea una GUI da un albero di widget
  • Facciata: semplifica complesse librerie di terze parti fornendo un'interfaccia più semplice per semplificarti la vita in seguito.
  • Flyweight: memorizza gli aspetti condivisi di un NPC (ad es. Modelli, trame, animazioni) separatamente dai singoli aspetti (ad es. Posizione, salute) in modo per lo più trasparente
  • Proxy: creare piccole classi su un client che rappresentano classi più grandi e complesse su un server e inoltrare richieste tramite la rete.
  • Catena di responsabilità: gestire l'input come una catena di gestori, ad es. tasti globali (ad es. per schermate), quindi la GUI (ad es. nel caso in cui una casella di testo sia focalizzata o un menu in alto), quindi il gioco (ad es. per spostare un personaggio)
  • Comando: incapsula la funzionalità di gioco come comandi che possono essere digitati in una console, archiviati e riprodotti, o addirittura scritti per aiutare a testare il gioco
  • Mediatore: implementa le entità di gioco come una piccola classe di mediatore che opera su diversi componenti (ad es. Lettura dal componente di salute al fine di passare i dati al componente AI)
  • Osservatore: chiedi alla rappresentazione renderizzabile di un personaggio di ascoltare gli eventi dalla rappresentazione logica, al fine di cambiare la presentazione visiva quando necessario senza che la logica di gioco abbia bisogno di sapere qualcosa sul rendering del codice
  • Stato: memorizza NPC AI come uno dei vari stati, ad es. Attaccare, Vagare, Fuggire. Ognuno può avere il proprio metodo update () e qualsiasi altro dato di cui abbia bisogno (es. Memorizzare il personaggio da cui sta attaccando o in fuga, l'area in cui sta vagando, ecc.)
  • Strategia: passa tra diverse euristiche per la tua ricerca A *, a seconda del tipo di terreno in cui ti trovi, o forse anche per utilizzare lo stesso framework A * per fare sia la ricerca di percorsi sia una pianificazione più generica
  • Metodo modello: imposta una routine generica di "combattimento", con varie funzioni di aggancio per gestire ogni passo, ad es. decrementa le munizioni, calcola la probabilità di colpire, risolve il colpo o manca, calcola il danno e ogni tipo di abilità di attacco implementerà i metodi nel loro modo specifico

Alcuni schemi lasciati fuori a causa della mancanza di ispirazione.


Una discussione molto illuminante sui singleton è disponibile qui: misko.hevery.com/2008/08/25/root-cause-of-singletons
Andrew Wang,

+1 per il modello di strategia. L'ho usato per lo scopo esatto sopra indicato (inserendo diverse euristiche A *).
Mike Strobel,

1
grazie per questa risposta, quelli suonano più come uno schema di design che il solito "singleton" che sto ascoltando ovunque ...
jokoon

Grande elenco di esempi. Nonostante l'abuso cronico del modello singleton (stato globale sotto mentite spoglie), ci sono usi legittimi: quando rappresenta una risorsa di cui in realtà ne hai (o vuoi) solo uno. Questo può essere qualcosa come avvolgere l'hardware (es. Tastiera / mouse) o avvolgere una libreria che non è rientrante (succede, e non tutte le lingue hanno parole chiave di sincronizzazione magica).
Charstar,

11
Non userei ancora i singleton per le risorse hardware - elementi che pensi che avrai sempre 1 di tende a moltiplicarsi in seguito, proprio come hanno fatto le schede video e i monitor nel corso degli anni. Allo stesso modo, in alcune API è necessario leggere 2 joystick per comprendere 1 gamepad. Quindi direi, se hai solo bisogno di qualcosa, istanzia solo uno, non imporre restrizioni arbitrarie che probabilmente non sono necessarie.
Kylotan,

59

Ho scritto un libro su questo argomento esattamente: Pattern di programmazione del gioco . I capitoli presenti potrebbero essere utili per te.


2
+1 Speravo che qualcuno si fosse collegato a questo e vedo che l'autore ha! La descrizione del modello del componente è stata piuttosto utile, e mi piace che tu provi ad usare esempi di codice completi per dimostrare.
CodexArcanum,

2
Sì, ricordo di aver letto il tuo link qualche anno fa. Dovresti finire quegli articoli!
onedayitwillmake

2
Ora il libro è finito :)
dusan,

1
Una risorsa straordinaria che mi ha aiutato a tradurre le mie conoscenze di programmazione esistenti in programmazione per giochi. Grazie per averlo scritto!

Questa spiegazione dei modelli di programmazione del gioco mi ha effettivamente aiutato a capire - progettare i modelli - in un modo in cui nessun libro di schemi di progettazione software ha fatto davvero! Questo è in parte il potere dello sviluppo del gioco (esempi concreti in un linguaggio che mi parla e mi permette di migliorare il mio sviluppo in generale), ma in una parte più ampia perché la scrittura è così eccellente.
Kzqai,

19

Una cosa che Brandon Eich ha avuto il buon senso di far apparire in Coders at Work è che i pattern sono hack e soluzioni alternative: [Patterns] mostrano un qualche tipo di difetto nel linguaggio. Questi schemi non sono gratuiti. Non c'è pranzo libero. Quindi dovremmo cercare l'evoluzione nel linguaggio che aggiunge i bit giusti.

Come programmatori di giochi piuttosto che come progettisti di compilatori raramente abbiamo la possibilità di evolvere le lingue che usiamo, ma possiamo imparare ad evolvere il nostro stile per adattarci meglio alla nostra lingua e ai nostri requisiti. I pattern sono alcuni di questi, ma non usare i pattern è un'altra parte, soprattutto perché, come dice Brandon, i pattern raramente vanno senza prestazioni notevoli o costi di agilità di memoria o codice. MVC non è un ottimo modello per molte cose nei giochi. Singleton è una soluzione alternativa per le regole di inizializzazione statica C ++ scadenti e probabilmente non dovresti farlo comunque. Factory semplifica la creazione di oggetti complicati - forse i tuoi oggetti dovrebbero essere più semplici per cominciare. I modelli popolari sono strumenti a cui ricorrere quando ne abbiamo bisogno per gestire qualcosa di complesso, non strumenti che dovremmo desiderare di usare per costruire qualcosa di complesso all'inizio.

Un buon codice (di gioco) potrebbe usare schemi, oppure no. Se utilizza modelli, va bene: sono un ottimo strumento di comunicazione per spiegare la struttura del codice ad altri programmatori a un livello elevato, indipendente dalla lingua. Se pensi che il codice sia migliore senza usare un pattern, non battere su di esso - probabilmente lo è.


4
Sì, una delle cose chiarite nel libro originale (ma spesso trascurato) è che se fosse stato scritto per C piuttosto che C ++ / Smalltalk, avrebbero potuto includere un modello di "Ereditarietà" e, allo stesso modo, alcune lingue potrebbe contenere alcuni dei modelli GoF già incorporati.
Kylotan,

13
L'altra cosa spesso trascurata nel libro originale (il libro originale originale di Alexander, non GoF) era che i modelli sono uno strumento per la comunicazione , non per l' implementazione . Consentono ai progettisti di comunicare sull'implementazione a un livello superiore e vengono identificati perché ricorrenti, non necessariamente perché dovrebbero essere utilizzati quando possibile.

1
Tuttavia, il solo fatto di avere una terminologia può aiutarti a ragionare sul problema e riconoscere quando un tale approccio è una buona soluzione. I modelli migliori sono stati in genere perfezionati nel tempo da lavoratori qualificati ed esperti, e i lavoratori meno qualificati non avrebbero scoperto gli stessi modelli senza che esistessero questi esempi codificati.
Kylotan,

Concordo sul fatto che avere una terminologia è eccezionale, e parte della definizione di un modello è che è una buona soluzione ricorrente per qualche problema. Sfortunatamente i lavoratori meno qualificati tendono a trovare principalmente Singleton e ad applicarlo a tutti i problemi, anche quando non c'è ancora un problema.

Grazie per questa risposta; Mi sento sollevato nel leggere che i modelli di progettazione sono fatti per risolvere i problemi creati dalla progettazione del software. Penso che la struttura di un intero grande software dovrebbe essere pensata dall'inizio alla fine prima di iniziare a codificare qualsiasi cosa. Non è sempre possibile implementare funzionalità una volta alla volta, a volte è necessario pensare a ciascuna caratteristica particolare e verificare se non interferirà con la struttura globale del software o semplicemente ostacolare il modo in cui il software è destinato comportarsi. Dividere compiti per diversi programmatori può a volte creare contraddizioni ...
jokoon

7

Naturalmente, come altri hanno già detto, tutti i modelli sono utili nelle giuste circostanze e parte dell'apprendimento su come usarli è imparare quando usarli. Tuttavia, l'eccellente libro Core Techniques and Algorithms in Game Programming di Daniel Sanchez-Crespo Dalmau, elenca sei schemi di programmazione e sei schemi di usabilità come particolarmente utili nella programmazione di giochi.

Programmazione:

  • Singleton: Non odio questo come fanno molte persone; può essere usato per cose come il giocatore singolo o il lettore tastiera.
  • Factory: consente di creare e distruggere oggetti in modo efficiente.
  • Strategia: consente di modificare le strategie di intelligenza artificiale in modo elegante.
  • Indice spaziale: aiuta a eseguire query su set di dati spaziali.
  • Composito: imposta un'utile gerarchia di oggetti.
  • Flyweight: libera la memoria generando cose come nemici identici.

usabilità:

  • Scudo: protegge dall'attivazione accidentale di azioni drammatiche.
  • Stato: segnali visivi del mondo / stato dell'interfaccia utente.
  • Annullamento automatico della modalità: rende il gioco più intuitivo.
  • Magnetismo: autoaim e facile selezione dell'unità.
  • Focus: eliminare gli elementi dell'interfaccia utente che distraggono.
  • Progresso: universalmente utile.

Il libro, ovviamente, approfondisce in dettaglio ciascuno di essi.


Grazie per l'input! Non ero a conoscenza di quel libro, ma lo esaminerò ora come risultato del tuo post. Grazie ancora!
jcurrie33,

2
Singleton per il lettore di tastiere è esattamente la situazione in cui devo chiedere: puoi davvero non solo renderlo un puntatore globale impostato all'inizio della tua funzione principale? Hai mai istanziato accidentalmente due lettori di tastiere?

Per favore, odia il singleton. Fa due cose male. Accesso globale e arità. Spesso gli sviluppatori pensano che l'accesso globale == singleton. C'è un molto pochi problemi che hanno bisogno di un vero Singleton, e forse qualcuno in più che sono più elegante quando risolto con un Singleton.
deft_code

7

I sistemi di entità sono un bel tipo di modello. Non è esattamente un modello di progettazione dal momento che non è assolutamente OOP. Tuttavia puoi mescolarlo con OOP.

Alcuni buoni collegamenti (inizia dall'alto per introduzione):


3
"Non è esattamente un modello di progettazione poiché non è stranamente [sic] OOP." I modelli di progettazione non hanno nulla a che fare con OOP; semmai, OOP stesso è un modello di progettazione. I modelli di progettazione appaiono non solo al di fuori di OOP, ma al di fuori dello sviluppo del software.

In OOP design patternsgenere ci sono relazioni e interazioni tra classi / oggetti. E ci sono molti altri modelli di design. OOP è un insieme di concetti, non un modello in realtà. Design patternè anche un concetto.
topright

6
Invece di parlare di semantico, non dovresti valutare l'utilità della risposta che ho dato?
Wernight,

6

Tutti loro. Tranne Singleton. [/ Leggerezza]


Potresti forse nominare uno o due motivi di design che hai usato frequentemente nello sviluppo del tuo gioco, e per quale motivo? Come principiante rispetto ai modelli di progettazione, "tutti" non è una risposta particolarmente utile. Grazie per aver risposto, però.
jcurrie33,

5
Chiedere "quali schemi hai usato?" è come chiedere "quali nomi di variabili hai usato?" Dipende dallo stile personale, dai requisiti e dal dominio. Ad un certo punto, probabilmente userete qualsiasi modello che sia mai stato nominato. Probabilmente ne userete molti altri che non sono stati nominati e forse ne inventerete anche di nuovi.

@ jcurrie33: scusa, non ho potuto resistere per prima cosa a scavare nei singleton. ;)
Kylotan,

6

Non proprio sugli schemi, ma sui principi di base che li stanno dietro. In "Design Patterns: Elements of Reusable Object-Oriented Software" (1995) , la banda di quattro (Gamma, Erich; Richard Helm, Ralph Johnson e John Vlissides) raccomanda solo due principi per la progettazione orientata agli oggetti: (1) programma per un'interfaccia e non un'implementazione e (2) favorire la composizione degli oggetti rispetto all'ereditarietà delle classi.

Questi 2 principi sono molto utili in molte attività di sviluppo del gioco. Ad esempio, molti programmatori di giochi hanno usato una gerarchia di classe profonda per rappresentare le entità di gioco. Esiste un altro approccio basato sulla composizione : oggetti di gioco basati su componenti. Articolo su questo approccio. Ancora più collegamenti . È un esempio di modello di Decorator .


I componenti utilizzati nella progettazione del gioco sono più simili a un modello di strategia con stato, che è naturalmente espresso come chiusure esterne a C / C ++ / Java / C # e come oggetti componenti al loro interno. Il motivo del decoratore è più simile a un proxy; la sua proprietà e il flusso di dati sono opposti a quelli che intendiamo normalmente quando parliamo di sistemi componenti nei giochi.

I componenti devono anche dialogare tra loro, introducendo modelli come Mediatore, Osservatore e Compositore. "Component-Based Game" è un modello di disegno composito tutto da solo.
CodexArcanum,

@CodexArcanum, Observer, sicuramente, ma non sempre mediatore (si può usare invece la catena di responsabilità). È Composer solo se GameObject (composto da GameObjectComponent) è GameObjectComponent stesso (non essenziale).
piedi il

6

Il modello di modello curiosamente ricorrente può essere davvero utile per evitare metodi virtuali e la penalità delle prestazioni che può derivare dalle chiamate di funzione virtuale.

Questo può essere il modello appropriato quando in realtà non è necessario disporre di un contenitore del tipo di classe base che abbia l'interfaccia che si sta cercando, ma si desidera avere comportamenti e interfacce con nomi simili.

Ad esempio, è possibile utilizzarlo durante la compilazione di classi per più piattaforme o motori (dx vs. opengl) in cui la varianza del tipo è nota al momento della compilazione.


Ho sempre odiato che il livello di astrazione del sistema operativo fosse virtuale. Non è che avrai mai bisogno di due livelli di astrazione del sistema operativo. Molto meglio usare CRTP.
deft_code

Forse sono solo vecchio, ma non userei nemmeno CRTP per DX / OpenGL o interfacce di piattaforma. È troppo lento per la compilazione - userò solo typedefs. CRTP è utile quando si desidera condividere interfacce e implementazioni tra classi ma non si ha altra relazione, non quando si desidera semplicemente scegliere una struttura o l'altra.

4

Un modello di progettazione che mi sono evoluto nel corso di molti anni e che mi è stato straordinariamente utile, è qualcosa che chiamo "set di definizioni intermediati"; come riassumerlo in termini GOF sembra essere controverso, ma questa domanda che ho scritto su StackOverflow ci fornisce alcuni dettagli al riguardo.

Il concetto di base è che alcune proprietà di un modello, come le specie di una creatura, sono impostate in modo tale che ogni possibile valore per la proprietà abbia un oggetto di definizione corrispondente - un singolo oggetto condiviso per valore - che ne specifica il comportamento, e questi sono accessibili tramite un broker centrale (che, per quanto riguarda il GOF, può essere un registro, una fabbrica o entrambi). Nel mio utilizzo, sono anche generalmente accessibili tramite tasti scalari, per facilitare l'associazione debole a scopi di morfismo di runtime.


Non vedo come questo sia un singleton e quando si discute del modello dei pesi mosca la parola "registro" è ridondante. Questo è solo peso mosca.

La mia comprensione dal thread SO è stata che le persone hanno identificato Singleton come parte di esso a causa delle definizioni impostate come classi. Per quanto riguarda il registro, non vedo come possa essere ridondante quando può essere sostituito o combinato con Factory.
caos,

-1, nella misura in cui i modelli riguardano la comunicazione rapida, questo è probabilmente il più grande fallimento che abbia mai visto. Non riesco davvero a prendere sul serio questa descrizione.

Gesù, scusami per non essere stato abbastanza per te. Voterai anche la risposta "Sistemi di entità" perché non è immediatamente riassumibile in termini di GOF?
caos,

1
Una certa quantità di "cookie cutter", o almeno di chiarezza semantica, è esattamente quali schemi devono essere utili. Termini come "peso mosca" e "singleton" come comunemente intesi si escludono a vicenda. Il primo riguarda la condivisione automatica dei dati tra più istanze; il secondo riguarda esattamente un'istanza. Non sto dicendo che la tua scelta di design sia inutile o addirittura cattiva, ma stipare nomi di modelli "abbastanza vicini" confonde solo tutti di più. (Si prega di non prendere personalmente i
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.