Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

监听玩家的输入

Building upon the previous lesson 创建第一个脚本, let's look at another important feature of any game: giving control to the player. To add this, we need to modify our sprite_2d.gd code.

../../_images/scripting_first_script_moving_with_input.gif

在 Godot 中,你有两个主要工具来处理玩家的输入:

  1. 内置的输入回调,主要是 _unhandled_input()。像 _process(),它是一个内置的虚函数,Godot 每次在玩家按下一个键时都会调用。它是你想用来对那些不是每一帧都发生的事件做出反应的工具,比如按 Space 来跳跃。要了解更多关于输入回调的信息,请参阅 使用 InputEvent

  2. Input 单例。单例是一个全局可访问的对象。Godot 在脚本中提供对几个对象的访问。它是每一帧检查输入的有效工具。

我们这里将使用 Input 单例,因为我们需要知道在每一帧中玩家是否想转身或者移动。

对于转弯,我们应该使用一个新的变量:direction。在我们的 _process() 函数中,将 rotation += angular_speed * delta 替换成以下代码。

var direction = 0
if Input.is_action_pressed("ui_left"):
    direction = -1
if Input.is_action_pressed("ui_right"):
    direction = 1

rotation += angular_speed * direction * delta

我们的 direction 局部变量是一个乘数,代表玩家想要转向的方向。0 的值表示玩家没有按左或右方向键。1 表示玩家想向右转,而 -1 表示他们想向左转。

为了产生这些值,我们引入了条件和 Input 的使用。条件以 GDScript 中的 if 关键字开始,以冒号结束。条件是关键字和行末之间的表达式。

为了检查当前帧玩家是否按下了某个键,我们需要调用 Input.is_action_pressed()。这个方法使用一个字符串来表示一个输入动作。当该按键被按下时,函数返回 true,否则这个函数将返回 false

上面我们使用的两个动作,“ui_left”和“ui_right”,是每个 Godot 项目中预定义的。它们分别在玩家按键盘上的左右箭头或游戏手柄上的左右键时触发。

备注

打开“项目 -> 项目设置”并点击“输入映射”选项卡,就可以查看并编辑项目中的输入动作。

最后,当我们更新节点的 rotation 时,我们使用 direction 作为乘数:rotation += angular_speed * direction * delta

如果你用这段代码运行场景,当你按下 左方向键右方向键 时,图标应该会旋转。

按“上”时移动

为了只在按下一个键时移动,我们需要修改计算速度的代码。用下面的代码替换以 var velocity 开始的一行。

var velocity = Vector2.ZERO
if Input.is_action_pressed("ui_up"):
    velocity = Vector2.UP.rotated(rotation) * speed

我们将 velocity 的值初始化为 Vector2.ZERO,这是内置 Vector 类型的一个常量,代表长度为 0 的二维向量。

如果玩家按下“ui_up”动作,我们就会更新速度的值,使精灵向前移动。

完整脚本

Here is the complete sprite_2d.gd file for reference.

extends Sprite2D

var speed = 400
var angular_speed = PI


func _process(delta):
    var direction = 0
    if Input.is_action_pressed("ui_left"):
        direction = -1
    if Input.is_action_pressed("ui_right"):
        direction = 1

    rotation += angular_speed * direction * delta

    var velocity = Vector2.ZERO
    if Input.is_action_pressed("ui_up"):
        velocity = Vector2.UP.rotated(rotation) * speed

    position += velocity * delta

如果你运行这个场景,你现在应该能够用左右方向键进行旋转,并通过按 Up 向前移动。

../../_images/scripting_first_script_moving_with_input.gif

总结

总之,Godot中的每个脚本都代表一个类,并扩展了引擎的一个内置类。在我们sprite的例子中,你的类所继承的节点类型可以让你访问一些属性,如 rotationposition 。你还继承了许多函数,但我们在这个例子中没有使用这些函数。

在 GDScript 中,放在文件顶部的变量是类的属性,也称为成员变量。除了变量之外,您还可以定义函数,在大多数情况下,这些函数将是类的方法。

Godot 提供了几个虚函数,您可以定义这些函数来将类与引擎连接起来。其中包括 _process() ,用于每帧将更改应用于节点,以及 _unhandled_input() ,用于接收用户的输入事件,如按键和按钮。还有很多。

Input 单例允许您在代码中的任何位置对玩家的输入做出反应。 尤其是,你在 _process() 循环中使用它。

在下一课 使用信号 中,我们会让节点触发脚本中的代码,让脚本和代码之间产生联系。