概述
计算机程序是精确的艺术,现实生活却充满了随机性。如果你的游戏缺乏了随机性,也就缺乏了最基础的乐趣。
我们在很多场景下需要使用随机数,来为已经非常刻意和规整的设计带来一些变化和趣味。
比如打怪、打完Boss或开宝箱后随机掉落不同的物品,随机生成地图,判定某次攻击的命中率等等。
要想成为游戏设计高手,随机数的学习和使用是躲不开的命题。
本篇讲解Godot内置脚本GDScript提供的随机数生成类和方法,带你进入游戏设计随机数的大门。
真随机数和伪随机数
基本定义
在这之前需要先明白一点:随机数都是由随机数生成器(Random Number Generator)生成的。
真随机数(TRUE Random Number)
真正的随机数是使用物理现象产生的:比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等等,这样的随机数发生器叫做物理性随机数发生器,它们的缺点是技术要求比较高。 ----百度百科
伪随机数(Pseudo-Random Number)
真正意义上的随机数(或者随机事件)在某次产生过程中是按照实验过程中表现的分布概率随机产生的,其结果是不可预测的,是不可见的。
而计算机中的随机函数是按照一定算法模拟产生的,其结果是确定的,是可见的。我们可以这样认为这个可预见的结果其出现的概率是100%。所以用计算机随机函数所产生的“随机数”并不随机,是伪随机数。
从定义我们可以了解到,伪随机数其实是有规律的。只不过这个规律周期比较长,但还是可以预测的。主要原因就是伪随机数是计算机使用算法模拟出来的,这个过程并不涉及到物理过程,所以自然不可能具有真随机数的特性。
在GDScript中使用随机数
GDScript提供了一个名叫RandomNumberGenerator
的类用于生成随机数,直译过来就是“随机数生成器”。下图是它的一个简要总结图。
extends Node2Dvar rng = RandomNumberGenerator.new()func _ready():rng.randomize() # 为RNG设置基于时间的种子print(rng.randi()) # 生成整数pass
以上的代码生成的是一个比较大的随机整数。
randi()
中的i
就是int
或者integer
,也就是“整数”意思。- 你可以看到还有一个函数
randf()
,它的f
,就是float
,“浮点数”的意思。
这样理解和记忆起来就不会费劲了。
randi()
值得注意的是,randi()
只会生成无符号整数,也就是始终返回一个正整数。
因为它返回的数比较大,所以要限定其范围获得一个比较小的数,就需要用运算符%
,后面跟一个整数。这是一种特定的写法:
rng.randi() # 返回 0 和 2^32 - 1 之间的随机整数
rng.randi() % 20 # 返回0到19之间的随机整数
rng.randi() % 20 + 1 # 返回1到20之间的随机整数
rng.randi() % 100 # 返回0到99之间的随机整数
rng.randi() % 100 + 1 # 返回1和100之间的随机整数
randf()
而randf()
返回的是0.0
到1.0
之间的小数,print
出来的是带六位小数的浮点数。
如果想要获得一个大一点的数,就需要在randf()
之上乘以一个整数。
rng.randf() * 10 # 返回0-10之间的浮点数
randi_range()和randf_range()
很多时候我们只需要一个小范围内的随机数。可以使用带_range
后缀的两个方法来限定范围。
rng.randi_range(1,10)
rng.randi_range(-10,10)
rng.randf_range(1.0,10.0)
rng.randf_range(-10.0,10.0)
randomize()的作用
RandomNumberGenerator
生成伪随机数是靠“随机数种子”。randomize()
的作用是生成一个基于时间的随机数种子,只要这个随机数种子发生了变化,用其方法生成的伪随机数才会发生变化,否则,返回的还是之前的随机数数列。
随机数生成器的状态
RandomNumberGenerator
的state
属性是一个整数值,保存了它的状态,有点像随机数种子,只要我们记录和恢复了它,也就意为着可以还原整个随机数生成器的状态,生成一模一样的随机数数列。
var rng = RandomNumberGenerator.new()
print(rng.randf())
var saved_state = rng.state # 存储当前状态。
print(rng.randf()) # 提前进入内部状态。
rng.state = saved_state # 存储状态
print(rng.randf()) # 打印与上一次相同的值。
@GDScript内置的相关随机数生成函数
GDScript内置函数里,有几个和RandomNumberGenerator
方法近乎一致的一些方法,我们可以直接拿来使用。
参考
- CSDN博主「绘夜」,《随机数:真随机数和伪随机数》
- 百度百科
- Godot相关API的内置文档