Loading [MathJax]/jax/output/HTML-CSS/jax.js

Cursos / Jogos Digitais / Inteligência Artificial para Jogos / Aula

arrow_back Aula 02 - Comportamentos de navegação

2.2 Comportamento Arrival (chegada)

Como dito anteriormente, o comportamento Arrival é bem similar ao Seek. A diferença é que ele deve reduzir a velocidade ao se aproximar do destino. Bom, “se aproximar” é algo vago para o computador. É necessário especificar a que distância ele deve começar a frear. Para isso, defina um novo atributo público na classe, chamado de arrivalDistance, que representará a distância do NPC para o destino na qual ele começará a “pisar no freio”.

Pisar no freio na matemática vetorial é aplicar uma força contrária à velocidade atual, porém de menor intensidade, pois você não quer que pareça que o jogador bateu numa “parede invisível”. Ele precisa ir parando aos poucos.

Quanto de força, então, deve-se aplicar? Se você aplicar um valor fixo a cada atualização, o NPC pode parar antes do destino… ou até depois de ter passado do destino.

Uma forma de resolver esse problema é aplicar menos força em direção ao destino à medida que o NPC se aproxima dele. Nesse caso, você pode usar uma função de atenuação da velocidade desejada em relação à distância, de tal forma que quando a distância chegar a zero a velocidade deve ser também zero (o que significa que o jogador estará parado). Ou seja, quanto mais o jogador se aproxima do destino, mais sua velocidade vai se aproximando de zero.

Há várias maneiras de implementar uma função de atenuação, porém a mais simples, e por isso, a mais usada, é através de uma interpolação linear. Uma regra de três simples entre a distância e a velocidade de início do freio e a distância e a velocidade atual do jogador pode resolver o caso, como ilustra a Figura 12.

Figura 12 - Freio implementado através de uma Interpolação linear
Freio implementado através de uma Interpolação linear

Pela regra de três, o freio é apenas uma questão de multiplicar o vetor de velocidade desejada pela fração das distâncias, especificada abaixo.

fraçãodedistãncia=distânciaatualdistânciadoiníciodofreio

A implementação da ideia descrita encontra-se no Código 03. Nele, introduz-se o método SetMagnitude(), uma vez que os vetores estão sempre sendo reajustados com um determinado tamanho. Crie, então, um método para simplificar o código.

Veja que o método Arrival() possui três casos. O primeiro é quando o NPC já se encontra muito próximo do alvo (distância menor que a constante stopVal). Nesse caso, esqueça as forças de navegação e retorne simplesmente uma força contrária a atual velocidade do NPC. Assim, ao somar essa força com a sua velocidade, ela será zerada, fazendo-o parar. O segundo caso é quando o NPC se encontra na “área de freio” (distância menor do que arrivalDistance). Nesse caso, aplique os cálculos descritos anteriormente. Por fim, se nenhum desses casos ocorrer, é porque o NPC precisa manter o comportamento Seek.

x
1
            Vector2 SetMagnitude(Vector2 v, float max) {
2
                return v.normalized * max;
3
            }
4
5
            Vector2 Seek() {
6
                Vector2 velocity = SetMagnitude(goal - body.position, speed);
7
                Vector2 steering = velocity - body.velocity;
8
                return Vector2.ClampMagnitude(steering, maxSteeringForce);
9
            }
10
11
            Vector2 Arrival() {
12
                float distance = Vector2.Distance(body.position, goal);
13
                if (distance < stopVal)
14
                    return -body.velocity;
15
                else if (distance < arrivalDistance) {
16
                    Vector2 velocity = SetMagnitude(goal - body.position, speed);
17
                    velocity *= distance / arrivalDistance;
18
                    Vector2 steering = velocity - body.velocity;
19
                    return Vector2.ClampMagnitude(steering, maxSteeringForce);
20
                }
21
                else {
22
                    return Seek();
23
                }
24
            }
25
                
26
            void FixedUpdate () {
27
                Vector2 steering = Arrival();
28
                Vector2 newVelocity = body.velocity + steering;
29
                body.velocity = Vector2.ClampMagnitude(newVelocity, speed);
30
31
                if (body.velocity.magnitude > minDist)
32
                    AdjustSpriteRotation();
33
            }
34
        

Parabéns!Você conseguiu ensinar dois comportamentos para os jogadores: ir em direção a um alvo e diminuir a velocidade quando ele estiver chegando nele. A partir desses comportamentos, você irá instruir os craques da bola que você criar a realizar manobras mais radicais na próxima aula! Até lá!

Versão 5.3 - Todos os Direitos reservados