Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Personagem cinemático (2D)

Introdução

Sim, o nome soa estranho. "Personagem cinemático". O que é aquilo? A razão para o nome é que, quando os motores de física surgiram, eles eram chamados de motores "Dinâmicos" (porque lidavam principalmente com respostas de colisão). Muitas tentativas foram feitas para criar um controlador de personagem usando os motores de dinâmica, mas não foi tão fácil quanto parecia. Godot tem uma das melhores implementações de controlador de personagem dinâmico que você pode encontrar (como pode ser visto na demo 2d/platformer), mas usá-lo requer um nível considerável de habilidade e compreensão dos motores de física (ou muita paciência com testes e erro).

Alguns motores de física, como o Havok, parecem defender os controladores de personagens dinâmicos como a melhor opção, enquanto outros (PhysX) preferem promover o cinemático.

Então, qual é a diferença?:

  • Um controlador dinâmico de personagem usa um corpo rígido com um tensor de inércia infinito. É um corpo rígido que não pode girar. Os motores de física sempre permitem que os objetos se movam e colidam, então resolvem suas colisões todas juntas. Isso torna os controladores de personagem dinâmicos capazes de interagir perfeitamente com outros objetos físicos, como visto na demonstração do jogo de plataforma. No entanto, essas interações nem sempre são previsíveis. As colisões podem levar mais de um quadro para serem resolvidas, então algumas colisões podem parecer deslocar um pouquinho. Esses problemas podem ser corrigidos, mas requerem uma certa habilidade.

  • Presume-se que um controlador de caractere cinemático comece sempre em um estado sem colisão e sempre se moverá para um estado sem colisão. Se começar em estado de colisão, tentará se libertar como fazem os corpos rígidos, mas esta é a exceção, não a regra. Isso torna seu controle e movimento muito mais previsível e fácil de programar. No entanto, como desvantagem, eles não podem interagir diretamente com outros objetos físicos, a menos que sejam feitos à mão em código.

This short tutorial focuses on the kinematic character controller. It uses the old-school way of handling collisions, which is not necessarily simpler under the hood, but well hidden and presented as an API.

Processo físico

Para gerenciar a lógica de um corpo ou personagem cinemático, é sempre aconselhável usar o processo de física, pois é chamado antes da simulação de física e sua execução está em sincronia com o servidor de física, também é chamado a mesma quantidade de vezes por segundo, sempre. Isso faz com que a física e o cálculo de movimento funcionem de maneira mais previsível do que usando o processo regular, que pode ter picos ou perder a precisão se a taxa de quadros for muito alta ou muito baixa.

extends CharacterBody2D

func _physics_process(delta):
    pass

Configuração da cena

To have something to test, here's the scene (from the tilemap tutorial): kinematic_character_2d_starter.zip. We'll be creating a new scene for the character. Use the robot sprite and create a scene like this:

../../_images/kbscene.webp

Você notará que há um ícone de aviso próximo ao nosso nó CollisionShape2D; isso porque não definimos uma forma para ele. Crie um novo CircleShape2D na propriedade de forma de CollisionShape2D. Clique em <CircleShape2D> para acessar as opções e defina o raio como 30:

../../_images/kbradius.webp

Observação: como mencionado anteriormente no tutorial de física, o engine de física não pode lidar com a escala na maioria dos tipos de formas (somente polígonos de colisão, planos e segmentos funcionam), portanto, sempre altere os parâmetros (como o raio) da forma em vez de dimensioná-la. O mesmo também é verdade para os próprios corpos cinemáticos/rígidos/estáticos, pois sua escala afeta a escala da forma.

Agora, crie um script para o personagem, o usado como exemplo acima deve servir de base.

Por fim, crie uma instância dessa cena de personagem no tilemap e torne a cena do mapa a principal, para que seja executada ao pressionar o play.

../../_images/kbinstance.webp

Movendo o personagem cinemático

Go back to the character scene, and open the script, the magic begins now! Kinematic body will do nothing by default, but it has a useful function called CharacterBody2D.move_and_collide(). This function takes a Vector2 as an argument, and tries to apply that motion to the kinematic body. If a collision happens, it stops right at the moment of the collision.

Então, vamos mover nosso sprite para baixo até atingir o chão:

extends CharacterBody2D

func _physics_process(delta):
    move_and_collide(Vector2(0, 1)) # Move down 1 pixel per physics frame

O resultado é que o personagem vai se mover, mas parar ao bater no chão. Bem legal, né?

O próximo passo será adicionar gravidade à mistura, de forma que ela se comporte um pouco mais como um personagem normal do jogo:

extends CharacterBody2D

const GRAVITY = 200.0

func _physics_process(delta):
    velocity.y += delta * GRAVITY

    var motion = velocity * delta
    move_and_collide(motion)

Agora o personagem cai sem problemas. Vamos fazê-lo andar para os lados, esquerda e direita ao tocar nas teclas direcionais. Lembre-se de que os valores usados (pelo menos para velocidade) são pixels/segundo.

This adds basic support for walking when pressing left and right:

extends CharacterBody2D

const GRAVITY = 200.0
const WALK_SPEED = 200

func _physics_process(delta):
    velocity.y += delta * GRAVITY

    if Input.is_action_pressed("ui_left"):
        velocity.x = -WALK_SPEED
    elif Input.is_action_pressed("ui_right"):
        velocity.x =  WALK_SPEED
    else:
        velocity.x = 0

    # "move_and_slide" already takes delta time into account.
    move_and_slide()

E experimente.

Este é um bom ponto de partida para um jogo de plataforma. Uma demonstração mais completa pode ser encontrada no zip de demonstração distribuído com o mecanismo ou no https://github.com/godotengine/godot-demo-projects/tree/master/2d/kinematic_character.