Lo ammetto, ho commesso il peccato di abusare e persino di abusare dell'eredità. Il primo progetto di gioco (testuale) che ho realizzato durante il mio corso OOP è andato fino a "Porta chiusa" e "Porta aperta" da "Porta" e "Stanza con una porta", "Stanza con due porte" e così via da "Room".
Con il gioco (grafico) a cui ho lavorato di recente, pensavo di aver imparato la lezione e di limitare l'uso dell'ereditarietà. Tuttavia ho notato presto che i problemi iniziano ad apparire. La mia classe radice stava iniziando a gonfiarsi sempre di più e le mie classi foglia erano piene di codici duplicati.
Ho pensato che stavo ancora facendo cose sbagliate, e dopo averlo cercato online ho scoperto che non ero l'unico con questo problema. È così che ho scoperto i sistemi Entity dopo alcune ricerche approfondite (leggi: googlefu)
Quando ho iniziato a leggerlo, sono stato in grado di vedere con quanta chiarezza fosse in grado di risolvere i problemi che avevo con la gerarchia OOP tradizionale con i componenti. Questi erano tuttavia nelle prime letture. Quando mi sono imbattuto in altri ... approcci ES "radicali", come quello della T-machine .
Ho iniziato a non essere d'accordo con i metodi che stavano usando. Un sistema a componenti puri sembrava eccessivo, o piuttosto non intuitivo, che è probabilmente il punto di forza di OOP. L'autore si spinge fino a dire che il sistema ES è l'opposto di OOP, e mentre può essere utilizzabile con OOP, in realtà non dovrebbe. Non sto dicendo che è sbagliato, ma non mi sentivo come una soluzione che vorrei implementare.
Quindi, per me, e risolvere i problemi che avevo all'inizio del post, senza andare contro le mie intuizioni, è ancora usare una gerarchia, tuttavia non sarà una gerarchia monolitica come quelle che ho usato prima, ma piuttosto uno polilitico (non riuscivo a trovare una parola opposta al monolitico), che consiste di diversi alberi più piccoli.
L'esempio seguente mostra cosa intendo (questo è ispirato a un esempio che ho trovato in Game Engine Architecture, capitolo 14).
Avrei un piccolo albero per i veicoli. La classe del veicolo radice avrebbe un componente di rendering, un componente di collisione, un componente di posizione ecc.
Quindi un serbatoio, una sottoclasse di veicoli erediterebbe quei componenti da esso, e gli sarebbe stato dato il proprio componente "cannone".
Lo stesso vale per i personaggi. Un personaggio avrebbe i suoi componenti, quindi la Classe giocatore lo erediterebbe e gli sarebbe stato assegnato un controller di input, mentre le altre classi nemiche avrebbero ereditato dalla classe Character e gli sarebbe stato dato un controller AI.
Non vedo davvero alcun problema con questo design. Nonostante non utilizzi un puro Entity Controller System, il problema con l'effetto bubbling e la grande classe root viene risolto utilizzando una gerarchia multi-albero e il problema delle pesanti foglie che duplicano il codice scompare poiché le foglie non lo fanno avere un codice per cominciare, solo componenti. Se è necessario apportare una modifica al livello foglia, è semplice come modificare un singolo componente, anziché copiare e incollare il codice ovunque.
Naturalmente, essendo inesperto quanto me, non ho riscontrato alcun problema quando ho iniziato a utilizzare la singola gerarchia, il modello pesante ereditario, quindi se ci sono problemi con il modello che sto pensando di implementare, non lo farei essere in grado di vederlo.
Le tue opinioni?
PS: sto usando Java, quindi non è possibile utilizzare l'ereditarietà multipla per implementare questo invece di utilizzare componenti normali.
PPS: le comunicazioni intercomponenti verranno eseguite collegando tra loro componenti dipendenti. Questo porterà all'accoppiamento, ma penso che sia un giusto compromesso.