Quando si creano giochi, si crea spesso il seguente oggetto di gioco da cui ereditano tutte le entità:
public class GameObject{
abstract void Update(...);
abstract void Draw(...);
}
Quindi, nel ciclo di aggiornamento, esegui l'iterazione su tutti gli oggetti del gioco e dai loro la possibilità di cambiare stato, quindi nel ciclo di estrazione successivo esegui nuovamente l'iterazione su tutti gli oggetti del gioco e dai loro la possibilità di disegnare se stessi.
Anche se funziona abbastanza bene in un gioco semplice con un semplice renderer in avanti, spesso porta ad alcuni oggetti di gioco giganteschi che devono memorizzare i loro modelli, trame multiple e, soprattutto, un metodo di disegno grasso che crea un accoppiamento stretto tra l'oggetto di gioco, la strategia di rendering corrente e tutte le classi correlate al rendering.
Se dovessi cambiare la strategia di rendering da avanti a differita, dovrei aggiornare molti oggetti di gioco. E gli oggetti di gioco che realizzo non sono riutilizzabili come potrebbero essere. Naturalmente l'ereditarietà e / o la composizione possono aiutarmi a combattere la duplicazione del codice e rendere un po 'più facile cambiare l'implementazione, ma mi sembra ancora carente.
Un modo migliore, forse, sarebbe rimuovere del tutto il metodo Draw dalla classe GameObject e creare una classe Renderer. GameObject dovrebbe comunque contenere alcuni dati relativi ai suoi elementi visivi, ad esempio con quale modello rappresentarlo e con quali trame dovrebbe essere dipinta sul modello, ma come sarà fatto al renderer. Tuttavia, ci sono spesso molti casi di confine nel rendering, quindi anche se questo rimuoverà l'accoppiamento stretto dal GameObject al Renderer, il Renderer dovrebbe comunque essere tutti a conoscenza di tutti gli oggetti di gioco che lo renderebbero grasso, sapendo e strettamente accoppiati. Ciò violerebbe alcune buone pratiche. Forse Design orientato ai dati potrebbe fare il trucco. Gli oggetti di gioco sarebbero certamente dati, ma come sarebbe guidato dal renderer? Non ne sono sicuro.
Quindi sono in perdita e non riesco a pensare a una buona soluzione. Ho provato ad usare i principi di MVC e in passato avevo alcune idee su come usarlo nei giochi, ma recentemente non sembra applicabile come pensavo. Mi piacerebbe sapere come affrontate tutti questo problema.
Ricapitoliamo comunque, sono interessato a come possono essere raggiunti i seguenti obiettivi di progettazione.
- Nessuna logica di rendering nell'oggetto di gioco
- Accoppiamento libero tra oggetti di gioco e motore di rendering
- Nessun renderer che conosce tutti
- Preferibilmente passaggio di runtime tra i motori di rendering
L'impostazione del progetto ideale sarebbe una "logica di gioco" separata e rendere un progetto di logica che non debba fare riferimento a vicenda.
Questo treno di pensiero è iniziato quando ho sentito John Carmack dire su Twitter che ha un sistema così flessibile da poter sostituire i motori di rendering in fase di esecuzione e persino dire al suo sistema di utilizzare entrambi i renderer (un renderer software e un renderer con accelerazione hardware) allo stesso tempo in modo da poter controllare le differenze. I sistemi che ho programmato finora non sono nemmeno così flessibili