Come progettare un motore di gioco in un linguaggio orientato agli oggetti? [chiuso]


26

Ogni volta che provo a scrivere un gioco in qualsiasi linguaggio orientato agli oggetti, il primo problema che devo sempre affrontare (dopo aver pensato a quale tipo di gioco scrivere) è come progettare il motore. Anche se sto usando librerie o framework esistenti come SDL, mi ritrovo ancora a dover prendere determinate decisioni per ogni gioco, come se usare una macchina a stati per gestire i menu, che tipo di classe usare per caricare le risorse, ecc.

Che cos'è un buon design e come verrebbe implementato? Quali sono alcuni compromessi che devono essere fatti e i loro pro / contro?


12
Cosa c'è di sbagliato nell'andare all'impulso e nel refactoring da lì piuttosto che nella paralisi dell'analisi della sofferenza?
Il comunista Duck il

7
@TheCommunistDuck Perché andare all'impulso è l'approccio che ho adottato in tutti i miei progetti precedenti-- e ognuno colpisce un muro dopo pochi mesi quando scopro che ogni nuova funzionalità richiede uno sforzo e una complessità monumentali da aggiungere. In questo momento dedico più tempo a riscrivere i miei motori che a scrivere il gioco stesso, quindi spero che con un po 'di riflessione e pianificazione mi risparmierò tempo nel lungo periodo.
motore extropico,

3
@chuzzum, buon punto. Una cosa che consiglierei allora è di controllare l'architettura del motore C4, cioè; terathon.com/c4engine/images/architecture.png Potrebbe essere di livello molto più alto del necessario, ma potrebbe darti alcune idee ;-)
L'anatra comunista


3
Anche questa domanda è piuttosto vaga. Forse prendi uno dei tuoi esempi e trasformalo in una o due domande più profonde.
Tetrad,

Risposte:


24

Dubito che qualcuno sarà in grado di dire "Devi fare questo e quello e questo e questo slot con quel modello X".

Tuttavia, alcune risorse utili:
Enginuity - una serie di articoli per la costruzione di motori su Gamedev.net.
Codifica del gioco completa - Possiedo questo libro e si occupa di tutti gli aspetti (bene, quasi) della programmazione del gioco. Ha anche un motore incorporato in tutto il libro.
Architettura di Game Engine - Questo è un altro grande libro per la progettazione di motori.
Layout del motore C4 - Tratto dal mio commento, ma questo mostra un modo di alto livello di mettere insieme ciascuna parte del motore.

Questi potrebbero essere un po 'troppo per ciò di cui hai bisogno, ma non puoi sapere troppo di qualcosa e sono sicuro che otterrai da loro un buon piano.

EDIT: ho dimenticato che gli articoli di Gamedev sono stati archiviati dal nuovo sito, risolti :)


Il collegamento Enginuity è stato interrotto e gli articoli su Google sembrano mostrare che non sono più sul web. (?) I libri sembrano buone risorse però, e tengo sempre d'occhio altri libri di programmazione;)
motore estropico

Inoltre, per quanto riguarda il tuo primo commento, non mi aspetto che qualcuno abbia un piano generale che si adatti a ogni gioco. Ho appena notato, nel corso dello sviluppo di alcuni giochi, che i modelli comuni tendono ad emergere molto, quindi mi chiedevo cosa usavano le altre persone nei loro giochi.
motore extropico,

1
Risolto il collegamento.
Il comunista Duck il

+1 per l'ingegnosità. @chuzzum Basta esaminare un paio di motori di gioco, lasciarti ispirare e ricavare l'architettura ottimale per te. Inoltre: è spesso meglio rendere il tuo componente del motore di gioco basato su gerarchico, vedi cowboyprogramming.com/2007/01/05/evolve-your-heirachy
Dave O.

1
Non direi che è il motore che deve essere aggregato, più la parte del framework delle entità.
The Communist Duck,

7

Ad esempio, ecco come è strutturato il mio attuale progetto roguelike (in Java). Sta usando un motore grafico 2D, quindi gran parte del codice di rendering è già stato curato per me. Le critiche sono ben accette.

