Visão geral de movimento 2D

Introdução

Todo iniciante está lá: "Como faço para mover meu personagem?" Dependendo do estilo de jogo que você está fazendo, você pode ter requisitos especiais, mas em geral o movimento na maioria dos jogos 2D é baseado em um pequeno número de designs.

We'll use CharacterBody2D for these examples, but the principles will apply to other node types (Area2D, RigidBody2D) as well.

Configurar

Each example below uses the same scene setup. Start with a CharacterBody2D with two children: Sprite2D and CollisionShape2D. You can use the Godot icon ("icon.png") for the Sprite2D's texture or use any other 2D image you have.

Abra Projeto -> Configurações do Projeto e selecione a guia "Mapa de Entrada". Adicione as seguintes ações de entrada (consulte InputEvent para obter detalhes):

../../_images/movement_inputs.webp

Movimento em 8 direções

Neste cenário, você quer que o usuário pressione as quatro teclas direcionais (para cima/esquerda/baixo/direita ou W/A/S/D) e se mova na direção selecionada. O nome "movimento em 8 direções" vem do fato de que o jogador pode se mover diagonalmente pressionando duas teclas ao mesmo tempo.

Add a script to the character body and add the following code:

extends CharacterBody2D

@export var speed = 400

func get_input():
    var input_direction = Input.get_vector("left", "right", "up", "down")
    velocity = input_direction * speed

func _physics_process(delta):
    get_input()
    move_and_slide()

Na função get_input(), usamos Input get_vector() para verificar os quatro eventos de tecla e retornar um vetor de direção somando os resultados.

Podemos então definir nossa velocidade multiplicando esse vetor de direção, que tem comprimento 1, pela velocidade desejada.

Dica

Se você nunca usou matemática vetorial antes, ou precisa de uma atualização, você pode ver uma explicação sobre o uso de vetores no Godot em Matemática vetorial.

Nota

Se o código acima não faz nada quando você pressiona as teclas, verifique se você configurou as ações de entrada corretamente conforme descrito na parte Configurar deste tutorial.

Rotação + movimento

Esse tipo de movimento às vezes é chamado de "estilo Asteroids" porque se assemelha a como o clássico jogo de arcade que funcionava assim. Pressionar a esquerda/direita gira o caractere, enquanto para cima/para baixo o move para frente ou para trás em qualquer direção que esteja voltado.

extends CharacterBody2D

@export var speed = 400
@export var rotation_speed = 1.5

var rotation_direction = 0

func get_input():
    rotation_direction = Input.get_axis("left", "right")
    velocity = transform.x * Input.get_axis("down", "up") * speed

func _physics_process(delta):
    get_input()
    rotation += rotation_direction * rotation_speed * delta
    move_and_slide()

Here we've added two variables to track our rotation direction and speed. The rotation is applied directly to the body's rotation property.

Para definir a velocidade, usamos o transform.x do corpo, que é um vetor apontando na direção "frontal" do corpo, e multiplicamos isso pela velocidade.

Rotação + movimento (mouse)

Este estilo de movimento é uma variação do anterior. Desta vez, a direção é definida pela posição do mouse em vez do teclado. O personagem sempre "olhará" para o ponteiro do mouse. No entanto, as entradas para a frente/para trás permanecem as mesmas.

extends CharacterBody2D

@export var speed = 400

func get_input():
    look_at(get_global_mouse_position())
    velocity = transform.x * Input.get_axis("down", "up") * speed

func _physics_process(delta):
    get_input()
    move_and_slide()

Here we're using the Node2D look_at() method to point the player towards the mouse's position. Without this function, you could get the same effect by setting the angle like this:

rotation = get_global_mouse_position().angle_to_point(position)

Clique e mova

Este último exemplo usa apenas o mouse para controlar o personagem. Clicar na tela fará com que o jogador se mova para o local de destino.

extends CharacterBody2D

@export var speed = 400

var target = position

func _input(event):
    # Use is_action_pressed to only accept single taps as input instead of mouse drags.
    if event.is_action_pressed(&"click"):
        target = get_global_mouse_position()

func _physics_process(delta):
    velocity = position.direction_to(target) * speed
    # look_at(target)
    if position.distance_to(target) > 10:
        move_and_slide()

Observe a verificação distance_to() que fazemos antes do movimento. Sem esse teste, o corpo "tremeria" ao atingir a posição-alvo, pois se moveria um pouco além da posição e tentaria voltar, apenas para se afastar demais e repetir.

Descomentar a linha look_at() também irá virar o corpo para apontar em sua direção de movimento, se você preferir.

Dica

Essa técnica também pode ser usada como base para um personagem "seguidor". A posição target pode ser a de qualquer objeto para o qual você deseja mover.

Resumo

Você pode achar esses exemplos de código úteis como pontos de partida para seus próprios projetos. Sinta-se livre para usá-los e experimentá-los para ver o que você pode fazer.

Você pode baixar este projeto de exemplo aqui: 2d_movement_starter.zip