Compendium - Movimento em Primeira Pessoa

Nesse pequeno tutorial você vai aprender a como criar um personagem que se move com as teclas WASD e também como controlar a câmera com o mouse.

Configurando as teclas de controle

Devemos criar as teclas de controle dentro do Godot. Para isso acessamos a opção Project > Project Settings:

Depois disso vá até a aba Input Map e lá crie um novo comando inserindo o nome da action. Depois basta escolher a tecla indo no + e pressionando a tecla desejada. Adicione as 4 teclas de comando que precisamos:

Adicionando a cena do Player ao projeto

Depois de criar as actions de comando, vamos construir o personagem. A estrutura de nodes que precisamos montar é:

- Kinematic body (Renomeie para PlayerFPS)

        - Collision Shape (Insira um capsule shape)

        - Spatial (Renomeie para Head)

                - Camera

O “Head” será a cabeça do personagem, onde dentro dele existirá uma câmera. A cabeça vai rotacionar utilizando um eixo e a câmera em outro,sendo que o corpo apenas se move na direção desejada e não rotaciona.

Salve sua cena dentro do seu projeto com uma pasta somente para ela. Depois crie um script no node raiz para continuar.

Programando a rotação da câmera

Dentro do script vamos montar primeiro a movimentação da câmera. Antes você deve entender que o mouse possui 2 eixos de movimento na tela: X e Y. O eixo X controla a rotação em Y da cabeça do objeto (Head), e o eixo Y controla a rotação em X da câmera (filho do Head).

Crie uma variável para controlarmos a sensibilidade do mouse. Agora precisamos de uma função que já é própria do Godot chamada _input(event):

Dentro da função precisamos agora identificar qual evento de input será utilizado. Como será o movimento do mouse, basta identificar com o inputEventMouseMotion:

Agora precisamos fazer com que a cabeça gire primeiro. Como dito anteriormente, a “Head” rotacionará no eixo Y. Para isso precisamos então utilizar o eixo X do mouse dentro da função rotate_x(). Dentro dela precisamos converter de grau para radiano o valor com deg2rad; após isso precisamos pegar a posição do mouse na tela com o relative e multiplicar com a variável que controla a sensibilidade.

Teste o projeto e perceba que a camera já gira, mas o mouse não fica preso a tela. Vamos consertar isso utilizando a função _ready(). Assim que o jogo iniciar, vamos capturar o cursor dentro da janela:

Agora temos apenas um problema: o mouse ficará sempre no meio da tela e não teremos como fechar a aplicação. Então vamos criar um simples evento na função _physics_process(delta) que checa quando pressionarmos a tecla ESC, o game fecha automaticamente:

Agora que fizemos isso precisamos apenas fazer com que a câmera rotacione no eixo X. Se formos seguir a lógica que fizemos antes o código deve ficar assim:

Se você testar o projeto, você vai perceber que a câmera rotaciona para cima sem limite algum. Isso é um grande problema, mas existe uma solução. Antes devemos criar uma variável que armazena o ângulo de rotação do objeto:

Agora na função _input(event) vamos criar mais uma variável. Ela vai servir para armazenar a posição do mouse no eixo Y com a sensibilidade:

A variável change vai alterar seu valor conforme o mouse se move, e a variável camAngle vai receber esse valor ao mesmo tempo. Agora devemos apenas comparar se o valor somado das duas variáveis são menores que 90 e ao mesmo tempo maiores que -90, ou seja, se o valor do mouse não alcançou o limite tanto olhando para cima quanto para baixo, a câmera rotaciona normalmente.

Movimentando o Player

O que falta agora é movermos o Player na direção em que ele olha. Antes devemos saber que para o personagem andar ele deve possuir um vetor de direção (para onde ele anda) ,um de movimento (indicando para onde ele deve ir) além de velocidade e também da gravidade. Vamos antes criar essas variáveis no script para armazenarmos os cada valor separadamente:

