Eu projetei um sistema de entidades para um FPS. Basicamente, funciona assim:
Temos um objeto "mundo", chamado GameWorld. Isso contém uma matriz de GameObject, bem como uma matriz do ComponentManager.
GameObject contém uma matriz de Component. Ele também fornece um mecanismo de evento que é realmente simples. Os próprios componentes podem enviar um evento para a entidade, que é transmitido para todos os componentes.
Component é basicamente algo que dá ao GameObject certas propriedades e, como o GameObject é na verdade apenas um contêiner, tudo o que tem a ver com um objeto do jogo acontece nos componentes. Exemplos incluem ViewComponent, PhysicsComponent e LogicComponent. Se a comunicação entre eles for necessária, isso poderá ser feito através do uso de eventos.
ComponentManager apenas uma interface como Component e, para cada classe Component, geralmente deve haver uma classe ComponentManager. Esses gerenciadores de componentes são responsáveis por criar os componentes e inicializá-los com propriedades lidas a partir de algo como um arquivo XML.
O ComponentManager também cuida de atualizações em massa de componentes, como o PhysicsComponent, onde usarei uma biblioteca externa (que faz tudo no mundo de uma só vez).
Para configurabilidade, usarei uma fábrica para as entidades que lerão um arquivo XML ou um script, criarão os componentes especificados no arquivo (que também adiciona uma referência a ele no gerenciador de componentes certo para atualizações em massa) e injete-os em um objeto GameObject.
Agora vem o meu problema: vou tentar usar isso para jogos multiplayer. Não tenho ideia de como abordar isso.
Primeiro: quais entidades os clientes devem ter desde o início? Eu deveria começar explicando como um mecanismo para um jogador determinaria quais entidades criar.
No editor de níveis, você pode criar "pincéis" e "entidades". Escovas são para coisas como paredes, pisos e tetos, formas basicamente simples. As entidades são o GameObject de que falei. Ao criar entidades no editor de níveis, você pode especificar propriedades para cada um de seus componentes. Essas propriedades são passadas diretamente para algo como um construtor no script da entidade.
Quando você salva o nível para o mecanismo carregar, ele é decomposto em uma lista de entidades e suas propriedades associadas. Os pincéis são convertidos em uma entidade "worldspawn".
Quando você carrega esse nível, apenas instancia todas as entidades. Parece simples, não é?
Agora, para conectar em rede as entidades, encontro vários problemas. Primeiro, quais entidades devem existir no cliente desde o início? Supondo que o servidor e o cliente possuam o arquivo de nível, o cliente também pode instanciar todas as entidades no nível, mesmo se elas existirem apenas para fins de regras do jogo no servidor.
Outra possibilidade é que o cliente instancia uma entidade assim que o servidor envia informações sobre ela, e isso significa que o cliente terá apenas entidades de que precisa.
Outra questão é como enviar as informações. Eu acho que o servidor poderia usar a compactação delta, o que significa que ele só envia novas informações quando algo muda, em vez de enviar um instantâneo para o cliente em cada quadro. Embora isso signifique que o servidor deve acompanhar o que cada cliente sabe no momento.
E, finalmente, como a rede deve ser injetada no mecanismo? Estou pensando em um componente, NetworkComponent, que é injetado em todas as entidades que deveriam estar em rede. Mas como o componente de rede deve saber quais variáveis devem ser acessadas e como acessá-las e, finalmente, como o componente de rede correspondente no cliente deve saber como alterar as variáveis de rede?
Estou tendo um grande problema para abordar isso. Eu realmente aprecio se você me ajudou no caminho. Estou aberto a dicas sobre como melhorar o design do sistema de componentes, portanto, não tenha medo de sugerir isso.