Em inglês a palavra Steering pode ser traduzida como direcionar, conduzir ou ainda pilotar. O termo comportamento, no inglês Behavior, é apresentado como forma de decisão e das ações feitas por um agente autônomo. Portanto, Steering Behaviors podem ser traduzidos como comportamentos de condução de agentes. Na GDC de 1999 foi apresentado o artigo “Steering Behaviors For Autonomous Characters” por Craig Reynolds. O artigo apresenta um conjunto de soluções para permitir a habilidade navegação de agentes em ambientes de forma autônoma.

No artigo Craig Reynolds define agentes autônomos que representam personagens em uma história ou jogo com a habilidade de improvisar suas ações. Um agente autônomo que pode existir isoladamente, ou ainda em ambientes multiagentes.

Considere o seguinte exemplo: em uma fazenda existe um cowboy com seu cavalo, o chefe desse cowboy, um rebanho de ovelhas, sendo que uma delas está isolada das outras. O chefe fala para o cowboy juntar a ovelha isolada com as outras. O cowboy sobe em seu cavalo e conduz essa ovelha, possivelmente evitando obstáculos no caminho, para junto das outras. Nesse exemplo, o chefe representa a seleção de ação, observando que existia uma ovelha separada das outras e determinando como objetivo manter todas juntas. O cowboy representa a condução, ao determinar o um sub conjunto de objetivos (aproximar da ovelha, evitar obstáculos e guiar a ovelha). Através de comandos o cowboy conduz seu cavalo até a ovelha. Por fim, o cavalo representa a locomoção, ao receber os comandos do cowboy e se movimentando de acordo. O cavalo também considera  ao se movimentar sua percepção visual, seu senso de balanço, seus músculos aplicando torque em suas juntas e em seu esqueleto.  Em Steering Behaviors o foco é a camada de condução, não nos preocuparemos, nesse momento com a criação de estratégias, planejamento e objetivos.

A estrutura mais simples de um agente descrita por Peter Norvig e Stuart Russell em “Artificial Intelligence: A Modern Approach”, apresentada na aula anterior, contém sensores, atuadores que interagem com o ambiente, assim como um algoritmo que faz uma tomada de decisão. Observe que a estrutura utilizada por Craig Reynolds para seus agentes é bastante compatível com a apresentada no livro. Entretanto, a estrutura apresentada por Craig Reynolds isola em cada camada um agente diferente. O chefe, o cowboy, o cavalo e as ovelhas cada um deles são agentes diferentes com diferentes atuadores e sensores no ambiente.

Locomoção

A camada de locomoção, o cavalo no exemplo anterior, é a encarnação do personagem e converte sinais do controle do movimento enviados pela camada de condução em movimento. O movimento em si está sujeito às restrições impostas pelo corpo físico do modelo, ou seja, o movimento está limitado pelas forças que podem ser criadas/aplicadas no corpo.

No exemplo anterior, o cavalo do cowboy é um dos possíveis exemplos da camada de locomoção. As decisões de condução são convertidas em sinais para o cavalo que então os converte em movimento. É importante fazer uma distinção entre condução e movimentação para manter os componentes separados. Por exemplo, imagine exatamente o mesmo exemplo anterior, entretanto o ano é 3017. No ano 3017 devido aos apoio popular, é ilegal a utilização de cavalos em fazendas para montaria já que é considerado maus tratos. A escolha popular para deslocamentos rápidos e de curta distância são motos movimentadas por energia solar. Nessa fazenda futuristas o objetivo e as regras de condução continuam as mesmas, o que mudou foi a camada de locomoção. Anteriormente utilizava-se um cavalo, agora se utiliza a moto e o trabalho de condução feito pelo cowboy é exatamente o mesmo o que muda são os parâmetros. 

Modelo Simples de Veículo

No artigo original, Craig Reynolds, considera que os comportamentos de condução são independentes do sistema de locomoção, também chamado de veículo, busca ser simples e genérico.

