跳转到内容

使用 XNA/AI/人工智能进行游戏开发

来自维基教科书,开放世界中的开放书籍

游戏始终提供了一个开发人工智能的环境。因此,在过去几十年中,它成为了游戏中最重要的组成部分之一。如今,拥有复杂 AI 的游戏处于技术的前沿。您将在许多游戏中需要一些更简单的算法,也需要一些更复杂的算法。它在许多情况下使用,例如

  • 控制 NPC
  • 寻路
  • 动态游戏难度平衡
  • 战斗

早在 20 世纪 70 年代游戏开发的初期,程序员和开发者就遇到了游戏人工智能领域。但在那个时候,AI 很简单,可以说很谦虚,这种状态一直持续到几年前才改变。

"AI 已从游戏界的红头发继女悄悄转变为该行业的闪耀明星" - 史蒂夫·拉宾,AI 游戏编程智慧,2002 年,第 3 页

第一款以单人模式为特色的游戏,因此 AI 在其早期阶段就像雅达利游戏“Qwak!”一样,并没有像我们今天描述的那样拥有 AI。敌人的移动主要是预定义的,并以模式形式存储。只有随着硬件的改进,例如微处理器的加入,才允许进行更多的计算,才能实现更多随机元素。由此产生的游戏包括太空侵略者、银河战士和吃豆人。这些游戏呈现了例如不断提高的难度等级、复杂多样化的敌人移动、取决于玩家输入的事件,甚至每个敌人的不同个性。随着 20 世纪 90 年代新游戏类型的出现,新的 AI 工具被开发出来并使用。其中包括有限状态机。在较新的游戏中,AI 成为游戏的核心内容。AI 的改进不仅取决于给定的硬件组件。事实上,这绝对是一个非常重要的方面。有一些问题,如果没有足够的处理器资源,就无法解决。但应该补充的是,在游戏开发的初期,程序员并没有把 AI 太当回事。AI 通常是在完成所有高优先级任务后才完成的。[1]

如今,AI 已经爬上了游戏梯子的顶端,成为最高优先级任务。

游戏中存在无数需要人工智能的场景。那么,您如何解决追逐、群体行为或寻路问题呢?聪明的程序员和开发者想出了一些巧妙的技术和算法,为您的游戏增添了一丝智慧。以下将解释一些有趣的算法和 AI 场景。我不会声称这是一个完整的列表。但我会向您展示您将要面对的基本场景。[2]

追逐和躲避

[编辑 | 编辑源代码]

无论您拥有什么样的游戏,都有可能遇到追逐和躲避的情况。

基本算法

[编辑 | 编辑源代码]

描述追逐和躲避的最简单方法是,首先找出捕食者和猎物之间的距离,然后在追逐的情况下减小距离,在躲避的情况下增加距离。

追逐 躲避
if (predatorPos > preyPos)
  predatorPos --;
else if (predatorPos < preyPos)
  predatorPos ++;
if (preyPos> predatorPos )
  preyPos++;
else if (preyX < predatorPos )
  preyPos-- ?  > ;

它确实有效,但显然这不是一种非常自然的方法。

视线追逐

[编辑 | 编辑源代码]

让捕食者沿着直线朝向猎物移动,这更符合现实。

简单追逐 vs. 视线追逐

查找直线路径的算法稍微复杂一些。您需要找到一条直线且最短的路径,避免捕食者和猎物之间不必要的步骤。有很多有用的算法可以帮助我们解决这个问题。想想那些为像素环境构建的直线绘制算法。这些算法用于查找从起点到目的地的直线路径。但我们的算法还需要满足另一个标准,那就是找到最短路径。所以现在该向 Bresenham 求助了。Bresenham 的算法可以提供我们想要的东西。您可以在这里找到它。

对于捕食者来说,更有效的方法是在猎物轨迹的某个点拦截猎物。

拦截

应根据捕食者和猎物的相对位置和速度选择拦截点。为了预测该点,您必须考虑三个值。它们是位置、方向和速度。

计算步骤
[编辑 | 编辑源代码]
  1. 相对速度(接近速度)
  2. 相对距离(接近范围)
  3. 以等于接近速度的速度(接近时间)行驶相对距离所需的时间
  4. 猎物预测位置(目标点)


Vector FindInterceptingPoint(void)
{
  Vector v, d;
  Double t; 
  v = Prey.v - Predator.v; // closing velocity
  d = Prey.pos - Predator.pos; // range to close
  t = d.Magnitude() / v.Magnitude(); // time to close
  return Prey.pos + (Prey.v * t); // target point
}


