AI Framework e Eventos

Olá senhores [beware, long post]

Agora de volta à civilização e com acesso decente a interwebs posso falar mais disso…

Esses dias mexi um pouco no Horus Eye pra implementar o novo sistema de AI que discutimos nas ultimas reuniões do mês :stuck_out_tongue:
A idéia era de o sistema básico (o framework mesmo) fazer parte da UGDK, mas ai me toquei que a AI precisa ser ligada a um tipo base de “entidade” (que possa ter uma AI), o que no nosso caso é a Creature do Horus Eye, mas como isso tá só no Horus Eye por motivos óbvios, acabei fazendo tudo no Horus Eye mesmo e não toquei na UGDK.

Anyway o sistema em si já está funcionando, o que é algo muito legal hahaha, mas ainda irá necessitar de uma refatorada no código…
Por enquanto as AIs estão iguais a como estavam antes (usando o novo sistema, e já tirei o código antigo da Mummy, mas iguais em comportamento e ações), não tive tempo de adicionar nada novo ainda, pelas razões que seguem…

As classes novas que contém a lógica das AIs (são algumas classes “blocos” pequenas, por enquanto 5) são separadas da herança Sprite->WorldObject->Creature->Mummy/Hero, então elas não tem acesso as várias coisas protected das Creatures pra poderem fazer o que tem que fazer. Funcionava antes pq o código ficava na Mummy, que tem acesso. Mas not anymore. E essas coisas eram tudo protected, como por exemplo as skills (nao tinha getter pra pegar de fora), ou a função de Move() da Creature.
Então tive que fazer alguns getters e outras funções auxiliares na Mummy e na Creature (mostly na Creature).
Tinha tentado fazer com que a Creature fosse friend da classe base dos blocos de AI, mas não funfou pois como vim a descobrir, o friendship das classes é uma das poucas coisas que uma classe não herda da classe-pai. Ainda tem umas possibilidades que posso testar com esse negócio de friend, mas não sei se vai funcionar e honestamente acho que é mó POG usar friend, homicidio de OO :stuck_out_tongue:

Mas até ai, beleza, consegui fazer a AI como tava antes.

Quando fui pensar em coisas novas pra implementar (de comportamento das AIs) que me veio a duvida que é a maior razão desse post… (por sinal, sorry pelo tamanho. Se você leu até aqui, parabéns! xD)
É muito dificil fazer com que a AI perceba mudanças no mundo… pra fazer algo assim teriamos que ficar iterando por coisas a cada frame, o que não é algo legal…
Veja o seguinte exemplo: quero ter uma mumia que desvie (ou pelo menos tente) de projeteis do Kha (pelo menos o básico).
Ai vc pensa: É ridiculo! Vejo quando o Kha atira, faço uma mágica com vetores pra ver se tal tiro tá vindo na minha direção, se sim, me movo.
True story. Mas como raios vou ver como o Kha atira? Tem nada no código pra ajudar com isso. A unica solução para a AI é iterar pelos WorldObjects que o World mantém, ver os que sao Projectile, ver os que vieram do Kha, talvez ver o tempo de vida deles pra ver se eh um projetil “recente”, ver o vetor de direcao e talvez velocidade. Ou seja, trabalho pra caralho. Fora que a lista de WorldObjects do World é protected, teriamos que alterar o World pra poder acessá-la, entre outros problemas em acessar essas coisas.
Ou seja, não é trabalho pra caralho, é trabalho pra !&#$^*%A&^SDRU#YGE^!#TXUDQGWXDB!R# SBRUBLES

Minha idéia (e a razão por trás do post, fora falar que o sistema novo tá funcionando e é mó legal xD), é fazer um sistema de eventos.
Certas classes tem certos eventos (como World->New Object Added, ou Hero->Fired ), e qualquer parte do código pode registrar (ou talvez também remover) funções de callback para esses eventos. Ai quando algo desses eventos acontece, (tipo, heroi atirar), ele percorrer e executa essas funções.

Um sistema de eventos desses, e os eventos apropriados nas classes ia ajudar PAGARAIIIIO as AIs :stuck_out_tongue: e provavelmente outras partes do jogo também.

Como já to fazendo isso das AIs, me voluntario a implementar tal sistema.
Passei aqui e fiz esse post gigantesco pra discutir tal idéia, ver se realmente querem que eu implemente algo assim, e idéias de como implementá-lo.
Como percebi esses dias, meu C++ anda meio enferrujado… Umas idéias sobre como implementar poderiam ajudar xD

Como não sei bem de usar ponteiro de função em C++ e como disse meu C++ anda enferrujado, tive duas idéias parecidas:

1)fazer uma classe base EventHandler, com uma função, Call ou o operador(), sei lá. Ai as classes que tem eventos tem uma lista de EventHandlers pra cada evento, e quando o evento acontece percorre e da os Calls() neles. Os lugares que quiserem receber tal evento implementam sua classe que herda da EventHandler, com sua implementação como quiserem da tal função.

2)Classes que tem eventos também fazem uma classe auxiliar pra cuidar de tal event, tipo WhateverHandler pro evento Whatever. Ai ela tem uma lista de WhateverHandlers, e quando ele acontece, a classe percorre pelos WhateverHandlers e executa uma funcão delas. As classes que quiserem receber o evento Whatever podem herdar de WhateverHandler (pelo que lembro pode ter herança multipla em C++) mas ai fazem sua implementação da tal função.

:P

Olha sistema de eventos. Agente já pensou em fazer isso e é algo muito legal de ter. É exatamente por isso que ele está no backlog (eu lembro de ter colocado… se escrevi o cartão de fato é outro papo).
Isso é uma coisa meio grande que seria legal discutir melhor como fazer e tudo mais. Além de fazer isso quando for parte do sprint! :stuck_out_tongue:

(Desculpa por ser chato mas eu já fiz muito isso de querer fazer coisas que não tão no sprint e isso não é muito legal HAHAHAHA)

Concordo que um sistema de eventos é bem interessante, mas tenho outra sugestão (meio que paralela):

Deveria haver um modo de “observar” apenas os objetos dentro de uma janela do jogo (janela = retângulo arbitrário no mapa).
Isso não só tornaria um sistema de AI mais eficiente quando quisesse saber o que tem ao seu redor, mas também poderia ser utilizado para resolver colisões de modo mais eficiente (nem sei como é feito atualmente).

No exemplo específico de desviar de um tiro, não tenho muita idéia de qual método seria mais eficiente. Imagino que uma multidão de múmias (todas as do mapa) sendo chamada cada vez que você atira possa travar um pouco o jogo em pcs mais antigos. Mas ter todas estas múmias observando objetos próximos a elas a todo momento também pode ser ineficiente, mesmo que existam pouquíssimos objetos próximos (em média). Mas já deixaria de ser algo quadrático, assumindo que não seja possível um número arbitrário de Creatures na mesma janela, e que as janelas não sejam gigantes.

Deixando eficiência de lado, acho que a AI deveria agir mais ou menos da seguinte forma:

  1. Observa o mundo ao seu redor;
  2. Toma uma decisão (possivelmente criando um plano);
  3. Realiza um conjunto de ações de acordo com a decisão tomada.

Eventos são legais de serem utilizados em alguns casos, onde fazem sentido, mas basear o sistema de AI nisso deixaria tudo muito confuso. Você começa a perder a visão do todo, fica tudo quebrado em coisas independentes, que podem acabar interferindo entre si e gerando comportamentos estranhos e indesejados.

Omar’s surprise attack!

Primeiramente, muito bom Omar =P

Segundamente, como você deve ter visto, Omar, fazer um sistema de eventos requer maior discussão, sendo que talvez não seja necessário para tudo no sistema de AI (como ressaltou o Jeff).

Sugiro, como o Henrique, que a questão seja melhor discutida E produzida dentro de um Sprint.

Só pra chegar causando, digo que para fazer uma múmia desviar de um projétil basta fazer o projétil repelir ela. Isso poderia ser trivialmente feito se existisse um certo sistema de física isométrica que tratasse corpos com campos de força. XD

cough cough rWindows cough

É acabei falando com o Henrique depois e decidimos esperar até as reuniões pra discutir melhor isso… Tinha alguma outra coisa que ele tinha falado também quando conversamos, mas não lembro agora :stuck_out_tongue:

E Wil, projétil repelir mumia (ou o contrário) é BEM diferente de múmia desviar de projétil :stuck_out_tongue:
Imagine você (ou qualquer outro humano) desviando de um projétil (tipo uma bala). Você “desviar” dela é você ter o capacidade (fisica e mental) pra se mexer e sair do caminho do projétil - ou seja, é algo que num jogo, uma AI devia calcular e fazer; Enquanto você ter um escudo mágico que deflete as balas é algo bem diferente (alguma skill da mumia ou sei la) :stuck_out_tongue:
Um projétil que empurra seus alvos pra não acertar eles é MUITO idiota então não falo mais disso xD

Em outra nota, como já fiz no Bridge Commander um sistema de gravidade e anti-gravidade entre planetas, naves e projéteis, que nada mais é que um sistema de forças de atração e repulsão, digo que fazer um negócio desses não é dificil, e dá uns resultados legais, e mais de tudo, divertidos hehehehehe xD
Mas este não é o ponto aqui :stuck_out_tongue:
Por sinal podia até ser legal o Kha ter umas magias de defesa, tipo um escudo anti-projeteis-das-mumias ou um “escudo” pra repelir mumias que chegam perto dele pra longe… Mas again, offtopic here.

Edit: lembrei das bolinhas/particulas do Wil agora hahahaha
Mas well, ele fez aquilo em Java, tava predestinado a dar merda (sorry Wil) =P

Edit2: esqueci de responder o negócio do Jeff… Sobre os eventos e AIs, não to falando pra basear as AIs somente nisso… GOD NO.
Mas é que o fluxo de execução das AIs podem ser divididos em basicamente 2 coisas, condições e ações (codigo normal que não é uma condição, digamos). Ambos podem ser feitos (e já são assim no framework agora) com o antigo padrão do Update lógico a cada frame. Inclusive tal método acho que é o melhor para as ‘ações’.

A questão dos eventos é em relação às condições. Sim, dá pra fazer elas pelo método do Update - a AI antiga do Horus Eye que eu “portei” pro framework novo faz assim com as condições que ela tem - e em alguns casos é o melhor método, mas em outros casos (como o que eu mencionei no primeiro post) um método de evento pra mudar uma condição é melhor.

Não é que o projétil empurra as múmias para longe, elas é que “se afastam dele”. Na implementção, fica sendo uma repulsão, mas visualmente, as múmias “evitam” o projétil =P. Até porque eu sinto que se fôssemos implementar essa AI especificamente seria exatamente isso o que faríamos: a múmia “fugir” para longe do projétil.

Enfim, só queria causar um pouco para enxer o Henrique, na verdade. Ele deve ter entendido XD.

E não se preocupe, Omar, eu tenho planos para fazer um sistema de física mais feliz para a PyramidWorks, então suas matutações são bem-vindas.

Wil, eu entendi e o ignorei com a mesma facilidade. =P
Agora Omar, eu exatamente não lembro o que foi essa outra coisa que comentei. Talvez seja que eu já pensei em como encaixar/o que usar, mas não lembro se foi isso…