Estou desenvolvendo um mecanismo de jogo simples (em C #, se for o caso) e não consigo pensar em uma maneira decente o suficiente para implementar scripts em termos de arquitetura.
É uma estratégia simples baseada em turnos, com animações personalizadas e independentes da lógica para batalhas. Possui uma camada de arquitetura global para sistema / coisas de baixo nível e, mais importante, dois módulos principais - lógica e visual de jogo - que se comunicam usando um gerenciador de eventos.
E o fato é que eu realmente gostaria que os scripts influenciassem tanto as coisas relacionadas à lógica do jogo (alteração dos parâmetros das unidades, etc.) quanto as relacionadas à visualização do jogo, como animações / diálogos especiais para batalhas que podem depender de um certo gatilho com script.
(Para ser sincero, o ideal é que eu queira que o script controle o fluxo do jogo, deixando apenas a mecânica / gráficos principais para a lógica / exibição, mas sou novo nisso, então não tenho certeza se posso fazê-lo agora)
Eu estive pensando em três opções:
Apenas deixe o script viver na lógica, mas informe-o sobre o lado gráfico do jogo. Mas isso tornaria a divisão lógica / visão muito vaga, não é ...
Torne o script um módulo separado que trocará eventos com os outros usando o mesmo gerenciador de eventos. Mas isso exigiria muito cuidado com a sincronização de eventos, eu acho ... e também adicionaria muitos tipos de eventos ao gerente. (Ainda, favorito pessoal)
Faça do script um módulo acima de tudo, para que ele possa influenciar / chamar diretamente as funções da lógica / exibição. Isso permite uma funcionalidade inerentemente mais ampla, com o custo de estragar todo o esquema de troca de eventos e com medo de que o script possa quebrar coisas, mesmo quando realmente não deveria.
Portanto, não posso decidir sobre um deles nem pensar em uma maneira melhor de inserir o módulo de script ... Alguma sugestão ou link útil?
Obrigado!
Ps obrigado por migrar a pergunta, não sabia que havia uma seção especializada para gamedev
fonte
Respostas:
Acredito que você deseja a terceira opção, mas descobrirá que está certo em pensar que ter eventos lógicos acontecendo em dois locais potencialmente é algo ruim. Você descobrirá que deseja que o módulo lógico do mecanismo acabe sendo um tique de atualização que faz duas perguntas 'O que eu faço agora?' e 'Como faço isso?' às quais você pode vincular scripts para lidar com a resposta a essas perguntas.
Junte isso à exposição dos objetos que contêm os dados e uma API para acessar os componentes lógicos necessários (quero dizer, você pode criar um script para a descoberta do caminho da AI, mas como esse é um trecho de código genérico que provavelmente será usado e reutilizado, por que não incorpore-o no módulo e adicione-o à API exposta à linguagem de script?). Isso deve lhe dar a acessibilidade e os locais claramente definidos onde as coisas estão acontecendo.
Mais uma vez, ressalvo isso com a mesma declaração que sempre faço. Um produto acabado de trabalho é sempre mais valioso do que uma boa teoria em programação :)
Espero que isto ajude!
fonte
Muitos tendem a subestimar o poder das linguagens dinâmicas, pensando que essa flexibilidade tem um custo de velocidade; Isso é verdade, mas muitas vezes o custo é simplesmente insignificante.
Pessoalmente, costumo desenvolver o máximo possível usando linguagens dinâmicas que exploram a expressividade e, em seguida, perfil o protótipo para entender onde e se a otimização é necessária.
No seu caso, isso significa que você deve tentar avançar para a terceira opção, desenvolvendo a parte "superior" usando uma linguagem dinâmica adequada que também pode ser usada como linguagem de script.
Muitos padrões podem ser usados depois que você coloca o dinamismo na profundidade certa. Seus scripts personalizados podem ser integrados em um sistema baseado em eventos como um sistema de retorno de chamada, quando o núcleo chama de volta para fornecer um ambiente adequado para que o script possa alterar o status global ou apenas o estado de um subconjunto de todo o sistema.
Você pode encapsular a interface que o script pode interagir usando o padrão Fachada. Nos métodos de fachada, você pode colocar a lógica que define como , quando , se o script pode usar uma funcionalidade e abstrair a interação do script a partir da implementação principal.
Sua interface de script deve fornecer os métodos de fábrica relevantes para que o script possa gerar elementos sem instancia-los diretamente; essas instâncias podem ser invólucros sobre os objetos reais, para que mais lógica de acesso de controle possa ser implementada.
fonte
O objeto de script precisa ter acesso aos outros objetos para os quais fornecerá dados. Cuidado para não passar esses outros objetos diretamente para o objeto de script. Faça isso cria uma interface quebradiça. Você pode querer ter algo como uma classe mediadora que gerencia essas referências a objetos e fornece acesso a dados para o objeto de script.
fonte
Lua é uma escolha popular para uma linguagem de script de uso geral. Você pode criar sua própria linguagem de script usando Lex e Yacc (consulte o artigo na Game Programming Gems 3), mas eu diria que a maioria de suas necessidades pode ser atendida com Lua, não importa quão grande ou pequena.
fonte