输入示例
简介
在本教程中,您将学习如何使用Godot的 输入事件 系统捕获玩家输入.您的游戏可以使用多种不同类型的输入——键盘,游戏手柄,鼠标等等.还有许多不同的方法,将这些输入转化为游戏中的动作.本文将向您展示一些最常见的场景,您可以将其作为您自己项目的起点.
注解
要详细了解Godot的输入事件系统是如何工作的,请见 文档_输入事件 .
事件和轮询
有时你想让你的游戏对某一输入事件作出反应—例如按下 “跳跃” 按钮.在其他情况下,你可能希望只要有一个键被按下就会发生一些事情,比如移动.在第一种情况下,你可以使用 _input()
函数,只要有输入事件发生就会调用该函数.在第二种情况下,Godot提供了 Input 单例,你可以用它来查询一个输入的状态.
示例:
GDScript
C#
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;
}
}
这使您能够灵活地混合和匹配所执行输入的处理类型.
对于本教程的其余部分,我们将专注于使用 _input ()
捕捉单个事件.
输入事件
输入事件是继承自 输入事件 的对象.根据事件类型,对象将包含与该事件相关的特定属性.为了了解事件的实际情况,添加一个节点并附加以下脚本:
GDScript
C#
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());
}
}
当你按下按键,移动鼠标,并执行其他输入,您会在输出窗口中看到每个事件滚动.下面是输出的一个例子:
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)
如你所见,对于不同类型的输入,结果是非常不同的.按键事件甚至被打印为按键符号.例如,让我们考虑 鼠标按钮输入事件 .它继承自以下类:
InputEvent - 所有输入事件的基类
InputEventWithModifiers - 增加了检查是否按下修饰按键,如 Shift 或 Alt .
InputEventMouse - 增加鼠标事件属性,如
position
鼠标按钮输入事件 包含按下的按钮的索引,无论是双击,或是其他.
小技巧
在处理事件时,打开类引用是一个好主意,这样可以检查事件类型的可用属性和方法.
如果您尝试访问不包含属性的输入类型上的属性,则可能会遇到错误-例如,对 InputEventKey
调用 Position
.要避免这种情况,请确保首先测试事件类型:
GDScript
C#
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
事件表 是处理各种输入的最灵活的方法.您可以通过创建命名的输入 动作 来使用它,可以为它分配任意数量的输入事件,例如按键或鼠标点击.一个新的Godot项目已经包含许多默认定义操作.看看它们,然后添加你自己的,打开项目->项目设置,并选择事件表选项卡:
捕捉动作
一旦你定义了动作,可以在脚本中使用 is_action_pressed()
和 is_action_released ()
处理它们.通过名称查找响应的动作:
GDScript
C#
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!");
}
}
键盘事件
键盘事件在 InputEventKey 中被捕获.虽然建议使用输入动作来代替,但在某些情况下,你可能会想专门查看按键事件.对于当前示例,来检查一下 T :
GDScript
C#
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.Scancode == KeyList.T)
{
GD.Print("T was pressed");
}
}
}
小技巧
详见 全局范围_键位列表 获取扫描代码常量列表.
键盘修饰键
修饰键属性继承自 InputEventWithModifiers ,可使用布尔属性检查修饰键组合.试想,当按下 T 时,发生一件事,但当按下 Shift + T 时,却发生不同的事情:
GDScript
C#
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;
}
}
}
小技巧
详见 全局范围_键位列表 获取扫描代码常量列表.
鼠标事件
鼠标事件继承自 鼠标输入事件 ,并被分成两种类型 : 鼠标按钮输入事件 和 鼠标移动输入事件 .注意,这意味着所有鼠标事件将包含一个 位置(position) 属性.
鼠标按钮
捕获鼠标按钮与处理按键事件非常相似. @全局作用域_按钮列表 包含每个可能按钮的 BUTTON_* 常量列表,它将在事件的 button_index(按钮_索引)
属性中报告.注意,鼠标滚轮也可以算作一个按钮——准确地说,是两个按钮, BUTTON_WHEEL_UP(按钮_滚轮_向上)
和 BUTTON_WHEEL_DOWN(按钮_滚轮_向下)
都是独立的事件.
GDScript
C#
func _input(event):
if event is InputEventMouseButton:
if event.button_index == BUTTON_LEFT and event.pressed:
print("Left button was clicked at ", event.position)
if event.button_index == BUTTON_WHEEL_UP and event.pressed:
print("Wheel up")
public override void _Input(InputEvent inputEvent)
{
if (inputEvent is InputEventMouseButton mouseEvent && mouseEvent.Pressed)
{
switch ((ButtonList)mouseEvent.ButtonIndex)
{
case ButtonList.Left:
GD.Print("Left button was clicked at ", {mouseEvent.Position});
break;
case ButtonList.WheelUp:
GD.Print("Wheel up");
break;
}
}
}
鼠标行为
InputEventMouseMotion 只要鼠标移动就会发生事件.可以通过 relative
属性找到移动的距离.
下面是一个使用鼠标事件拖放 精灵 节点的例子:
GDScript
C#
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;
}
}
}
}
触摸事件
如果使用触摸屏设备,可以生成触摸事件. 触摸屏幕输入事件 相当于鼠标点击事件,并且 拖拽屏幕输入事件 的工作原理与鼠标移动非常相似.
小技巧
要在非触摸屏设备上测试触摸事件,打开项目设置,进入”输入设备(Input Devices)/指向(Pointing)”部分.启用”模拟鼠标触摸”,您的项目将把鼠标单击和移动解释为触摸事件.