O modelo de veículo utilizado por Reynolds é baseado num ponto de massa, ou seja, utiliza um modelo de partículas. Essa escolha foi feita por ser bastante simples e barata a utilização de modelos físicos computacionalmente. Uma partícula é definida por sua posição, massa e velocidade. A velocidade é modificada ao se aplicar forças, como se trata de um veículo essas forças geralmente são auto-aplicáveis, e, portanto, são limitadas.

“For example, a typical force which adjusts a vehicle’s velocity is thrust, generated by the vehicle’s own power plant, and hence limited in magnitude by the capacity of the power plant. For the simple vehicle model, this notion is summarized by a single “maximum force” parameter (max_force).” - Craig Reynolds,  “Steering Behaviors For Autonomous Characters”

Assim como existe uma força máxima que pode ser auto-aplicada por um veículo existe também uma velocidade máxima. Essa característica da velocidade máxima é mantida fazendo-se um truncamento do parâmetro velocidade. Por último também existe a orientação, que combinada com a velocidade e a posição do veículo formam um espaço de coordenadas em que o modelo do veículo pode ser adicionado.

Portanto um modelo simples de veículo contém os seguintes componentes:

NomeTipo de Dados
MassaEscalar
PosiçãoVetor
VelocidadeVetor
ForçaMaximaEscalar
VelocidadeMaximaEscalar
OrientaçãoN Vetores básicos

A maneira mais simples de simular a física desse modelo de veículo é utilizar a integração Euleriana. A cada passo da simulação, que tem as forças aplicadas determinadas pelo comportamento de condução e são limitadas pela força máxima, são aplicadas no ponto de massa do veículo. Isso produz uma aceleração igual a força de condução dividida pela massa do veículo. Finalmente essa aceleração é adicionada na antiga velocidade e produz uma nova velocidade que novamente é truncada pela velocidade máxima. O pseudocódigo desta simulação é o seguinte:

steeringForce = truncate(steeringDirection, maxForce); acceleration = steeringForce / mass; velocity = truncate ( velocity + aceleration, maxSpeed); position = position + velocity

Com o objetivo de manter a velocidade e a orientação corretas é feito um ajuste incremental no passo anterior. A orientação de um objeto pode ser representada por 4 vetores: um vetor indicando a posição e três vetores indicando a rotação desse objeto no espaço conhecidos como: forward, up and side. Para manter esses vetores corretamente alinhados, esses vetores básicos devem ser rotacionados para a nova  direção. Se a velocidade atual é zero, então a antiga orientação é mantida. Ao invés de explicitamente executar rotações, esse espaço local é re-construído utilizando uma combinação de substituição, aproximação e re-ortogonalização. Esse processo é representado pelo seguinte pseudocódigo:

newForward = normalize(velocity) approximateUp = normalize(approximateUp) //Se necessário newSide = cross(newForward, approximateUp) newUp = cross(newForward, newSide)

A idéia básica é que o aproximateUP é quase perpendicular a direção de newForward já que a diferença é muito pequena entre um frame e outro. Para determinar o vetor newSide é utilizado o produto vetorial entre o newForward e o approximateUP. Com a definição do vetor newSide e de newForward é possível fazer um novo produto vetorial e obter o newUp. Por conta dessa atualização da orientação, essa técnica não consegue simular efeitos como derrapagem e rodopios.

Comportamentos de Condução

Cada um comportamentos utiliza uma velocidade desejada que é parametrizada, dessa maneira se quisermos combinar mais de um comportamento é só somar todas essas velocidades desejadas. 

Seek (Perseguir um alvo fixo) x Flee (Fugir de um alvo fixo)

O comportamento Seek busca conduzir o agente até uma posição especificada no mapa do mundo com a velocidade máxima permitida. Por conta dessa característica, se um personagem continuar perseguindo um alvo fixo eventualmente ele irá passar através deste alvo. O comportamento Flee é exatamente o contrário do seek, nesse comportamento o agente foge de uma posição especificada do mapa.

O pseudo código do Seek funciona da seguinte maneira:

