目录
-
- 可预测随机数
- 生成真正的随机数
- 随机数生成
一、可预测随机数
前言:
细节丰富的背景已成为成功游戏的重要因素,游戏中的各种动作正式在此前景之上发送的。不仅如此,背景还在玩家与游戏的交互中扮演着积极的角色。为了得到这种效果,传统的方法是将手工制作的关卡数据提取出来,然后保存在一个相对复杂、占用空间较大的关卡文件里,以备实时重放。但即便拥有强劲的资源配置,对于规模宏大而复杂的游戏而言,开发者也常常缺乏足够的空间进行调配。如果关卡数据不足,可能会使游戏的深度低于玩家的期望值。本文研究的是一种能用于提供给玩家应得的游戏深度同时无需过多空间的技术。
可预测随机数
这一技术最重要的原则是:为了在一个游戏世界中给出无限空间的幻觉,我们需要满足两个分解条件:宏无限和微无限。宏无限涉及到问题的空间规模,或者说离散的实体数目。微无限则表明了每个对象所支持的细节级别。
首先,每个游戏世界的对象都可用它的一个特征集来表示(比如方位坐标)。以此特征集,通过可预测随机数序列来生成随机数并作为该对象的特定属性。每当我们需要一个数字序列时,需要一个二级操作——给定发生器一个种子数来繁殖序列。当我们给出同一个种子数时总会生成同一个序列,这样序列就可以重复。因为它可以快速生成,我们就可以不必存储它(随机序列),这样就能得到一个近乎无限的游戏世界,同时极大减少静态存储的需求。
以下为伪代码:一个给定有限规模的星系,假设栅格为100*100,我们就有10000个可能的空间存放恒星。随机数根据恒星位置(假设为二维空间,由x、y决定)产生,当随机数>70,则说明该位置存在恒星。srand()为发生器,当给定种子相同时能得到相同的随机数序列。
srand(1)
for galaxy_x = 1 to 100
for galaxy_y 1to 100
probability = rand() % 100
if probability> 70 then
universe(galaxy_x,galaxy_y) = star
else
universe(galaxy_x,galaxy_y) = no star
上述方法有一个缺点,我们仍然需要存储每个恒星的位置。我们想得到一个接近无限的总体,最好是按需进行计算。代码如下:
int Start(int nGalaxy,int nX,int nY)
{
int x,y.nReturn;
srand(nGalaxy);
for(y=0;y<=nY;y++)
{
for(x=0;x<nX;x++)
{
nReturn = rand() % MAXIMUM_VALUE;
}
}
return nReturn;
}
替换算法
首先我们得到一个可重复的数字序列,它由一个给定的模式开始(一个乘法和一个加法),然后打破这一模式,由一个除法得到余数。然后再使用得到的结果生成一个具有同一基础方程式的新序列。这样,一个相当随机的序列就建成了。伪代码如下:
限制:这种方法系统最大能生成数字是32位的无符号数,即4294967295,除此之外迭代4294967295次后序列会重复生成。如果需要更大的数字,必须改用不同的表示法。
无限宇宙算法
上文介绍了针对特定的游戏中的区域来确定某个给定的特征,这解决了一半的问题——宏无限分解。接下来将介绍使用伪随机数处理游戏对象