Eu tenho lutado com como implementar scripts no meu mecanismo de jogo. Eu só tenho alguns requisitos: deve ser intuitivo, não quero escrever uma linguagem personalizada, analisador e intérprete e não quero usar o encadeamento. (Tenho certeza de que há uma solução mais simples; não preciso do incômodo de vários segmentos da lógica do jogo.) Aqui está um exemplo de script, em Python (também conhecido como pseudocódigo):
def dramatic_scene(actors):
alice = actors["alice"]
bob = actors["bob"]
alice.walk_to(bob)
if bob.can_see(alice):
bob.say("Hello again!")
else:
alice.say("Excuse me, Bob?")
Essa peça épica de contar histórias apresenta problemas de implementação. Não posso apenas avaliar todo o método de uma só vez, porque walk_to
leva tempo de jogo. Se ele retornar imediatamente, Alice começará a caminhar até Bob e (no mesmo quadro) dirá olá (ou seja cumprimentada). Mas sewalk_to
é uma chamada de bloqueio que retorna quando ela alcança Bob, meu jogo fica paralisado, porque está bloqueando o mesmo segmento de execução que faria Alice andar.
Eu considerei tornar cada função enfileirar uma ação - alice.walk_to(bob)
empurraria um objeto para uma fila, que seria disparada depois que Alice alcançasse Bob, onde quer que ele estivesse. Isso é mais sutilmente quebrado: o if
ramo é avaliado imediatamente, para que Bob possa cumprimentar Alice, mesmo que esteja de costas para ela.
Como outros mecanismos / pessoas lidam com scripts sem criar threads? Estou começando a procurar em áreas que não sejam desenvolvedores de jogos, como cadeias de animação jQuery, para obter idéias. Parece que deve haver alguns bons padrões para esse tipo de problema.
Respostas:
A maneira como algo como o Panda faz isso é com retornos de chamada. Em vez de bloquear, seria algo como
Ter um retorno de chamada completo permite que você encadeie esses tipos de eventos com a profundidade que desejar.
EDIT: Exemplo de JavaScript, pois possui melhor sintaxe para este estilo:
fonte
O termo que você deseja pesquisar aqui é " corotinas " (e geralmente a palavra-chave do idioma ou o nome da função é
yield
).A implementação dependerá primeiro do seu idioma. Para um jogo, você deseja que a implementação seja o mais leve possível (mais leve que os fios ou até as fibras). A página da Wikipedia (vinculada) possui alguns links para várias implementações específicas de idiomas.
Ouvi dizer que Lua tem suporte interno para corotinas. O mesmo acontece com o GameMonkey.
O UnrealScript implementa isso com o que chama de "estados" e "funções latentes".
Se você usa C #, pode ver esta postagem do blog de Nick Gravelyn.
Além disso, a idéia de "cadeias de animação", embora não seja a mesma coisa, é uma solução viável para o mesmo problema. Nick Gravelyn também tem uma implementação em C # disso .
fonte
yield return walk_to();
em seu script.não enroscar é inteligente.
A maioria dos mecanismos de jogos funciona como uma série de estágios modulares, com coisas na memória que conduzem cada estágio. Para o seu "passeio ao exemplo", você geralmente tem um estágio de IA em que seus personagens caminhados estão em um estado em que não deveriam procurar inimigos para matar, um estágio de animação em que deveriam executar a animação X, um estágio de física (ou estágio de simulação), onde sua posição atual é atualizada etc.
no seu exemplo acima, 'alice' é um ator composto por peças que vivem em muitos desses estágios; portanto, um ator bloqueador. para tomar muitas decisões.
Em vez disso, uma função 'start_walk_to' provavelmente faria algo como:
Em seguida, o loop principal executa seu tick ai, seu tick físico, seu tick de animação e tick de cena, e o cutscene atualiza o estado de cada um dos subsistemas do seu mecanismo. O sistema de cena deve definitivamente rastrear o que cada uma de suas cenas está fazendo, e um sistema acionado por corotina para algo linear e determinístico como uma cena de corte pode fazer sentido.
O motivo dessa modularidade é que ela mantém as coisas simples e agradáveis e, para alguns sistemas (como física e IA), você precisa conhecer o estado de tudo ao mesmo tempo para resolver as coisas corretamente e manter o jogo em um estado consistente .
espero que isto ajude!
fonte