Como implementar um sistema baseado em componentes para itens em um jogo na web

7

Lendo várias outras perguntas e respostas sobre o uso de um sistema baseado em componentes para definir itens, quero usar um para os itens e feitiços em um jogo da Web escrito em PHP. Estou apenas preso na implementação.

Vou usar um esquema de banco de dados sugerido nesta série (a parte 5 descreve o esquema);
http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/

Isso significa que terei uma tabela de itens com propriedades genéricas, uma tabela listando todos os componentes de um item e, finalmente, registros em cada tabela de componente usada para compor o item.

Supondo que eu possa selecionar os dois primeiros juntos em uma única consulta, ainda vou fazer N consultas para cada tipo de componente. Eu estou bem com isso, porque posso armazenar em cache os dados no memcache e verificá-los primeiro antes de fazer qualquer consulta. Precisarei criar os itens em todas as solicitações em que eles são usados, para que a implementação precise estar do lado do lean, mesmo se forem extraídos do memcache.

Mas é aí que me sinto confiante em implementar um sistema de componentes para meus itens terminar. Eu acho que precisaria trazer atributos e comportamentos para o contêiner de cada componente que ele usa. Só não sei como fazer isso de maneira eficaz e não acabarei escrevendo muito código especializado para lidar com cada componente.

Por exemplo, um AttackComponent pode precisar saber como filtrar alvos dentro de um contexto de batalha e também talvez fornecer um comportamento de ataque. Esse mesmo item também pode ter um UsableComponent que permite que o item seja usado e aplique algum efeito em um conjunto diferente de destinos filtrados de maneira diferente no mesmo contexto de batalha. Então, nem todas as partes de um item são partes ativas, um AttributeBonusComponent pode precisar ativar apenas quando o item estiver em um estado equipado ou ao exibir a página de detalhes do item.

Por fim, como devo reunir todos os componentes no contêiner para que, quando eu uso um item como arma, obtenho a lista correta de alvos? Sabe quando uma arma também pode ser usada como item? Ou para aplicar os bônus que o item fornece a um objeto de personagem?

Sinto como se tivesse ido longe demais na toca do coelho e não consigo entender a solução simples à minha frente. (Se aquilo fizer algum sentido.)

Da mesma forma, se eu implementasse a melhor resposta daqui, sinto que teria muitas das mesmas perguntas.
Como modelar vários "usos" (por exemplo, arma) para inventário / objeto / itens utilizáveis ​​(por exemplo, katana) em um banco de dados relacional

Landstander
fonte

Respostas:

4

Parece que você está usando modelagem relacional. Existe um método alternativo: modelagem de propriedade / protótipo, que Steve Yegge usou para criar seu MMORPG "extensível em última instância", Wyvern . Basicamente, cada objeto do jogo é armazenado como um único blob (apenas uma consulta por objeto) que é analisado em uma lista de propriedades após a recuperação. A flexibilidade das listas de propriedades permite que diferentes objetos do jogo tenham conjuntos de propriedades diferentes, conforme necessário.

O Universal Design Pattern de Yegge aborda profundamente a modelagem de propriedades / protótipos. As postagens do blog de Steve tendem a ser bastante longas, então tentarei apontar para as seções relevantes e resumir os pontos relevantes para sua pergunta:

  1. O Wyvern usa uma implementação do Padrão de Propriedades. Um objeto de jogo é basicamente um saco de propriedades arbitrárias. Qualquer objeto pode servir como protótipo para qualquer outro objeto, resultando em uma incrível flexibilidade aberta.
  2. Listas de propriedades persistentes. Existem vários métodos de serializar e salvar listas de propriedades. O Wyvern usa um banco de dados, "colocando a lista de propriedades serializadas em XML em uma coluna de texto / clob e desnormalizando os vinte ou trinta campos ... necessários para consultas em suas próprias colunas".
  3. O armazenamento de dados das listas de propriedades agora precisa de um método para fazer consultas sobre elas. Steve faz várias sugestões. Consultas simples baseadas em texto não funcionam bem para dados hierárquicos. Bancos de dados XML ou JavaScript / JSON + jQuery podem ser respostas para esse problema.
Leftium
fonte
11
Eu quase parei de ler quando você sugere um blob e pensou que sua resposta sugeriria o MongoDB ou alguma outra solução NoSQL. Em vez disso, oferece uma direção diferente dos componentes. Claro, essa abordagem pode funcionar melhor no NoSQL, mas há muito mais aqui do que apenas uma resposta 'use NoSQL'.
Landstander
4

Eu implementaria um sistema de gancho (um mecanismo pelo qual retornos de chamada para funções especificáveis ​​podem ser adicionados e removidos de um objeto quando ocorrem eventos) no contêiner, e teria componentes que configurassem os ganchos apropriados quando adicionados e os derrubariam quando removidos. Por exemplo, o AttributeBonusComponent pode usar atEquipe atUnequiphooks para adicionar e remover seu bônus, o AttackComponent pode fornecer valores pollForTargetse pollForAttackBehaviorshooks e o UsableComponent pode conversar pollForUseBehaviors.

