输入示例

前言

在本教程中, 您将学习如何使用Godot的 输入事件 系统捕获玩家输入. 您的游戏可以使用多种不同类型的输入——键盘, 游戏手柄, 鼠标等等. 还有许多不同的方法, 将这些输入转化为游戏中的动作. 本文将向您展示一些最常见的场景, 您可以将其作为您自己项目的起点.

备注

要详细了解 Godot 的输入事件系统是如何工作的,请参阅 使用 InputEvent

事件和轮询

有时你想让你的游戏对某一输入事件作出反应--例如按下 "跳跃" 按钮. 在其他情况下, 你可能希望只要有一个键被按下就会发生一些事情, 比如移动. 在第一种情况下, 你可以使用 _input() 函数, 只要有输入事件发生就会调用该函数. 在第二种情况下,Godot提供了 Input 单例, 你可以用它来查询一个输入的状态.

示例:

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

这使您能够灵活地混合和匹配所执行输入的处理类型.

对于本教程的其余部分, 我们将专注于使用 _input () 捕捉单个事件.

输入事件

输入事件是继承自 输入事件 的对象. 根据事件类型, 对象将包含与该事件相关的特定属性. 为了了解事件的实际情况, 添加一个节点并附加以下脚本:

extends Node


func _input(event):
    print(event.as_text())

当你按下按键, 移动鼠标, 并执行其他输入, 您会在输出窗口中看到每个事件滚动. 下面是输出的一个例子:

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)

如你所见, 对于不同类型的输入, 结果是非常不同的. 按键事件甚至被打印为按键符号. 例如, 让我们考虑 鼠标按钮输入事件 . 它继承自以下类:

小技巧

在处理事件时, 打开类引用是一个好主意, 这样可以检查事件类型的可用属性和方法.

如果您尝试访问不包含属性的输入类型上的属性, 则可能会遇到错误-例如, 对 InputEventKey 调用 Position . 要避免这种情况, 请确保首先测试事件类型:

func _input(event):
    if event is InputEventMouseButton:
        print("mouse button event at ", event.position)

InputMap

事件表 是处理各种输入的最灵活的方法. 您可以通过创建命名的输入 动作 来使用它, 可以为它分配任意数量的输入事件, 例如按键或鼠标点击. 一个新的Godot项目已经包含许多默认定义操作. 看看它们, 然后添加你自己的, 打开项目->项目设置, 并选择事件表选项卡:

../../_images/inputs_inputmap.png

捕捉动作

一旦你定义了动作, 可以在脚本中使用 is_action_pressed()is_action_released () 处理它们. 通过名称查找响应的动作:

func _input(event):
    if event.is_action_pressed("my_action"):
        print("my_action occurred!")

键盘事件

键盘事件在 InputEventKey 中被捕获. 虽然建议使用输入动作来代替, 但在某些情况下, 你可能会想专门查看按键事件. 对于当前示例, 来检查一下 T :

func _input(event):
    if event is InputEventKey and event.pressed:
        if event.scancode == KEY_T:
            print("T was pressed")

小技巧

详见 全局范围_键位列表 获取扫描代码常量列表.

警告

Due to keyboard ghosting, not all key inputs may be registered at a given time if you press too many keys at once. Due to their location on the keyboard, certain keys are more prone to ghosting than others. Some keyboards feature antighosting at a hardware level, but this feature is generally not present on low-end keyboards and laptop keyboards.

As a result, it's recommended to use a default keyboard layout that is designed to work well on a keyboard without antighosting. See this Gamedev Stack Exchange question for more information.

键盘修饰键

修饰键属性继承自 InputEventWithModifiers ,可使用布尔属性检查修饰键的组合。试想,如果需要在按下 T 时发生一件事,而按下 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")

小技巧

详见 全局范围_键位列表 获取扫描代码常量列表.

鼠标事件

鼠标事件继承自 InputEventMouse 并被分成 InputEventMouseButtonInputEventMouseMotion 两种类型。注意,这意味着所有鼠标事件都包含 position 属性。

鼠标按钮

捕获鼠标按钮与处理按键事件非常相似。@GlobalScope_ButtonList 包含每个可能按钮的 BUTTON_* 常量列表,它将在事件的 button_index 属性中报告。注意,鼠标滚轮也可以算作一个按钮——准确地说是两个按钮,BUTTON_WHEEL_UP(滚轮键向上)和 BUTTON_WHEEL_DOWN(滚轮键向上)都是独立的事件。

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")

鼠标行为

InputEventMouseMotion 只要鼠标移动就会发生事件. 可以通过 relative 属性找到移动的距离.

下面是一个使用鼠标事件拖放 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

触摸事件

如果你使用的是触摸屏设备,就可以生成触摸事件。InputEventScreenTouch 相当于鼠标点击事件,而 InputEventScreenDrag 的工作原理与鼠标移动一致。

小技巧

要在非触摸屏设备上测试触摸事件,请打开“项目设置”,进入“Input Devices/Pointing”(输入设备/触点)部分。启用“Emulate Touch From Mouse”(根据鼠标模拟触摸),您的项目将把鼠标单击和移动解释为触摸事件。