Eu admito, cometi o pecado de abusar e até abusar da herança. O primeiro projeto de jogo (texto) que eu fiz quando estava no curso de OOP foi até "Porta trancada" e "porta destrancada" de "Porta" e "Sala com uma porta", "Sala com duas portas" e assim por diante a partir de "Room".
Com o jogo (gráfico) em que trabalhei recentemente, pensei ter aprendido minha lição e colocar um limite no uso de herança. No entanto, notei os problemas logo começando a aparecer. Minha classe raiz estava começando a inchar cada vez mais, e minhas classes folha estavam cheias de códigos duplicados.
Eu pensei que ainda estava fazendo as coisas erradas e, depois de pesquisar on-line, descobri que não era o único com esse problema. Foi assim que acabei descobrindo os sistemas de entidades após uma pesquisa completa (leia-se: googlefu)
Quando comecei a ler, pude ver com que clareza era possível resolver os problemas que eu estava tendo com a hierarquia OOP tradicional com componentes. Essas foram as primeiras leituras, no entanto. Quando me deparei com mais ... abordagens ES "radicais", como a da T-machine .
Comecei a discordar dos métodos que estavam usando. Um sistema de componentes puros parecia exagerar, ou melhor, não intuitivo, o que provavelmente é a força da OOP. O autor chega ao ponto de dizer que o sistema ES é o oposto do OOP e, embora possa ser usado junto com o OOP, realmente não deveria. Não estou dizendo que está errado, mas simplesmente não me senti uma solução que gostaria de implementar.
Então, para mim, e resolver os problemas que eu estava tendo no início do post, sem ir contra minhas intuições, é ainda usar uma hierarquia, no entanto, não será uma hierarquia monolítica como as que eu usei antes, mas sim uma polilítica (não consegui encontrar uma palavra oposta à monolítica), que consiste em várias árvores menores.
O exemplo a seguir mostra o que quero dizer (isso é inspirado em um exemplo que encontrei na Game Engine Architecture, capítulo 14).
Eu teria uma pequena árvore para veículos. A classe de veículo raiz teria um componente de renderização, um componente de colisão, componente de posição etc.
Em seguida, um tanque, uma subclasse de veículo herdaria esses componentes e receberia seu próprio componente "canhão".
O mesmo vale para os personagens. Um personagem teria seus próprios componentes, então a Classe de Jogador o herdaria e receberia um controlador de Entrada, enquanto outras classes inimigas herdariam da classe de Personagens e receberia um controlador de IA.
Realmente não vejo nenhum problema com este design. Apesar de não usar um Entity Controller System puro, o problema com o efeito borbulhante e a classe raiz grande são resolvidos usando uma hierarquia de várias árvores, e o problema das folhas pesadas e duplicadas de código desaparece, pois as folhas não tem qualquer código para começar, apenas componentes. Se for necessário fazer uma alteração no nível da folha, é tão simples quanto alterar um único componente, em vez de copiar e colar o código em qualquer lugar.
É claro que, por ser tão inexperiente quanto eu, não vi nenhum problema quando comecei a usar o modelo pesado de herança de hierarquia única; portanto, se houver problemas com o modelo que estou pensando em implementar, não seria ser capaz de vê-lo.
Suas opiniões?
PS: Estou usando Java, portanto, usar herança múltipla para implementar isso em vez de usar componentes normais não é possível.
PPS: As comunicações intercomponentes serão feitas vinculando componentes dependentes entre si. Isso levará ao acoplamento, mas acho que é uma troca aceitável.