desiredVelocity = normalize(target-position)* maxSpeed; steering = desiredVelocity - velocity;

Arrive

O comportamento Arrive é bastante parecido com o Seek. Entretanto, o comportamento arrive busca fazer o agente parar no ponto especificado. Para isso é calculada distância entre o destino e o agente se a distância for maior que um limiar pré determinado, então utiliza-se a velocidade máxima. Caso contrário, multiplica-se a essa velocidade máxima por distância / limiar.

Pursuit (Perseguir alvo móvel) x Evasion (Fugir de alvo móvel)

O comportamento Pursuit é bastante similar ao Seek. Nesse comportamento o objetivo do agente é “capturar” o outro agente. É diferente de apenas seguir o outro agente já que para perseguir um alvo é necessário fazer uma previsão de onde ele estará no futuro.

O mesmo vale para o comportamento Evasion, a diferença que ao invés de tentar capturar um alvo móvel, o agente tentará fugir deste alvo.

Wander

Em algumas situações é interessante que o agente percorra o mapa de maneira aleatória. Entretanto, apesar do agente estar andando aleatório é interessante que esse passeio seja feito de maneira visualmente agradável e realista. Se um jogador observar um caminho definido ou ainda movimentos irrealistas, ele vai rir, ou pior ainda vai conseguir antecipar o comportamento do agente. O objetivo do comportamento wander é produzir um movimento suave e “casual”, como se estivesse realmente passeando pelo ambiente.

Uma das maneiras de implementar esse comportamento é utilizando o comportamento seek para pontos distantes e que mudem de localização de tempos em tempos.

Outra forma de se implementar foi apresentada por Craig Reynolds em seu artigo. A idéia básica é produzir pequenos e aleatórios deslocamentos e somar a velocidade atual do agente a cada frame do jogo. O objetivo é usar pequenas alterações em cada frame com o objetivo de prevenir que o agente mude de rota de forma muito abrupta.

Obstacle Avoidance

Esse comportamento permite ao agente desviar de objetos. É importante destacar que o comportamento Obstacle Avoidance é bem diferente do comportamento Flee. No comportamento Flee, o agente irá “correr” daquele ponto sempre, já no Obstacle Avoidance o agente será conduzido para desviar quando estiver perto do obstáculo diretamente. Observe também que o comportamento obstacle avoidance não é o mesmo que detecção de colisão. 

Nesse comportamento apenas são considerados os objetos que estão na frente do agente e o mais próximo dele é selecionado. Como já foi apresentado, o vetor velocidade descreve a direção do personagem. É possível utilizar um vetor com uma magnitude maior e  a mesma direção do vetor velocidade com o objetivo de detectar possíveis obstáculos. Esse vetor será chamado de ahead e é similar a linha de visão do agente. Quanto maior for a magnitude desse vetor, mais cedo o agente começará a desviar dos obstáculos

Para verificar se haverá colisão, cada possível obstáculo deverá ter seu próprio collider. Uma solução possível para verificar se existe colisão entre a linha e a esfera, entretanto utilizaremos outra abordagem. Para fazer este teste de colisão iremos fazer o seguinte teste: 

Para fazer este teste basta comparar a distância entre o vetor e o centro da esfera de colisão. Se a distância for menor ou igual ao raio da esfera, então o vetor está dentro da esfera e existe uma colisão.

Para calcular direção da força necessária para o agente desviar em sua rota é necessário criar um vetor formado pelo centro da esfera e o vetor ahead.

Após o cálculo dessa direção é necessário  normalizar esse vetor e multiplicar por um parâmetro que indica o valor máximo da força sendo aplicada.

Path Follow ( Seguir um caminho determinado )

Esse comportamento permite que um personagem seja conduzido ao longo de um determinado caminho, como um corredor ou túnel. Veja que esse comportamento é diferente de um caminho rígido como o trilho de um trem. O objetivo final deste comportamento é conduzir os personagem em um movimento similar ao de pessoas andando por um corredor: os caminhos individuais se mantêm próximos e comumente paralelos a linha central do corredor.

