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):
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()
using Godot;
public partial class Movement : CharacterBody2D
{
[Export]
public int Speed { get; set; } = 400;
public void GetInput()
{
Vector2 inputDirection = Input.GetVector("left", "right", "up", "down");
Velocity = inputDirection * Speed;
}
public override void _PhysicsProcess(double delta)
{
GetInput();
MoveAndSlide();
}
}
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()
using Godot;
public partial class Movement : CharacterBody2D
{
[Export]
public int Speed { get; set; } = 400;
[Export]
public float RotationSpeed { get; set; } = 1.5f;
private float _rotationDirection;
public void GetInput()
{
_rotationDirection = Input.GetAxis("left", "right");
Velocity = Transform.X * Input.GetAxis("down", "up") * Speed;
}
public override void _PhysicsProcess(double delta)
{
GetInput();
Rotation += _rotationDirection * RotationSpeed * (float)delta;
MoveAndSlide();
}
}
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()
using Godot;
public partial class Movement : CharacterBody2D
{
[Export]
public int Speed { get; set; } = 400;
public void GetInput()
{
LookAt(GetGlobalMousePosition());
Velocity = Transform.X * Input.GetAxis("down", "up") * Speed;
}
public override void _PhysicsProcess(double delta)
{
GetInput();
MoveAndSlide();
}
}
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)
var rotation = GetGlobalMousePosition().AngleToPoint(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()
using Godot;
public partial class Movement : CharacterBody2D
{
[Export]
public int Speed { get; set; } = 400;
private Vector2 _target;
public override void _Input(InputEvent @event)
{
// Use IsActionPressed to only accept single taps as input instead of mouse drags.
if (@event.IsActionPressed("click"))
{
_target = GetGlobalMousePosition();
}
}
public override void _PhysicsProcess(double delta)
{
Velocity = Position.DirectionTo(_target) * Speed;
// LookAt(_target);
if (Position.DistanceTo(_target) > 10)
{
MoveAndSlide();
}
}
}
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