Exemplos de entrada¶
Introdução¶
Neste tutorial, você aprenderá como usar o sistema InputEvent do Godot para capturar a entrada do jogador. Existem muitos tipos diferentes de entrada que seu jogo pode usar - teclado, gamepad, mouse, etc. - e muitas maneiras diferentes de transformar essas entradas em ações em seu jogo. Este documento mostrará alguns dos cenários mais comuns, que você pode usar como ponto de partida para seus próprios projetos.
Nota
Para uma visão geral detalhada de como o sistema de eventos de entrada do Godot funciona, veja Usando InputEvent.
Eventos versus polling¶
Às vezes, você deseja que seu jogo responda a um determinado evento de entrada - pressionando o botão "pular", por exemplo. Para outras situações, você pode querer que algo aconteça enquanto uma tecla for pressionada, como um movimento. No primeiro caso, você pode usar a função _input()
, que será chamada sempre que ocorrer um evento de entrada. No segundo caso, Godot fornece o singleton Input, que você pode usar para consultar o estado de uma entrada.
Exemplos:
func _input(event):
if event.is_action_pressed("jump"):
jump()
func _physics_process(delta):
if Input.is_action_pressed("move_right"):
# Move as long as the key/button is pressed.
position.x += speed * delta
public override void _Input(InputEvent inputEvent)
{
if (inputEvent.IsActionPressed("jump"))
{
Jump();
}
}
public override void _PhysicsProcess(float delta)
{
if (Input.IsActionPressed("move_right"))
{
// Move as long as the key/button is pressed.
position.x += speed * delta;
}
}
Isso lhe dá a flexibilidade de misturar e combinar o tipo de processamento de entrada que você faz.
No restante deste tutorial, focaremos na captura de eventos individuais em _input()
.
Eventos de entrada¶
Eventos de entrada são objetos que herdam de InputEvent. Dependendo do tipo de evento, o objeto conterá propriedades específicas relacionadas a esse evento. Para ver como os eventos realmente se parecem, adicione um Nó e anexe o seguinte script:
extends Node
func _input(event):
print(event.as_text())
using Godot;
using System;
public class Node : Godot.Node
{
public override void _Input(InputEvent inputEvent)
{
GD.Print(inputEvent.AsText());
}
}
Ao pressionar as teclas, mover o mouse e executar outras entradas, você verá cada evento aparecer na janela de saída. Aqui está um exemplo da saída:
A
InputEventMouseMotion : button_mask=0, position=(108, 108), relative=(26, 1), speed=(164.152496, 159.119843), pressure=(0), tilt=(0, 0)
InputEventMouseButton : button_index=BUTTON_LEFT, pressed=true, position=(108, 107), button_mask=1, doubleclick=false
InputEventMouseButton : button_index=BUTTON_LEFT, pressed=false, position=(108, 107), button_mask=0, doubleclick=false
S
F
Alt
InputEventMouseMotion : button_mask=0, position=(108, 107), relative=(0, -1), speed=(164.152496, 159.119843), pressure=(0), tilt=(0, 0)
Como você pode ver, os resultados são muito diferentes para os diferentes tipos de entrada. Os eventos-chave são até impressos como seus símbolos-chave. Por exemplo, vamos considerar InputEventMouseButton. Ele herda das seguintes classes:
InputEvent - a classe base para todos os eventos de entrada
InputEventWithModifiers - adiciona a capacidade de verificar se modificadores foram pressionados, como Shift ou Alt.
InputEventMouse - adiciona propriedades de evento de mouse, como
position
InputEventMouseButton - contém o índice do botão que foi pressionado, se foi um clique duplo, etc.
Dica
É uma boa ideia manter a referência de classe aberta enquanto estiver trabalhando com eventos para que você possa verificar as propriedades e métodos disponíveis do tipo de evento.
Você pode encontrar erros se tentar acessar uma propriedade em um tipo de entrada que não a contém - chamando position
em InputEventKey
, por exemplo. Para evitar isso, teste primeiro o tipo de evento:
func _input(event):
if event is InputEventMouseButton:
print("mouse button event at ", event.position)
public override void _Input(InputEvent inputEvent)
{
if (inputEvent is InputEventMouseButton mouseEvent)
{
GD.Print("mouse button event at ", mouseEvent.Position);
}
}
InputMap¶
O InputMap é a maneira mais flexível de lidar com uma variedade de entradas. Você usa isso criando ações de entrada nomeadas, às quais você pode atribuir qualquer número de eventos de entrada, como pressionamentos de tecla ou cliques do mouse. Um novo projeto Godot inclui uma série de ações padrão já definidas. Para vê-los e adicionar o seu próprio, abra Projeto -> Configurações do Projeto e selecione a aba InputMap:
Capturando ações¶
Depois de definir suas ações, você pode processá-las em seus scripts usando is_action_pressed()
e is_action_released()
passando o nome da ação que você está procurando:
func _input(event):
if event.is_action_pressed("my_action"):
print("my_action occurred!")
public override void _Input(InputEvent inputEvent)
{
if (inputEvent.IsActionPressed("my_action"))
{
GD.Print("my_action occurred!");
}
}
Eventos de teclado¶
Eventos de teclado são capturados em InputEventKey. Embora seja recomendável usar ações de entrada, pode haver casos em que você queira examinar especificamente os principais eventos. Para este exemplo, vamos verificar o T:
func _input(event):
if event is InputEventKey and event.pressed:
if event.scancode == KEY_T:
print("T was pressed")
public override void _Input(InputEvent inputEvent)
{
if (inputEvent is InputEventKey keyEvent && keyEvent.Pressed)
{
if ((KeyList)keyEvent.Keycode == KeyList.T)
{
GD.Print("T was pressed");
}
}
}
Dica
Ver @GlobalScope_KeyList para uma lista de constantes de scancode.
Aviso
Devido ao fantasma do teclado, nem todas as entradas de teclas podem ser registradas em um determinado momento se você pressionar muitas teclas ao mesmo tempo. Devido à sua localização no teclado, certas teclas são mais propensas a serem fantasmas do que outras. Alguns teclados apresentam antighosting no nível do hardware, mas esse recurso geralmente não está presente em teclados de baixo custo e teclados de laptop.
Como resultado, é recomendável usar um layout de teclado padrão projetado para funcionar bem em um teclado sem antighosting. Consulte esta questão do Gamedev Stack Exchange para obter mais informações.
Modificadores de teclado¶
As propriedades do modificador são herdadas de InputEventWithModifiers. Isso permite verificar combinações de modificadores usando propriedades booleanas. Vamos imaginar que você queira que uma coisa aconteça quando o T for pressionado, mas algo diferente quando for Shift + T:
func _input(event):
if event is InputEventKey and event.pressed:
if event.scancode == KEY_T:
if event.shift:
print("Shift+T was pressed")
else:
print("T was pressed")
public override void _Input(InputEvent inputEvent)
{
if (inputEvent is InputEventKey keyEvent && keyEvent.Pressed)
{
switch ((KeyList)keyEvent.Scancode)
{
case KeyList.T:
GD.Print(keyEvent.Shift ? "Shift+T was pressed" : "T was pressed");
break;
}
}
}
Dica
Ver @GlobalScope_KeyList para uma lista de constantes de scancode.
Eventos do mouse¶
Os eventos de mouse derivam da classe InputEventMouse, e são separados em dois tipos: InputEventMouseButton e InputEventMouseMotion. Note que isto significa que todos os eventos de mouse irão conter uma propriedade position
.
Movimentação do mouse¶
InputEventMouseMotion ocorrem sempre que o mouse se move. Você pode encontrar a distância do movimento com a propriedade relative
.
Aqui está um exemplo usando eventos de mouse para arrastar e soltar um nó Sprite:
extends Node
var dragging = false
var click_radius = 32 # Size of the sprite.
func _input(event):
if event is InputEventMouseButton and event.button_index == BUTTON_LEFT:
if (event.position - $Sprite.position).length() < click_radius:
# Start dragging if the click is on the sprite.
if not dragging and event.pressed:
dragging = true
# Stop dragging if the button is released.
if dragging and not event.pressed:
dragging = false
if event is InputEventMouseMotion and dragging:
# While dragging, move the sprite with the mouse.
$Sprite.position = event.position
using Godot;
using System;
public class Node2D : Godot.Node2D
{
private bool dragging = false;
private int clickRadius = 32; // Size of the sprite.
public override void _Input(InputEvent inputEvent)
{
Sprite sprite = GetNodeOrNull<Sprite>("Sprite");
if (sprite == null)
{
return; // No suitable node was found.
}
if (inputEvent is InputEventMouseButton mouseEvent && (ButtonList)mouseEvent.ButtonIndex == ButtonList.Left)
{
if ((mouseEvent.Position - sprite.Position).Length() < clickRadius)
{
// Start dragging if the click is on the sprite.
if (!dragging && mouseEvent.Pressed)
{
dragging = true;
}
}
// Stop dragging if the button is released.
if (dragging && !mouseEvent.Pressed)
{
dragging = false;
}
}
else
{
if (inputEvent is InputEventMouseMotion motionEvent && dragging)
{
// While dragging, move the sprite with the mouse.
sprite.Position = motionEvent.Position;
}
}
}
}
Eventos de toque¶
Se você estiver usando um dispositivo touchscreen, poderá gerar eventos de toque. InputEventScreenTouch é equivalente a um evento de clique do mouse, e InputEventScreenDrag funciona da mesma forma que o movimento do mouse.
Dica
Para testar seus eventos de toque em um dispositivo sem tela sensível ao toque, abra as Configurações do projeto e vá para a seção "Dispositivos de entrada/Apontador". Ative "Emular toque do mouse" e seu projeto interpretará cliques e movimentos do mouse como eventos de toque.