class Game
Questa classe imposta la macchina a stati che gestisce lo stato attuale del gioco. (in un menu vs. iniziare una nuova partita vs. giocare una partita salvata)

interface State
Ogni classe State contiene due loop: un loop per l'aggiornamento della logica e un loop per il rendering. Contengono inoltre il codice per chiamare la Gameclasse e richiedere una modifica a uno stato diverso.

class ResourceManager
Un singleton inizializzato dalla Gameclasse che carica tutte le risorse necessarie e consente l'accesso ad esse. Non mi piace questo design perché rende difficile caricare / scaricare risorse su diversi livelli, ad esempio. Probabilmente lo progetterei diversamente se dovessi ricominciare da capo.

class Map
Una mappa contiene una serie di tessere e un elenco di tutte le creature e gli oggetti sulla mappa. È una classe piuttosto semplice.

class Creature
Le creature contengono informazioni su se stesse, inclusi i calcoli del movimento (che richiedono loro di sapere in quale mappa si trovano e di essere in grado di interrogarle per scoprire gli ostacoli). Decidere se farlo, o fare in modo che un qualche tipo di manager si prenda cura di lui per tutte le creature è qualcosa con cui faccio fatica.

interface AITask
Le creature possono avere un elenco di AITask, che vengono eseguiti ogni volta che viene eseguito il ciclo logico della creatura. L'AITask ha il suo circuito logico che impartisce comandi alla creatura e una condizione di terminazione che determina se l'attività è stata completata con successo o no.

interface UIElement
Ho implementato la mia interfaccia utente per questo motore. Ogni UIElement ha un loop di rendering e un loop logico. Hanno anche un ciclo per l'elaborazione dell'input da tastiera / mouse. Tutti gli elementi possono avere un numero di elementi figlio, che sono resi dopo i loro genitori, e assumono l'input da tastiera / mouse. Ciò consente di avere menu con sottomenu, ad esempio.


Cosa non va esattamente in questo? Mi sembra perfettamente perfetto.
Il comunista Duck il

@TheCommunistDuck In realtà non emerge negli esempi che ho scelto, ma ho molti problemi con questo codice. La classe ResourceManager è una di queste, ma ho anche dei problemi con gli stati: finisco con un'enorme proliferazione di questi e copio molto codice. Soprattutto in un gioco di ruolo, in cui il giocatore ha molte scelte in qualsiasi momento, puoi finire con grafici di stato davvero complessi. Esempio: lanciare un incantesimo. Passa da NormalState -> SelectSpellState -> SelectTargetState -> InvalidTargetState (se fallito) -> DoSpellAnimationState -> NormalState. E questa è solo un'azione.
motore extropico,

1
No. NO NO . NO. Per favore no. Oh aspetta hai detto che non ti piace.
Bartek Banachewicz,

6

Il primo punto importante da sottolineare è che non esiste una risposta "buona" a questa domanda.

La cosa più vicina a una risposta giusta sarebbe qualcosa del genere: dipende molto dal tipo di gioco, dalla piattaforma target, dai vincoli (tempo) ecc.

Detto questo, ci sono alcuni articoli davvero validi là fuori che ti mostreranno come altre persone hanno cercato di rispondere a questo problema (come ho cercato di trovare informazioni su questo in passato).
Mentre The duck comunista menzionava l' articolo sull'ingegnosità sul game dev mi ha aiutato a capire alcune parti dell'architettura di gioco.

Il mio progetto attuale è un ibrido di Quake3 / Doom3 e un po 'della libreria di classi .NET :)

Ho due librerie (statiche o dinamiche dipende da come vuoi costruire / consegnare) Frameworke Library.

La libreria contiene tutte le classi di aiuto che sono lì per aiutare con la produzione di software di gioco ma non sono limitate a questo tipo di prodotto. cioè ha un'implementazione di un elenco collegato che è ottimizzato per il codice di gioco ma potrebbe essere utilizzato da tutto ciò che necessita del servizio di un elenco collegato.

Il Framework è il coraggio del "motore" se vuoi chiamarlo così. Molto di questo segue le filosofie progettuali di Quake3 (solo in un modo più orientato agli oggetti). Contiene l' interfaccia della riga di comando , la gestione dei tempi, il codice specifico del sistema operativo e infine i livelli di rete ecc.