A implementação apresentada por Craig Reynolds utiliza uma “espinha” e um raio. A espinha é representada por uma spline ou um polígono e, então, um círculo de raio especificado é conduzido pela espinha determinado assim o caminho. O objetivo do Path Follow é mover um personagem dentro deste caminho especificado pelo raio e pela espinha. Se uma personagem está fora da rota, ele deverá primeiro se aproximar para depois seguir o caminho especificado.

Para calcular a condução necessária para o path follow é feita uma predição baseada na velocidade para determinar a posição futura do personagem da mesma forma que é feita a predição do comportamento Obstacle Avoidance. A posição prevista é então projetada no ponto mais próximo da espinha do caminho. Se a distância entre o ponto projetado for menor que o raio do caminho, então o personagem está seguirá a rota corretamente sem problemas. Portanto, não é necessário fazer nenhuma correção e é retornado um valor nulo ou ainda zero. Caso contrário , o personagem irá fugir da rota ou está muito longe do caminho. Para evitar esse caso, o agente é conduzido de volta para o caminho desejado utilizando o comportamento seek para o ponto mais próximo na espinha da posição futura.

Flow Field Following ( Seguir o Fluxo)

O comportamento flow field following provê uma ferramenta útil para o direcionamento de personagens baseando-se na posição do mesmo em um ambiente.  No comportamento flow field following os personagens são conduzidos para alinhar o movimento com a tangente local do fluxo. O fluxo determina o mapeamento de uma posição no espaço para um vetor.  Esse comportamento é bastante útil em alguns times já que permite que o movimento seja especificado sem que seja feito o uso de programação sendo possível que um level designer crie o mapa de fluxo.

A implementação é bastante simples: calcula-se a posição futura do personagem no fluxo. A direção do fluxo é a velocidade desejada (F) e a direção (S) é simplesmente a diferença entre a velocidade atual (V) e a velocidade desejada.

Unaligned Collision Avoidance (Evitar Colisões Desalinhadas)

O comportamento unaligned collision avoidance busca manter os agentes que estão andando de forma arbitrária colidam. Por exemplo, considere  que você está andando na Rua das Flores, para evitar que  você esbarre com outras pessoas é necessário prever e alterar sua velocidade e sua direção. Se a multidão estiver alinhada é possível utilizar uma estratégia mais simples chamada separação.

Um agente que implementa este comportamento considera a velocidade de todos os outros agentes para determinar quando os dois agentes irão fazer o “contato mais próximo”. Uma colisão em potencial existe se o contato mais próximo está no futuro e se a distância entre os personagens entre o contato mais próximo é suficientemente pequena, dessa forma a mais próxima dentre essas potenciais colisões, se existir uma, é determinada. O personagem então é conduzido para evitar o local da colisão prevista, sendo conduzido lateralmente para evitar essa potencial. Esse agente também deverá acelerar ou desacelerar para chegar antes ou depois no local da colisão prevista.

Separation (Separação) x Cohesion (Coesão) x Alignment (Alinhamento)

Os comportamentos de separação, coesão e alinhamento são referentes como os agentes reagem a presença de outros agentes em sua vizinhança local. Observe que agentes fora dessa vizinhança são completamente ignorados. A vizinhança de um agente é definida pela distância e o ângulo que forma o campo de visão.

A separação é o comportamento de condução que permite ao personagem manter uma certa distância entre os outros agentes nessa vizinhança. Esse comportamento previne que os agentes aglomerem-se demais. Para calcular a separação, primeiro determina-se quem são os agentes presentes nessa vizinhança, existem duas formas dessa busca ser feita. A primeira forma busca fazer uma procura exaustiva entre todos os agentes simulados no mundo, a segunda forma faz um particionamento espacial. Em seguida, para cada um dos agentes encontrado nesta busca é  somada uma força inversamente proporcional a distância entre os dois agentes.

