四处旋转
是时候让节点移动并旋转了。为此,我们要向脚本添加两个成员变量:移动速度(像素/秒)和角速度(弧度/秒)。请在 extends Sprite2D 后面另起一行,添加如下代码。
GDScriptC#var speed = 400
var angular_speed = PI
private int _speed = 400;
private float _angularSpeed = Mathf.Pi;
成员变量位于脚本的顶部,在“extends”之后、函数之前。附加了此脚本的每个节点实例都将具有自己的 speed 和 angular_speed 属性副本。
备注
与其他一些引擎一样,Godot 中的角度默认使用弧度为单位,但如果你更喜欢以度为单位计算角度,则可以使用内置函数和属性。
为了移动我们的图标,我们需要在游戏循环中每一帧更新其位置和旋转。我们可以使用 Node 类中的虚函数 _process()。如果你在任何扩展自 Node 类的类中定义它,如 Sprite2D,Godot将在每一帧调用该函数,并传递给它一个名为 delta 的参数,即从上一帧开始经过的时间。
备注
游戏的工作方式是每秒钟渲染许多图像,每幅图像称为一帧,而且是循环进行的。我们用每秒帧数(FPS)来衡量一个游戏产生图像的速度。大多数游戏的目标是60FPS,尽管你可能会发现在较慢的移动设备上的数字是30FPS,或者是虚拟现实游戏的90至240。
引擎和游戏开发者尽最大努力以恒定的时间间隔更新游戏世界和渲染图像,但在帧的渲染时间上总是存在着微小的变化。这就是为什么引擎为我们提供了这个delta时间值,使我们的运动与我们的帧速率无关。
在脚本的底部,定义该函数:
GDScriptC#func _process(delta):
rotation += angular_speed * delta
public override void _Process(double delta)
{
Rotation += _angularSpeed * (float)delta;
}
func 关键字定义了一个新函数。在它之后,我们必须在括号里写上函数的名称和它所接受的参数。冒号结束定义,后面的缩进块是函数的内容或指令。
备注
请注意 _process() 和 _init() 一样都是以下划线开头的。按照约定,这是 Godot 的虚函数,也就是你可以覆盖的与引擎通信的内置函数。
函数内部的那一行 rotation += angular_speed * delta 每一帧都会增加我们的精灵的旋转量。这里 rotation 是从 Sprite2D 所扩展的 Node2D 类继承的属性。它可以控制我们节点的旋转,以弧度为单位。
小技巧
在代码编辑器中,你可以按住 Ctrl 键(在macOS上使用 Command 键) 单击任何内置的属性或函数,如 position、rotation、_process 以在新标签页中打开相应的文档。
运行该场景,可以看到 Godot 的图标在原地转动。
备注
在 C# 中,请注意 _Process() 所采用的 delta 参数类型是 double。 故当我们将其应用于旋转时,需要将其转换为 float 。
前进
现在我们来让节点移动。在 _process() 函数中添加下面两行代码,确保每一行都和之前的 rotation += angular_speed * delta 行的缩进保持一致。
GDScriptC#var velocity = Vector2.UP.rotated(rotation) * speed
position += velocity * delta
var velocity = Vector2.Up.Rotated(Rotation) * _speed;
Position += velocity * (float)delta;
正如我们所看到的,var 关键字可以定义新变量。如果你把它放在脚本顶部,定义的就是类的属性。在函数内部,定义的则是局部变量:只在函数的作用域中存在。
我们定义一个名为 velocity 的局部变量,该变量是用于表示方向和速度的 2D 向量。要让节点向前移动,我们可以从 Vector2 类的常量 Vector2.UP 入手,这个向量指向上方,调用 Vector2 的 rotated() 方法可以将其进行旋转。表达式 Vector2.UP.rotated(rotation) 表示的是指向图标前方的向量。用这个方向与我们的 speed 属性相乘后,得到的就是用来移动节点的速度。
我们在节点的 position 里加上 velocity * delta 来实现移动。位置本身是 Vector2 类型的,是 Godot 用于表示 2D 向量的内置类型。
运行场景就可以看到 Godot 头像在绕圈圈。
备注
使用这样的方法不会考虑与墙壁和地面的碰撞。在 你的第一个 2D 游戏 中,你会学到另一种移动对象的方法,可以检测碰撞。
我们的节点目前是自行移动的。在下一部分 监听玩家的输入 中,我们会让玩家的输入来控制它。