模式移动

[编辑 | 编辑源代码]

不同移动和机动模式是预定义的。使用这些复杂模式的电脑控制角色会给人一种智能行为的错觉。标准算法使用编码指令列表或数组。这些指令告诉电脑控制角色在游戏循环中的每一步如何移动。

以下模式借自 O'REILLY 的《游戏开发者 AI》一书

Pattern[0].turnRight = 0;
Pattern[0].turnLeft = 0;
Pattern[0].stepForward = 2;
Pattern[0].stepBackward = 0;
Pattern[1].turnRight = 0;
Pattern[1].turnLeft = 0;
Pattern[1].stepForward = 2;
Pattern[1].stepBackward = 0;
Pattern[2].turnRight = 10;
Pattern[2].turnLeft = 0;
Pattern[2].stepForward = 0;
Pattern[2].stepBackward = 0;
Pattern[3].turnRight = 10;
Pattern[3].turnLeft = 0;
Pattern[3].stepForward = 0;
Pattern[3].stepBackward = 0;
Pattern[4].turnRight = 0;
Pattern[4].turnLeft = 0;
Pattern[4].stepForward = 2;
Pattern[4].stepBackward = 0;
Pattern[5].turnRight = 0;
Pattern[5].turnLeft = 0;
Pattern[5].stepForward = 2;
Pattern[5].stepBackward = 0;
Pattern[6].turnRight = 0;
Pattern[6].turnLeft = 10;
Pattern[6].stepForward = 0;
Pattern[6].stepBackward = 0;
.
.
.


该模式中编码的指令是

  1. 向前移动 2 个距离单位
  2. 向前移动 2 个距离单位
  3. 向右转 10 度
  4. 向右转 10 度
  5. 向前移动 2 个距离单位
  6. 向前移动 2 个距离单位
  7. 向左转 10 度


有时在游戏中,让非玩家角色以凝聚的群体移动更现实。让我们考虑鸟类、绵羊和所有这些总是躲在羊群安全中的群居动物。或者那些大型电脑控制的人类、巨魔或兽人单位。集群绝对是游戏中常见的表演。看看我从 roxlu 借来的剪辑:http://vimeo.com/5352863

基本算法

[编辑 | 编辑源代码]

有一些基本的集群算法来实现我们期望的行为。我们将看看 Craig Reynolds 算法。这种实现是无领导的。所有鸟类(Craig Reynolds 创造的术语,指的是模拟的鸟群)个体都遵循群体本身。

该算法遵循三个简单的规则

  • 分离
    转向以避免撞到邻居
  • 对齐
    转向以使其与邻居的平均航向对齐
  • 凝聚
    转向朝向邻居的平均位置

您可以在此处找到对该算法及其实现的解释:http://oreilly.com/catalog/ai/chapter/ch04.pdf

有成千上万个独立的寻路问题。您找不到一种算法作为所有这些问题的万能药方。即使 A* 算法(实际上是许多问题的理想解决方案)也不适合所有情况。

基本算法

[编辑 | 编辑源代码]

追逐和躲避章节中的算法进行了一些基本的寻路。我们澄清了视距算法创建了一种更现实的移动方式。现在让我们看一下避障

实现避障最简单的方法如下

if Player In Line of Sight
{
  Follow Straight Path to Player
}
else
{
  Move in Random Direction
}

这里的问题是由于它的简单性,它只适用于少量障碍物。让角色绕过障碍物会更有效:当角色与障碍物接壤时,它会在障碍物周围追踪。一旦目标进入角色的视线,它就会停止追踪。

[编辑 | 编辑源代码]

在这里,玩家本身正在为非玩家角色定义路径。这样,电脑控制的玩家看起来非常聪明。玩家在其走的每一步都留下了路标。非玩家角色只会沿着这些足迹前进。

路径跟随
[编辑 | 编辑源代码]

例如,您需要在赛车游戏中使用路径跟随。没有明确的目的地。只有一条预定义的道路必须遵循。

路点导航
[编辑 | 编辑源代码]

寻路是一项非常耗时的任务。特别是当您有一个具有大量障碍物的大环境时。路点减少了这个问题。主要思想是在游戏环境中放置节点,然后使用它们进行廉价的寻路算法。

A* 寻路
[编辑 | 编辑源代码]

A* 算法为寻路问题提供了一种有效的解决方案。

进一步的技术

[编辑 | 编辑源代码]

我们查看了许多需要 AI 方法的游戏玩法情况。但这些并非全部。如果您好奇,请查看 O'REILLY 的《游戏开发者 AI》一书

乒乓球

