Suponha que você tenha um jogo no qual existem muitas (muitas) entidades que cumprem algumas funções, nem todas são constantemente necessárias ou precisam ser consideradas em todos os quadros. O problema concreto em que estou trabalhando, no qual esse problema está presente, é uma simulação detalhada de um corpo, incluindo seus órgãos.
No jogo, cada criatura tem seu próprio corpo, que é separado em partes menores (tronco, pernas, etc.) e, às vezes, essas partes contêm órgãos, que desempenham uma função específica dentro do corpo. Se um órgão atualmente serve ou não a um objetivo ou está ativo nunca é realmente claro. Afinal, um animal pode estar com o estômago vazio e, portanto, não precisa digerir nada. Seria bastante ridículo verificar ou simular cada objeto em cada quadro e muito caro assim que você tiver muitas criaturas no mundo. Então, eu estava pensando em uma maneira inteligente de diferenciar entre objetos que precisam ser atualizados e aqueles que não precisam.
O que eu criei parece uma solução pelo menos aceitável. Ele cria uma fila / pilha simples (essencial é que cada elemento seja removido assim que for lido; a ordem é irrelevante) chamada de "pilha de atenção" onde residem os objetos que precisam ser simulados. Objetos que precisam de atenção simplesmente se colocam na pilha ou são colocados lá por outros objetos. Esses objetos provavelmente implementariam uma interface simples com uma função simulate ().
Aplicado ao meu exemplo de digestão anterior, isso significaria:
O jogador escolhe algo para comer (suponha que seja pão) no inventário e o coloca na boca de seu personagem, e a boca é colocada na pilha de atenção. No próximo quadro, a boca é retirada da pilha e sua função simular () - é chamada. Como é uma boca, seria razoável simular a mastigação aqui. Isso pode continuar por alguns quadros em que a boca continua se colocando na pilha até decidir que o alimento está pronto para ser engolido. Nesse caso, a boca coloca o pão mastigado no estômago (eu sei que ele não vai diretamente para lá, mas o esôfago é deixado de fora para simplificação), que também é colocado na pilha de atenção. No próximo quadro, a simulação do processo de digestão é iniciada. E assim por diante para o restante dos órgãos necessários.
Um problema previsível com isso são os objetos inativos. Um animal adormecido é um bom exemplo disso. Isso pode ser feito conforme descrito anteriormente, mantendo o animal adormecido na pilha e verificando cada vez que ele precisa acordar, mas isso parece um desperdício, pois é a única coisa a ser feita. Para tornar os objetos ociosos mais eficientes, eu planejava adicionar um tipo de agendamento que armazena os trabalhos a serem executados em um horário específico. Se um animal for dormir, colocará um trabalho nesse horário que seria agendado por um certo período de tempo após o animal dormir. Esse trabalho cuidaria de colocar o animal adormecido na pilha de atenção novamente. Agora, você pode dizer que um animal adormecido que não está na pilha de atenção pode deixar de ser atacado por algo porque sua IA não é simulada,
Agora, sinceramente, não sei se isso é mesmo uma solução elegante para esse problema devido à falta de experiência. Estou perto de algo utilizável? Como isso geralmente é feito ou alguém tem sugestões ou soluções melhores?
fonte
Parece um problema semelhante ao das entradas: você tem mais de 100 teclas no teclado, mas não deseja verificar cada tecla individual em cada quadro; então, o que você faz?
Duas respostas: sondagem ou mensagens do sistema.
Polling = em qualquer momento em que isso realmente importe no jogo, consulte o estado das teclas do teclado (ou dos objetos, no seu caso). O resto do tempo, ignore-os.
Mensagens = faça com que cada tecla do teclado (objeto) coloque algo em uma fila de mensagens quando pressionada ou liberada (quando precisar de atenção). Em cada iteração do loop do jogo, ele examina a fila e resolve todas as mensagens antes de continuar.
fonte
Então, vou dar um passo atrás na implementação e revisar a questão da perspectiva do design. Você tem um plano sólido para exibir todos os detalhes que deseja incluir nesta simulação?
Por exemplo:
Basicamente, a regra geral é não tornar sua simulação mais complicada do que suas saídas. No final do dia, se as únicas animações que você tem para ovelhas são pastar, dormir, fugir. Então, realmente não importa quantos fatores entram na decisão sobre qual estado escolher. Todos os jogadores vão ver ovelhas que dormem à noite, fogem do perigo e comem durante o dia.
A simulação de comportamento é muito divertida de se trabalhar, mas mantenha sempre em mente a experiência do usuário final.
fonte
Eu tive um problema semelhante em um jogo em que trabalhei alguns anos atrás - a simulação de objetos era complexa e não podia realmente ser realizada em detalhes em todos os objetos do mundo.
A solução foi usar o conceito LOD para a simulação. Objetos dentro da visão do jogador executariam a simulação completa. Objetos distantes do player executavam uma simulação altamente simplificada periodicamente. À medida que os objetos apareciam, os jogadores passavam do curso, atualização periódica da simulação para atualizações detalhadas e regulares.
fonte
Solução com um cronograma é bom. Observe que toda entidade deve ter uma lista de indicadores para suas ações futuras, o que oferece a possibilidade de invalidar ações futuras, se necessário. Ou seja. o animal adormecido acorda instantaneamente quando atacado, então você deve invalidar sua ação de despertar no futuro.
fonte
Existe um padrão de design para isso. Eu acho que é chamado de objetos de banco de dados?
Basicamente, você mantém uma ovelha "modelo" que pode representar todas as ovelhas não especiais do mundo do jogo, desenha-as da mesma maneira, mantendo os dados exclusivos dentro do objeto modelo, digamos, como uma tabela de locais e / ou hora das ovelhas desde o cisalhamento. Então, sempre que precisar tornar uma ovelha única, é possível criar uma instância específica para rastrear essa ovelha única.
O mesmo vale para animações. Se for uma animação inativa ou evento comum a todas as instâncias, poderá residir na instância do modelo, onde animações mais específicas podem ser agendadas separadamente.
Há muito tempo, escrevi um jogo para um concurso de programação cujo loop principal chamava de animate () em toda a cena. Utilizou ponteiros de função para substituir animações inativas por outras, conforme necessário, e usou a técnica para oferecer suporte a animações herdadas (por exemplo, girar um personagem que está em um disco giratório).
É de natureza semelhante ao uso de um delegado para animação.
fonte
Uma máquina de estado funcionaria? O animal está, por exemplo, no estado de sono, estado de alimentação, estado de corrida, etc. Para cada estado, você associa uma lista de órgãos ativos. Assim, cada quadro que você visita cada animal, ativa o estado, lista de órgãos para esse estado e executa a atualização em cada um dos órgãos.
fonte