Continuando, precisamos agora criar uma função separada apenas para guardar os códigos de movimento do personagem. Isso auxilia e muito na hora de organizar seu script, pois se nós formos programar em apenas um só local do código, tudo pode virar uma bagunça futuramente dependendo do tamanho do seu projeto. Então vamos criar a função run com um parâmetro:

Agora vamos identificar a direção para onde a cabeça (Head) do Player está olhando, pois é nessa direção que ele deve andar. Na função que criamos vamos identificar a direção para onde ele está olhando no momento com o basis e guardar tudo isso em uma variável. Com essa função é possível identificar os vetores locais do objeto ao invés dos vetores globais.

(Os eixos azuis são os Globais,enquanto os vermelhos são os Locais)

Agora identificado a direção, precisamos mudar o seu movimento quando alguma tecla for pressionada. Para isso podemos utilizar o vetor de direção dir modificando seu valor conforme os eixos de direções locais da cabeça identificados na variável aim:

Até esse ponto já temos os valores de movimento, mas o Player ainda não vai andar, pois não estamos usando esses valores até agora. Para isso, vamos utilizar a variável de movimento e aplicar o valor obtido da direção tanto no eixo x quanto no eixo z:

Tendo o movimento, podemos agora usar a função move_and_slide do godot para aplicarmos os valores dentro dela e fazer o objeto se mover:

Para que o Godot começe a executar o comando, é necessário que você chame a função. Para isso podemos agora na _physics_process(delta) chamar a função run e inserir como parâmetro o delta, que é o tempo em mílisegundos descrito anteriormente.

Se você testar o projeto vai perceber que o personagem anda sozinho pelo infinito. Devemos impedir isso fazendo com que toda hora os vetores de direção fiquem com valor zero acima do código da função. Esse valor só é modificado se alguma tecla de movimento for acionada:

Adicionando gravidade e pulo no jogo

A única coisa que falta agora é aplicar a força de gravidade no personagem. Para isso vamos fazer com que toda hora o movimento aplicado no eixo y seja incrementado utilizando o valor da gravidade multiplicado pelo parâmetro da função dt. Esse parâmetro vai receber futuramente o valor em milisegundos, fazendo com que em qualquer máquina que executar o jogo rode no mesmo tempo que outras:

A gravidade já funciona, mas podemos programar para que quando uma tecla for pressionada (o espaço por exemplo) e se o personagem estiver no chão, ele pule. Para isso basta apenas comparar qual tecla foi pressionada e utilizar a função is_on_floor() na mesma sentença, e por fim modificar o valor do eixo Y da variável de movimento:

Pronto! Até aqui seu personagem já possui os movimentos básicos e consegue andar pelo cenário. Basta instanciá-lo na cena que desejar usá-lo, desde que ela possua um static body para que ele fique firme no chão.

Fazendo o ponteiro do mouse aparecer e desaparecer

Você pode ter notado que quando o jogo se inicia, o mouse fica travado no meio da tela e não é possível mais clicar fora da janela do game. Podemos criar um sistema em que quando o jogador pressiona determinada tecla, o game faz com que o mouse apareça e desapareça. Uma forma de fazer isso é substituindo o código que fizemos para a tecla ESC anteriormente, que quando for pressionada o jogo fecha automaticamente, por outra função que faz o mouse reaparecer.

Caso queira fazer o ponteiro do mouse aparecer, basta utilizar a função Input.MOUSE_MODE_VISIBLE dentro da condição e do _physics_process(delta):

Se quiser que o mouse volte ao modo normal de jogo, basta programar outra condição e utilizar a função Input.MOUSE_MODE_CAPTURED,mas dessa vez esse código deve estar obrigatoriamente dentro da função _input(event). Podemos fazer com que quando o usuário clicar na tela novamente, o cursor desaparecer usando a função InputEventMouseButton: