监听玩家的输入

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.gd code.

../../_images/scripting_first_script_moving_with_input.gif

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

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

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

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

For turning, we should use a new variable: direction. In our _process() function, replace the rotation += angular_speed * delta line with the code below.

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”动作,我们就会更新速度的值,使精灵向前移动。

Complete script

这是完整的 Sprite.gd 文件,仅供参考。

extends Sprite

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() 循环中使用它。

In the next lesson Using signals, we'll build upon the relationship between scripts and nodes by having our nodes trigger code in scripts.