Módulo 8 · Aula 8.3 · Mapa de Entrada e movimento
| Carga horária | Dificuldade | Ferramenta | Competências |
|---|---|---|---|
| 10 h/a | ⭐⭐⭐ | Godot 4.7 | C2 |
Objetivos de aprendizagem
- Mover um desenho com as setas usando
delta(velocidade igual em qualquer computador). - Criar ações no Mapa de Entrada (
esquerda,direita,cima,baixo) com mais de uma tecla cada. - Mover um
CharacterBody2Dcomvelocity,move_and_slide()eInput.get_vector. - Trocar a animação e virar o desenho conforme a direção.
- Seguir o mouse ou o dedo enquanto ele está apertado.
Pré-requisitos
Aula 8.2.
Materiais
Godot 4.7; laboratório (cenas/anda_com_setas.tscn); Sementes em Godot (cenas/jogador.tscn).
Conceitos
Velocidade × delta. position.x += 200 * delta anda 200 pixels por segundo. Sem delta, andaria 200 pixels por quadro: num computador de 60 quadros por segundo, voaria a 12.000 pixels por segundo.
Ação em vez de tecla. No código não se escreve "seta para a direita": escreve-se a ação "direita". No Mapa de Entrada cada ação recebe uma ou mais teclas (seta e letra D, por exemplo). Para trocar as teclas, não se mexe no código. É a mesma ideia da tecla trocável da Feira do Troco (Aula 7.6).
Ações prontas. O Godot já vem com ações ui_left, ui_right, ui_up, ui_down e ui_accept (aparecem ao ligar Mostrar Ações Integradas). O primeiro exemplo usa essas; o jogo usa as ações próprias, com nome em português.
Input.get_vector. Junta as quatro ações numa direção só, de tamanho no máximo 1. Assim, andar na diagonal não fica mais rápido do que andar reto. O teste do Sementes confere isso: reto ou na diagonal, uns 100 pixels em meio segundo.
CharacterBody2D. Corpo que o jogador controla. Põe-se a velocidade em velocity e chama-se move_and_slide(): ele anda e desliza nas paredes. Para jogo visto de cima, a propriedade Motion Mode fica em Floating (no Sementes já está).
_physics_process. Movimento com colisão vai aqui, e não no _process, porque a física roda sempre no mesmo ritmo.
Exemplos
| GDevelop (Módulo 3) | Godot |
|---|---|
| comportamento Movimento em TopDown, velocidade 200 | velocity = direcao * 200 + move_and_slide() |
| teclas do comportamento | ações do Mapa de Entrada |
| inverter o objeto horizontalmente | desenho.flip_h = true |
| animação por nome | desenho.play("andando") |
Tutorial passo a passo
Parte A. Primeiro movimento (90 min)
- Abra
anda_com_setas.tscnno laboratório e execute a cena. Ande com as setas. - Leia
anda_com_setas.gd. Tire o* deltade uma linha e execute: o que aconteceu? Volte como estava.
Parte B. Mapa de Entrada (90 min)
- Menu Projeto → Configurações do Projeto..., aba Mapa de Entrada.
- Em Adicionar Nova Ação, escreva
direitae clique em Adicionar. Faça o mesmo paraesquerda,cimaebaixo. - No
+de cada ação, aperte a tecla (seta) e confirme. Adicione também W, A, S, D. - Compare com a captura do Sementes. As teclas aparecem como
Right (Físico): "físico" quer dizer a posição da tecla no teclado, e assim funciona em teclados de outros idiomas.
Parte C. Corpo que anda (180 min)
- Cena nova com raiz
CharacterBody2DchamadaJogador. Filhos:AnimatedSprite2DchamadoDesenhoeCollisionShape2DchamadoColisao. - No
Desenho, emSprite Frames, crie um SpriteFrames com as animaçõesparado(1 quadro) eandando(2 quadros), usando os desenhos do sertanejo. - No
Colisao, emShape, escolha um retângulo do tamanho do corpo. - No
Jogador,Motion Mode=Floating. Anexe um script e escreva o código abaixo (sem a parte do toque, por enquanto). - Coloque a cena do jogador dentro de uma cena de teste (arrastando o
.tscnpara a área 2D) e execute.
Parte D. Mouse e dedo (90 min)
- Acrescente
alvo_toquee a função_unhandled_inputdo código completo. Segure o mouse num ponto: o sertanejo vai até lá. - Teste: o que acontece quando o sertanejo chega no ponto? Por que existe o
> 8?
Imagens
../../../recursos/imagens/godot/captura-godot-mapa-de-entrada.png
: Mapa de Entrada com as ações do Sementes.../../../recursos/imagens/godot/captura-godot-script-jogador.png
: o script do jogador no editor.../../../recursos/imagens/godot/captura-godot-cena-jogador-inspetor.png
: a cena do jogador.
Indicação da interface
| Item | Nome na tela |
|---|---|
| ações e teclas | Configurações do Projeto... → aba Mapa de Entrada: Adicionar Nova Ação, Adicionar, Mostrar Ações Integradas, coluna Zona Morta |
| janela de escolher a tecla | Configuração de Evento (opções "Keycode Físico (Posição no teclado QWERTY dos EUA)" e "Keycode (Equivalente Latino)") |
| quadros da animação | propriedade Sprite Frames do AnimatedSprite2D; o painel de quadros abre embaixo |
| forma de colisão | propriedade Shape do CollisionShape2D |
O passo a passo do painel de quadros (botões para adicionar quadros de arquivo) não foi fotografado nesta versão; o professor deve fazer uma vez antes da aula.
O código completo
projetos/sementes-godot/scripts/jogador.gd:
extends CharacterBody2D
const VELOCIDADE := 200.0
## Ponto que o jogador está apertando com o mouse ou o dedo. null quando ninguém aperta.
var alvo_toque = null
@onready var desenho: AnimatedSprite2D = $Desenho
func _unhandled_input(event: InputEvent) -> void:
# O toque na tela chega como clique de mouse (opção padrão do Godot).
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
alvo_toque = event.position if event.pressed else null
elif event is InputEventMouseMotion and alvo_toque != null:
alvo_toque = event.position
func _physics_process(_delta: float) -> void:
var direcao := Input.get_vector("esquerda", "direita", "cima", "baixo")
if direcao == Vector2.ZERO and alvo_toque != null and position.distance_to(alvo_toque) > 8:
direcao = position.direction_to(alvo_toque)
velocity = direcao * VELOCIDADE
move_and_slide()
# Não deixa o sertanejo sair da tela de 800 x 600.
position = position.clamp(Vector2(16, 24), Vector2(784, 576))
if direcao.x != 0:
desenho.flip_h = direcao.x < 0
if direcao == Vector2.ZERO:
desenho.play("parado")
else:
desenho.play("andando")Explicação do código
@onready var desenho = $Desenho:$Desenhoé o nó filho chamadoDesenho.@onreadyespera a cena ficar pronta para buscar.move_and_slide()já usa odeltapor dentro; por isso a função recebe_delta(o traço diz "não uso").Vector2é um par (x, y).clampprende a posição dentro de um retângulo.- O toque: segurando,
alvo_toqueguarda o ponto; soltando, viranulle o sertanejo para. As setas têm prioridade. - Só vira o desenho quando há movimento para o lado; parado, fica virado para onde estava.
Resultado esperado
Personagem com ações próprias, velocidade igual na diagonal, animação e virada certas, preso na tela, seguindo o mouse ou o dedo.
Problemas comuns
| Sintoma | Causa | Solução |
|---|---|---|
| o personagem não anda | nome da ação no código diferente do Mapa de Entrada | conferir letra por letra ("direita") |
| anda devagar demais ou rápido demais | velocidade sem delta (com position +=) | multiplicar por delta, ou usar velocity + move_and_slide() |
| erro "Node not found: Desenho" | o filho tem outro nome | renomear o nó ou mudar o $ |
| o desenho não muda | animação com nome diferente | "andando" e "parado" iguais no SpriteFrames e no código |
| na diagonal fica mais rápido | somou as direções à mão | Input.get_vector |
Exercício guiado
Com velocidade 200 e get_vector, quanto o jogador anda em 0,5 s para a direita? E na diagonal? (Resposta: uns 100 pixels nos dois casos. O teste mediu 103,3 nos dois, por causa do arredondamento dos quadros.)
Desafio individual
Acrescente uma ação correr (tecla Shift) que dobra a velocidade enquanto está apertada.
Desafio avançado (opcional)
Faça o personagem acelerar aos poucos até a velocidade máxima, usando velocity = velocity.move_toward(direcao * VELOCIDADE, 800 * delta).
Critérios de avaliação
- Ações próprias no Mapa de Entrada, com duas teclas cada.
- Movimento com
get_vectoremove_and_slide. - Animação e virada coerentes.
Checklist de conclusão
Extensão
Física: velocidade é distância dividida por tempo. Cronometre o personagem atravessando a tela de 800 pixels. Bate com 200 pixels por segundo?