A coesão é um comportamento de condução que permite ao agente a habilidade formar um grupo coeso com outros agentes próximos. A coesão pode ser feito através calculando-se o “centro de gravidade” dos personagens próximos e aplicando uma força proporcional. Para calcular esse “centro de gravidade” é feita uma média da posição entre os personagens da vizinhança.

Alinhamento é o comportamento de condução que permite a habilidade dos agentes ficarem alinhados na mesma direção e/ou velocidade. O alinhamento pode ser computado localizando-se todos os personagens em uma vizinhança local, em seguida calcula-se a velocidade média (ou ainda o vetor forward) desses personagens. Essa média é a velocidade desejada, e assim, o vetor condução é a diferença entre essa média e a velocidade atual.

Flocking

Em 1986 Craig Reynolds desenvolveu um modelo para coordenação de movimento de animais como rebanhos, cardumes ou ainda revoada de pássaros. Para ele, cada um agente presente nessa simulação de bando é chamado por ele de boid. A implementação desse comportamento é a combinação dos comportamentos de separação, coesão e alinhamento. Em aplicações simples, como jogos indies, é suficiente simplesmente somar os três comportamentos para formar o comportamento de flocking. Para obter resultados diferentes é possível normalizar os três vetores de condução gerados por cada um dos comportamentos e então multiplicá-los por três pesos antes de somá-los.

https://www.youtube.com/watch?v=oXXepdoLqas  https://www.youtube.com/watch?v=jCVwdeAobYc https://www.youtube.com/watch?v=Mo_1rAaj7FE https://www.youtube.com/watch?v=Mo_1rAaj7FE

Leader Following (Seguir o Líder)

O comportamento de Leader Following permite que um ou mais personagens sigam um agente designado como líder. Os seguidores querem ficar próximos ao líder e fora do caminho do mesmo e caso existam mais de um seguidor eles também desejam não se esbarrar entre si.

A implementação desse comportamento é baseada no comportamento arrival (chegada - aula anterior) em que o agente deseja parar em um determinado ponto. O ponto de chegada é um ponto logo atrás do líder. Se o seguidor se encontra numa região retangular em frente ao líder, o mesmo irá ser conduzido lateralmente para sair do caminho do líder antes de começar a utilizar novamente o comportamento arrival.

Combinando Comportamentos

Os comportamentos de condução descritos são muito úteis como componentes para construção de comportamentos mais complexos. Com o objetivo de criar comportamentos mais parecidos com seres vivos é possível selecionar um comportamento ou ainda combinar esses comportamentos entre si. Observe que somente em casos muito específicos é comum a utilização de apenas um único comportamento de condução.

Existem duas formas de combinar comportamentos. A primeira forma é a utilização de máquinas de estado. Por exemplo, considere um monstro que está andando aleatoriamente por um mapa, quando esse inimigo vê o jogador, o inimigo começa a perseguir esse jogador. 

Outra forma é utilizar uma adição desses comportamentos. Considere um cervo passeando por um floresta, o mesmo deverá fugir de lobos e ainda desviar das árvores. Este cervo não pode ignorar a presença das árvores ou ainda deixar de fugir dos lobos, se não ele se torna uma presa fácil. A maneira mais fácil de adicionar esses comportamentos é através de uma soma ponderada dos comportamentos de condução utilizados. Normalmente essa solução funciona bem, entretanto, em alguns casos é possível que um comportamento cancele o outro e outro fator é o custo computacional que não é o mais eficiente possível.

O custo computacional pode ser reduzido significativamente se ao invés de computar os componentes de condução em cada um dos passos de simulação e, então, fazer a média das forças utilizadas, é possível  utilizar apenas um comportamento de condução por frame. Outra abordagem possível é utilizar um sistema de prioridade. Por exemplo, o controlador verifica se o obstacle avoidance retorna algum valor não nulo, caso contrário utiliza um segundo comportamento de condução.

。・:*:・゚★,。・:*:・゚☆ 。・:*:・゚★,。・:*:・゚☆ 。・:*:

Contact Info:Contact Info:

E-mail: pamabeltrani@gmail.com

Discord: pamnawi