监听玩家的输入
在上一课 创建第一个脚本 的基础上,让我们看看任何游戏的另一个重要特征:将控制权交给玩家。为了增加这一点,我们需要修改 sprite_2d.gd
的代码。
在 Godot 中,你有两个主要工具来处理玩家的输入:
内置的输入回调,主要是
_unhandled_input()
。和_process()
一样 ,它是一个内置的虚函数,Godot 每次在玩家按下一个键时都会调用。它是你想用来对那些不是每一帧都发生的事件做出反应的工具,比如按 Space 来跳跃。要了解更多关于输入回调的信息,请参阅 使用 InputEvent 。Input
单例。单例是一个全局可访问的对象。Godot 在脚本中提供对几个对象的访问。它是每一帧检查输入的有效工具。
我们这里将使用 Input
单例,因为我们需要知道在每一帧中玩家是否想转身或者移动。
对于转弯,我们应该使用一个新的变量:direction
。在我们的 _process()
函数中,将 rotation += angular_speed * delta
替换成以下代码。
GDScriptC#
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 direction = 0;
if (Input.IsActionPressed("ui_left"))
{
direction = -1;
}
if (Input.IsActionPressed("ui_right"))
{
direction = 1;
}
Rotation += _angularSpeed * direction * (float)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 = Vector2.UP.rotated(rotation) * speed``和``position += velocity * delta``两行代码注释,像这样:
GDScriptC#
#var velocity = Vector2.UP.rotated(rotation) * speed
#position += velocity * delta
//var velocity = Vector2.Up.Rotated(Rotation) * _speed;
//Position += velocity * (float)delta;
这将忽略在没有用户输入的情况下在圆中移动图标位置的代码。
如果你用这段代码运行场景,当你按下 Left(左方向键)和 Right(右方向键) 时,图标应该会旋转。
按“上”时移动
为了只在按键时移动,我们需要修改计算速度的代码。取消注释代码,并将以 var velocity
开头的行替换为下面的代码。
GDScriptC#
var velocity = Vector2.ZERO
if Input.is_action_pressed("ui_up"):
velocity = Vector2.UP.rotated(rotation) * speed
var velocity = Vector2.Zero;
if (Input.IsActionPressed("ui_up"))
{
velocity = Vector2.Up.Rotated(Rotation) * _speed;
}
我们将 velocity
的值初始化为 Vector2.ZERO
,这是内置 Vector
类型的一个常量,代表长度为 0 的二维向量。
如果玩家按下“ui_up”动作,我们就会更新速度的值,使精灵向前移动。
完整脚本
这是完整的 sprite_2d.gd
文件,仅供参考。
GDScriptC#
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
using Godot;
public partial class MySprite2D : Sprite2D
{
private float _speed = 400;
private float _angularSpeed = Mathf.Pi;
public override void _Process(double delta)
{
var direction = 0;
if (Input.IsActionPressed("ui_left"))
{
direction = -1;
}
if (Input.IsActionPressed("ui_right"))
{
direction = 1;
}
Rotation += _angularSpeed * direction * (float)delta;
var velocity = Vector2.Zero;
if (Input.IsActionPressed("ui_up"))
{
velocity = Vector2.Up.Rotated(Rotation) * _speed;
}
Position += velocity * (float)delta;
}
}
如果你运行这个场景,你现在应该能够用左右方向键进行旋转,并通过按 Up 向前移动。
总结
总之,Godot中的每个脚本都代表一个类,并扩展了引擎的一个内置类。在我们sprite的例子中,你的类所继承的节点类型可以让你访问一些属性,例如在“精灵” 例子中的 rotation
和 position
。你还继承了许多函数,但我们在这个例子中没有使用这些函数。
在 GDScript 中,放在文件顶部的变量是类的属性,也称为成员变量。除了变量之外,你还可以定义函数,在大多数情况下,这些函数将是类的方法。
Godot 提供了几个虚函数,你可以定义这些函数来将类与引擎连接起来。其中包括 _process()
,用于每帧将更改应用于节点,以及 _unhandled_input()
,用于接收用户的输入事件,如按键和按钮。还有很多。
Input
单例允许你在代码中的任何位置对玩家的输入做出反应。 尤其是,你在 _process()
循环中使用它。
在下一课 使用信号 中,我们会让节点触发脚本中的代码,让脚本和代码之间产生联系。