Sobre como projetar um sistema flexível de habilidades de personagem em jogos

O sistema de habilidades do personagem é talvez a flexibilidade mais exigente no jogo. É impossível prever no estágio de design quais feitiços aparecerão na versão final ou nas atualizações subseqüentes. Este post será sobre como abstraí o processo de execução de habilidades.

A capacidade em si nada mais é do que um conjunto de ações. A interface mínima da habilidade consiste em um método: "aplicar", mas não tão simples quanto às dificuldades em questão.

imagem

Toda habilidade começa com uma série de verificações para ver se ela pode ser aplicada. Entre eles estão os comuns, como verificar recarga, disponibilidade de mana, verificar distância e outros. Já é evidente aqui que nem todas as verificações são necessárias para todas as habilidades. Por exemplo, existem habilidades aplicadas a qualquer distância. Ou seja, habilidades diferentes exigem conjuntos diferentes de verificações antes da execução. No entanto, é claro que muitas das verificações serão repetidas e, muitas vezes, muitas habilidades requerem o mesmo conjunto de verificações.

No total, parte das verificações será repetida logicamente, o que significa que elas devem ser alteradas conforme acordado, ou seja, imediatamente em todos os lugares. Além disso, os conjuntos de partes das verificações no caso geral serão diferentes.

Se partes das verificações são selecionadas em objetos separados que implementam uma interface e incorporados a uma lista vinculada única, obtemos uma cadeia de responsabilidades de modelo.

imagem

No caso de uma verificação bem-sucedida no link, a verificação no próximo link será iniciada; se não houver um próximo link, toda a verificação poderá ser considerada bem-sucedida. Além da própria verificação, o link também pode conter um manipulador de erros. Por exemplo, se ao verificar a mana, descobrir que não é suficiente, o link poderá notificar o jogador sobre isso.

Usando a cadeia de tarefas, para a habilidade [Powerful Shot], podemos inserir facilmente um link adicional que verifica se o personagem está usando um arco ou um link que verifica se o personagem tem um nível de vida abaixo de 30% para a habilidade [Second Wind].

Vamos reverter e lembrar que existem cadeias de testes iguais para muitas habilidades. Vamos destacar a essência da solicitação de atendimento de capacidade e descrever cada um dos tipos de cadeias de teste com sua classe.

A solicitação é necessária apenas para elaborar uma cadeia de tarefas, iniciá-la e cancelá-la quando o jogador der o comando apropriado.

imagem

Já criaremos cadeias nas implementações de consultas.

No momento, já aprendemos como fazer testes flexíveis da capacidade de executar habilidades. Agora, no caso de uma verificação bem-sucedida, ainda é necessário cumprir a capacidade.

Eu preferi fazer isso sem alterar as interfaces, adicionando o último link sempre bem-sucedido que a capacidade executa como efeito colateral. Aqui está um exemplo de implementação:

public class TerminalChecker: ICastChecker { CastChecker next { get; set; } ISkill skill; public TerminalChecker(ISkill skill) { this.skill = skill; } public bool check() { skill.cast(); return true; } } 

Essa implementação nos permite fazer solicitações assíncronas. Isso é útil quando precisamos de informações adicionais do usuário. Por exemplo, uma habilidade deve ser aplicada a alguma área que o jogador seleciona com o mouse. Claro, você não pode parar o jogo no momento.

Agora precisamos combinar solicitações com habilidades. É claro que faremos isso usando polimorfismo adicionando uma propriedade à interface de habilidade. Nesta fase, expandimos a capacidade dessa interface:

imagem

Depois de todo o trabalho realizado, vamos pensar sobre o que é uma habilidade. Na implementação atual, este é um conjunto de ações que é precedido por uma série de verificações. Observe que em um nível alto, não somos de forma alguma dependentes da lógica específica do jogo. Com a idéia inicial de descrever o sistema de habilidades aplicado às magias, obtivemos um sistema que, de acordo com certas regras, nos dá ou não nos permite executar ações arbitrárias.

Devido a essa propriedade, este sistema pode descrever qualquer modificação no mundo do jogo. Por exemplo, uma transação de vendas ou uma equipe de construção civil.

Vamos dar uma olhada em tudo em geral novamente

imagem

Neste exemplo, uma habilidade Sprint é uma habilidade normal sem um alvo; a classe que implementa a solicitação de tais recursos é NontargetCastRequest, que por sua vez forma uma cadeia de verificações do ManaChecker, CooldownChecker e TerminalChecker.

O código de chamada não depende dos detalhes da implementação deste sistema, ou seja, não quebraremos a lógica do jogo adicionando ou alterando a capacidade.

Este é o sistema de habilidades dos personagens de uma forma mínima. Esse modelo não possui os meios de alertar o código de chamada, transferir recursos para a interface do usuário e outros detalhes da vida. Você pode pensar neles você mesmo.

Source: https://habr.com/ru/post/pt454876/


All Articles