Portanto, o contêiner acaba tendo apenas um entendimento abstrato dos tipos de informações que podem ser solicitadas e das maneiras com as quais ele pode interagir, e os componentes são responsáveis ​​por definir como eles interagem com elas.

caos
fonte
2

Parece que você está perdendo o objetivo desse tipo de sistema de entidades. Se você está "carregando todos os componentes todas as vezes", não terá quase nenhum benefício com isso.

Você deve configurá-lo para que todos os dados necessários para uma determinada classe de operação (por exemplo, para "resolver ataques") sejam agrupados em um único componente.

Essencialmente, imagine que você precisa escrever o código principal de alguma parte do seu jogo, completo com os principais casos especiais, e deseja especificar quais dados serão necessários desde o início desse código até o final. Esse é um componente (você pode dividi-lo em componentes menores, mas apenas se necessário, porque algumas partes são (re) usadas posteriormente por outro código).

Então, quando você tiver casos especiais, poderá editar seu componente principal (geralmente: não) ou inventar componentes extras que permitam que todas as entidades existentes continuem trabalhando e todo o código existente continue inalterado.


fonte
Não pretendo entender o sistema de componentes. Parte da minha confusão é tentar usá-lo em um ambiente sem estado e ainda estou pensando / construindo a conexão entre, digamos, os componentes físicos, de renderização e de entrada freqüentemente mencionados nos artigos em partes de uma estrutura ou script.
Landstander
1

Lembre-se das regras para otimização !

  1. Não.
  2. Ainda não (apenas para especialistas).

Por exemplo, um AttackComponent pode precisar saber como filtrar alvos dentro de um contexto de batalha e também talvez fornecer um comportamento de ataque. Esse mesmo item também pode ter um UsableComponent que permite que o item seja usado e aplique algum efeito em um conjunto diferente de destinos filtrados de maneira diferente no mesmo contexto de batalha. Então, nem todas as partes de um item são partes ativas, um AttributeBonusComponent pode precisar ativar apenas quando o item estiver em um estado equipado ou ao exibir a página de detalhes do item.

É realmente um problema se você carregar todos os componentes (AttackComponent, UsableComponent, AttributeBonusComponent), mesmo que todos, exceto um, não sejam utilizados?

Leftium
fonte
Eu deveria ter sido mais claro. Pretendo carregar todos os componentes sempre que precisar do item. Os modificadores de atributo não são partes ativas, como o item retornar uma lista de destinos quando houver dados, mas apenas aplicar alguns números quando o item estiver equipado. É claro que posso estar pensando nisso tudo errado também.
Landstander
1

"Sinto como se tivesse ido longe demais na toca do coelho"

Sim, exatamente. Os sistemas baseados em componentes ainda estão na fase 'moda', onde não há acordo sobre a melhor forma de usá-los. Várias pessoas competentes e com conhecimento postaram artigos sugerindo seu uso, mas cada uma tende a discordar sobre como você as reúne, como elas se comunicam e assim por diante.

Minha opinião pessoal é que o modelo relacional ao qual você se vinculou é abstrato demais para o uso diário.

Em vez disso, eu examinaria mais de perto o seu próprio design e veria quais aspectos comuns da funcionalidade podem ser levados em consideração para formar componentes intercambiáveis. Provavelmente será muito mais proveitoso do que tentar incorporar seu jogo a uma noção preconcebida de quais componentes devem ser.

Kylotan
fonte
Eu concordo que existe uma falta de acordo sobre qual estilo de implementação é mais vantajoso que o seguinte, mas, dado o número de mecanismos altamente bem-sucedidos usando sistemas de componentes, eu dificilmente o descreveria como um "modismo".
Kynth
Realmente não existem muitos mecanismos usando esses sistemas, certamente não o suficiente para justificar a quantidade de pessoas interessadas em fazê-los. (O único em que posso pensar agora é o Unity.) Isso não é uma crítica à abordagem, apenas uma reflexão sobre o interesse desproporcional nesse tópico no momento em relação à quantidade de software que realmente o utiliza.
Kylotan
0

Pelo que entendi a série de artigos referenciados no Entity Systems, seu "item" é carregado com componentes. E um componente é uma lista de referências. A seguir, com o seu exemplo: AttackComponent incluirá referências de como o "item" ataca; o AttackTargetComponent incluirá referências a mecanismos para obter a lista de destinos; e assim por diante. Portanto, quando o seu "item" ataca um ou mais alvos - ele usa o AttackComponent e o AttackTargetComponent ou aciona um método externo com base no item (e em seus componentes). Obrigado por compartilhar esses artigos.

kosmoknot
fonte