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.

Usaremos KinematicBody2D para esses exemplos, mas os princípios também serão aplicados a outros tipos de nó (Area2D, RigidBody2D).

Configurar

Cada exemplo abaixo usa a mesma configuração de cena. Comece com um KinematicBody2D com dois filhos: Sprite e CollisionShape2D. Você pode usar o ícone do Godot ("icon.png") para a textura do Sprite ou usar qualquer imagem 2D que você tiver.

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.png

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.

../../_images/movement_8way.gif

Adicione um script ao corpo cinemático e adicione o seguinte código:

extends KinematicBody2D

export (int) var speed = 200

var velocity = Vector2()

func get_input():
    velocity = Vector2()
    if Input.is_action_pressed("right"):
        velocity.x += 1
    if Input.is_action_pressed("left"):
        velocity.x -= 1
    if Input.is_action_pressed("down"):
        velocity.y += 1
    if Input.is_action_pressed("up"):
        velocity.y -= 1
    velocity = velocity.normalized() * speed

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

Na função get_input(), verificamos os quatro eventos principais e os somamos para obter o vetor de velocidade. Isso tem a vantagem de fazer com que duas chaves opostas se anulem, mas também resultará em um movimento diagonal mais rápido devido à soma das duas direções.

Podemos evitar isso se normalizarmos a velocidade, o que significa que definimos seu comprimento como 1, e multiplicamos 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.

../../_images/movement_rotate1.gif
extends KinematicBody2D

export (int) var speed = 200
export (float) var rotation_speed = 1.5

var velocity = Vector2()
var rotation_dir = 0

func get_input():
    rotation_dir = 0
    velocity = Vector2()
    if Input.is_action_pressed("right"):
        rotation_dir += 1
    if Input.is_action_pressed("left"):
        rotation_dir -= 1
    if Input.is_action_pressed("down"):
        velocity = Vector2(-speed, 0).rotated(rotation)
    if Input.is_action_pressed("up"):
        velocity = Vector2(speed, 0).rotated(rotation)

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

Aqui adicionamos duas novas variáveis para rastrear nossa direção e velocidade de rotação. Novamente, pressionar ambas as teclas ao mesmo tempo cancelará e resultará em nenhuma rotação. A rotação é aplicada diretamente na propriedade rotation do corpo.

Para definir a velocidade, usamos o método Vector2.rotated(), de forma que ela aponte na mesma direção do corpo. rotated() é uma função vetorial útil que você pode usar em muitas circunstâncias onde você precisaria aplicar funções trigonométricas.

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.

../../_images/movement_rotate2.gif
extends KinematicBody2D

export (int) var speed = 200

var velocity = Vector2()

func get_input():
    look_at(get_global_mouse_position())
    velocity = Vector2()
    if Input.is_action_pressed("down"):
        velocity = Vector2(-speed, 0).rotated(rotation)
    if Input.is_action_pressed("up"):
        velocity = Vector2(speed, 0).rotated(rotation)

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

Aqui estamos usando o método Node2D look_at() para apontar o jogador para uma determinada posição. Sem esta função, você poderia obter o mesmo efeito definindo o ângulo assim:

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.

../../_images/movement_click.gif
extends KinematicBody2D

export (int) var speed = 200

onready var target = position
var velocity = Vector2()

func _input(event):
    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) > 5:
        velocity = move_and_slide(velocity)

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 amostra aqui: 2D_movement_demo.zip