Matemática para jogos – Como Utilizar Vetores

(Last Updated On: 13 de agosto de 2018)

No nosso jogo, desenvolvido na engine Unity, o Zumbi precisa perseguir a heroína, como fazer isso?

Como podemos observar na imagem abaixo, a heroína está na posição x = 100, y = 30 e o zumbi, na posição x = 200, y = 120.

Vamos escrever um código que faça com que o zumbi se desloque até a posição da heroína.

Uma boa prática na hora de resolver problemas é dividi-lo em partes simples e resolver cada uma antes de resolver o problema todo. Nesse caso, qual é a parte mais simples do problema?

Se precisamos sair da posição (200, 120) para a posição (100,30), precisamos alterar a posição do inimigo em dois eixos – horizontal e vertical. Vamos mover o inimigo apenas na horizontal, para depois mover ele no outro eixo.

Se eu estou na posição 200 e quero chegar na posição 100, qual a distância que eu preciso andar?

Na imagem temos d representando a distância que precisamos nos mover para chegar até a posição desejada. Fica fácil perceber que o zumbi precisa andar 100 unidades para chegar na posição da heroína.

Só que o computador não consegue “ver” a imagem e descobrir essa distância. Precisamos achar uma maneira dele calcular essa distância. Nesse caso, para chegarmos no número 100, precisamos subtrair a posição X do zumbi da posição X da heroína.

Depois, é só somar essa distância na posição atual do zumbi para ele se deslocar!



float distânciaX = zumbi.x - heroína.x;

zumbi.x += distânciaX ;

Abaixo, você confere como o código fica na Unity.



public class Zumbi : MonoBehaviour {

[SerializeField]

private Transform alvo;

private void Update()

{

float distanciaX = this.transform.position.x - this.alvo.position.x;

this.transform.position = new Vector3( this.transform.position.x + distanciaX , this.transform.position.y, this.transform.position.z);

}

}

O componente que guarda as informações de posição dos objetos é o Transform, por isso, declaramos uma variável “alvo” do tipo Transformque vai receber seu valor por meio do inspetor da Unity.

Apesar de estarmos trabalhando em um jogo 2D, a Unity ainda guarda as posições com 3 valores (X, Y e Z). Por isso, na hora de atribuirmos a nova posição ao zumbi, utilizamos um Vector3.


this.transform.position = new Vector3( this.transform.position.x + distanciaX, this.transform.position.y, this.transform.position.z);

O que acontece agora se testarmos nosso código?

 

Reparem que o zumbi foi para o lado errado, se afastando da heroína.

Acontece que o sentido do deslocamento importa e, quem define o sentido que estamos andando é o sinal de positivo(+) ou negativo(-).

Quando desenhamos o eixo horizontal, utilizamos uma seta (preta) para representá-lo. Ao mesmo tempo que usamos outra seta (laranja) para representar a distância que devemos andar.

A seta que representa o eixo X aponta na direção em que esse eixo cresce, ou seja se andarmos naquela direção vamos aumentar o valor da nossa posição em X. Nesse caso, estamos indo no sentido positivo (+) do eixo.

A seta que representa o caminho a percorrer aponta no sentido contrário do eixo, isso indica que queremos andar no sentido negativo (-) desse eixo. Como podemos mudar a conta que estamos fazendo para refletir isso?

A conta atual é:



float distânciaX = zumbi.x - heroína.x;

colocando os valores ficaria:



float distânciaX = 200 - 100;

O valor numérico dessa conta está correto, mas queremos o sinal contrário. Como a ordem dos valores de uma subtração importa, podemos inverter os valores da nossa conta para termos o resultado desejado.



float distânciaX = heroína.x - zumbi.x;

distancaX = 100 - 200;

distanciaX = -100;

Se voltarmos no nosso código, precisamos trocar somente a linha onde fazemos essa subtração.



private void Update()

{

**float distanciaX = this.alvo.position.x - this.transform.position.x;**

this.transform.position = new Vector3( this.transform.position.x + distanciaX , this.transform.position.y, this.transform.position.z);

}

Será que essa abordagem funciona também para o eixo vertical?

Vamos testar. No caso do eixo Y, a heroína está na posição 120 e o zumbi na posição 30.

Colocando esses valores na conta:



float distânciaY = heroína.y - zumbi.y;

float distânciaY = 30 - 120;

float distânciaY = - 90;

Chegamos ao número -90 e ele faz sentido, pois o zumbi tem que andar 90 unidades na direção oposta a direção de crescimento do próprio eixo Y.

Podemos então generalizar, ou seja, sempre que precisamos calcular o sentido e a distância entre dois pontos, precisamos subtrair a posição X e Y do nosso destino pelo X e Y da nossa origem.

Voltando ao nosso código da classe zumbi, adicionamos o cálculo da *distânciaY *para que o zumbi vá atrás da heroína.



private void Update()

{

float distanciaX = this.alvo.position.x - this.transform.position.x;

float distanciaY = this.alvo.position.y - this.transform.position.y;

this.transform.position = new Vector3( this.transform.position.x + distanciaX, this.transform.position.y + distanciaY, this.transform.position.z);

}

Será que agora chegamos no comportamento desejado?

Parece que não, agora o zumbi está se teleportando para a posição da heroína.

Resumindo: sempre que temos um comportamento de perseguição precisamos subtrair a posição do destino da posição da origem para achar a direção que temos que seguir e a distância que estamos do alvo.

Ao somar o resultado da subtração na posição do inimigo ele se moverá instantâneamente para o destino.

Como esse texto está ficando longo, resolver apenas esse problemas do perseguidor teleportar para a posição de destino em um outro post.Você conhece alguma outra situação onde podemos usar essa mesma lógica? Qual outro problema relacionado a jogos você gostaria de ver explicado aqui no blog? Deixa nos comentários!

Aproveita e olha lá no site da alura os cursos que temos sobre jogos, tenho certeza que você vai encontrar algo interessante para aprender.

Próximo ArtigoPincelando um protótipo no Adobe XD