Questi due sono quindi collegati all'app effettiva che viene prodotta. Il Gamese volete, che contiene il codice di gioco specifico. Allo stesso modo, Quake3 carica le DLL in base a quale 'mod' viene riprodotto.

Per darti un'idea della struttura, ecco una rapida suddivisione di cartelle e contenuti per ogni lib:


  • Struttura
    • IO (classi di gestione file specializzate, classi di stampa di testo (ad es. Alla CLI) e registrazione ecc.)
    • Rete
      • Cliente (classi che rappresentano ciò che il Framework considera una "persona che gioca / è connessa al gioco")
      • Server (classi per gestire la connessione nel framework e gestire i giocatori)
    • Piattaforma (tastiera / mouse / controller che gestiscono classi, routine specifiche del sistema operativo come getTime ())
    • Sistema (classi di livello molto basso come una classe di errore per facilitare la stampa di messaggi di errore, classi di temporizzazione e CLI stessa.)
    • Renderer (autoesplicativo)
    • eccetera.

  • Biblioteca
    • Collezioni (classi che rappresentano raccolte di dati, liste / hashtabili collegati ecc.)
    • Matematica (lezioni di base di matematica come vettori e matrici)
    • eccetera.

HTH! Dovresti darti alcuni suggerimenti ...


Collegamento alternativo alla serie Enginuity
Musaffa,

-3

Cose da considerare

  • I linguaggi orientati agli oggetti hanno problemi perché di solito non hanno funzioni di prima classe o non tutti i dati sono oggetti (come numeri interi o float in Java). I motivi di progettazione risolvono questi problemi con diversi motivi. Generalmente è più veloce da programmare e più facile da usare usare un linguaggio che li possa fare (oggetti di prima classe); ad esempio Python (che consente anche la progettazione orientata agli oggetti), avrai una velocità più lenta.
  • Event Calculus, almeno per AI
  • Hoare la logica, utilizzare precondizioni e postcondizioni per testare almeno il tuo codice
  • Agenti, guardate le entità di Quake
  • Database relazionali, un modo efficace per archiviare i dati

Buon design

  • fare diagramma ER
  • renderlo corretto
  • crea il tuo database, oggetti o strutture di dati da esso

I dati sono fondamentali per la programmazione. Se desideri che i tuoi dati siano validi, l'algoritmo di solito emerge da essi (se non conti alcuni algoritmi numerici, come il determinante di calcolo).


-1 poiché questa risposta è molto vaga e confusa. I database relazionali non hanno assolutamente nulla a che fare con un motore OO. Posso capire che l'inglese non è la tua prima lingua, ma potresti forse spiegare cosa intendi nel tuo primo paragrafo? Sembra contraddittorio (i linguaggi OO hanno problemi ma è più facile programmare in linguaggi con schemi di progettazione ... anche se gli schemi di progettazione sono quasi sempre strutture OO).
Il comunista Duck il

@duck Contradictory? OO ha problemi che non esistono in altre lingue, DP risolverli vedere c2.com/cgi/wiki?DesignPatternsInDynamicProgramming .
user712092,

@Duck 1) Puoi usare SQL in C ++ 2) Puoi inferire gli attributi degli oggetti da ER (anche se non è una pratica consigliata) 3) Puoi strutturare i dati dalle relazioni (questa è una lista perché devo riordinare gli elemenenti a volontà questo è un hash perché ho bisogno di una ricerca veloce)
user712092

@Duck Mi scuso, ho fatto un errore riordinando. Non volevo rivendicare "DP è più facile da XY" ma "le lingue che sanno fare la prima classe sono ...". :)
user712092

Sì, potrebbero esserci vantaggi per i linguaggi funzionali. Tuttavia, anche in modo imparziale, ritengo che un approccio OO abbia un senso logico dal punto di vista del gioco. Inoltre, non vi è alcun motivo per cui sia necessario un database relazionale ovunque. Certo, possono essere utili. Tuttavia, non diventa un componente necessario da nessuna parte.
Il comunista Duck il
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.