[编辑 | 编辑源代码]

Pong 最初由 Atari 于 1972 年发布。它包含一个黑色屏幕,屏幕两侧各有一个球拍,中间有一个球。球拍由玩家控制,玩家可以上下移动球拍来接住左右移动的球。如果一方玩家错过球,对方将获得一分。当一方玩家达到一定分数(例如 10 分)时,游戏结束。[3]

Pong 中的 AI

[edit | edit source]

如果你选择与电脑对战,实际上你是在与一个 AI 算法对抗。你总是面临着是否向上、向下移动球拍,或者保持静止的决策。电脑也是如此。

第一种方法

[edit | edit source]

解决这个问题的一个简单方法是分析球的当前状态(位置和运动方向),然后决定如何移动球拍。通过知道球的方向(以度数表示的角度),你可以确定球是在屏幕上向上还是向下移动。电脑现在可以计算球和球拍在 y 轴上的位置差,并根据这个信息决定将球拍向下或向上移动,以减少这个差值,理想情况下直到差值变为 0。如果差值接近 0,球拍可以停止,等待球的运动需要采取其他动作。

int difference = ball.positionY  paddle.positionY;

if(difference >= 5 || difference <= -5)
{
	if(difference > 0)
	{
		paddle.moveDown();
	}
	else
	{
		paddle.moveUp();
	}
}

这种方法的优点是易于实现。它不需要太多计算量(性能良好),并且往往会犯一些错误,或者在某些情况下措手不及。因此,它看起来更像人类操作,并且是可以战胜的。对于电脑 AI 来说,一种会让它措手不及的情况是,当球拍向上跟随球移动时,在球到达球拍边缘之前,球撞到了顶壁并改变了方向向下移动。在这种情况下,球拍可能反应太慢(尤其是在更高水平时球的速度更快),无法对方向变化做出反应,从而失去球。

第二种方法

[edit | edit source]

第二种方法稍微复杂一点,需要更多的计算。你只需要球的当前位置和当前运动方向——这些都是你可以从游戏引擎中获取的信息。根据这些值,可以确定球的未来运动轨迹(包括所有墙壁碰撞和方向变化),以及球最终可能击中 AI 玩家球拍的位置。如果你找到了这个点——而且这个点永远不会改变,因为标准的 Pong 游戏没有突然发生事件来改变球的方向——你只需要直接将球拍移动到这个点上,就能接住球,并将球击回对手的半场。这种方法也可以稍微修改,将球拍放置在击球时能击中球拍角落的位置,使其稍微旋转一下。

即使它是解决这个问题的改进方案,也有一些缺点。它更难实现,可能需要更长时间,并且需要更多资源来计算球的最终位置(对于移动电话、掌上游戏机等慢速系统来说可能太慢),最重要的是(在我看来),你将有一个实际上不可战胜的完美对手,因为它总是以最佳方式击球,这对于真正的玩家来说可能很烦人。


更多示例

[edit | edit source]
  • Eliza
  • 井字棋

困难

[edit | edit source]

AI 必须在游戏过程中实时计算,因此(良好)性能对于让游戏流畅运行至关重要。为了确保这一点,许多简化、变通方法、算法中的作弊行为会模拟玩家的理想行为。这样既快又聪明。当性能是一个重要问题时,很明显,对所有可能的决策进行暴力破解并不是处理游戏 AI 中这种情况的最佳方法。

另一个关键事实是,即使电脑玩家能够做到完美,也不应该完美地玩游戏。作弊在这个话题中是一个很大的词,因为电脑知道所有事实,并拥有关于游戏世界的各种信息,因此可以让 AI 玩家了解一些在现实中不应该知道的事情。玩家必须认为自己是在与真正的对手对战,而不是与电脑对战,这就是为什么首先 AI 必须是可以战胜的(而不是无敌的),而且它必须表现得像人类一样(犯错、在某些情况下随机行动等)。如果 AI 没有以这种方式行事,游戏很快就会对玩家变得非常无聊,或者如果玩家没有机会获胜就会令人沮丧。一些游戏使用近似算法而不是完美的解决方案,并在它们的算法中实施“错误的”(或更差的)决策。

六条经验法则和启发式方法,足以提供良好的游戏体验

参考文献

[edit | edit source]
  1. Steve Rabin (2002). AI Game Programming Wisdom. Cengage Learning.
  2. David M. Bourg, Glenn Seemann (2004). AI for Game Developers. O'Reilly Media.
  3. http://en.wikipedia.org/wiki/Pong

作者

[edit | edit source]
  • iSteffi
华夏公益教科书