我在《吃豆人》中找到了很多有关鬼魂AI的参考文献,但没有人提到吃豆子吃掉鬼魂后眼睛如何回到中央鬼洞。
在我的实现中,我实现了一个简单但糟糕的解决方案。我只是在每个角落都硬编码了应该采取的方向。
有没有更好的解决方案?也许是一种适用于不同级别设计的通用产品?
我在《吃豆人》中找到了很多有关鬼魂AI的参考文献,但没有人提到吃豆子吃掉鬼魂后眼睛如何回到中央鬼洞。
在我的实现中,我实现了一个简单但糟糕的解决方案。我只是在每个角落都硬编码了应该采取的方向。
有没有更好的解决方案?也许是一种适用于不同级别设计的通用产品?
Answers:
实际上,我想说您的方法是一个很棒的解决方案,与任何寻路方法相比,运行时间成本几乎为零。
如果您需要将其推广到任意地图,则可以使用任何寻路算法-例如,广度优先搜索易于实现-并在运行游戏之前使用该算法来计算在每个角上要编码的方向。
编辑(2010年8月11日):我刚刚被引到有关Pacman系统的一个非常详细的页面:Pac-Man Dossier,并且由于我在这里有公认的答案,因此我觉得我应该对其进行更新。这篇文章似乎没有明确介绍返回怪物屋的行为,但指出吃豆人中的直接寻路是以下情况:
我已经通过以下方式解决了通用关卡的这个问题:在关卡开始之前,我从怪物洞中进行了某种“洪水填充”;迷宫中每块不是墙的瓷砖都会得到一个数字,说明它离孔有多远。因此,当眼睛在距离为68的图块上时,他们会看哪个相邻的图块之间的距离为67;那就是要走的路。
对于更传统的寻路算法的替代方法,您可以看一下(适当命名的!)Pac-Man Scent Antiobject模式。
您可以在启动时在迷宫周围散布怪异的气味,并让眼睛跟随它。
气味一旦建立,运行时间成本将非常低。
编辑:可悲的是维基百科的文章已被删除,所以WayBack Machine营救 ...
您应该看一下寻径算法,例如Dijsktra的Algorithm或A * algorithm。这就是您的问题:图形/路径问题。
任何可行的简单解决方案都是可维护,可靠且性能良好的解决方案。在我看来,您已经找到了一个很好的解决方案...
寻路解决方案可能比您当前的解决方案更为复杂,因此更可能需要调试。可能还会变慢。
IMO,如果它没有损坏,请不要修复它。
编辑
IMO,如果迷宫是固定的,那么您当前的解决方案就是好的/优雅的代码。不要把“好”或“优雅”等同于“聪明”。简单的代码也可以是“好”和“优雅”的。
如果您具有可配置的迷宫等级,那么也许您应该在最初配置迷宫时进行寻路。最简单的方法就是让迷宫设计师手工完成。如果您有成千上万的迷宫,或者用户可以设计它们,我只会自动进行此操作。
(此外:如果通过手动配置路线,迷宫设计者可以通过使用次优路线来使关卡更加有趣...)
在原始的《吃豆人》中,鬼魂通过“气味”找到了吃黄色药丸的人,他会在地图上留下痕迹,鬼魂会随机游荡直到找到气味,然后他们便沿着气味路径直接将它们引向玩家;选手。每次Pacman移动时,“气味值”都会减少1。
现在,一种简单的逆转整个过程的方法是使用“幽灵金字塔”,其最高点位于地图的中心,然后幽灵便朝着这种气味的方向移动。
假设您已经具备了追逐pacman所需的逻辑,为什么不重用它呢?只要改变目标。似乎比使用完全相同的逻辑创建一个全新的例程要少得多。
这是一个寻路问题。有关流行的算法,请参见http://wiki.gamedev.net/index.php/A*。
每个正方形到中心的距离值如何?这样,对于每个给定的正方形,您都可以在所有可能的方向上获得相邻邻居正方形的值。您选择具有最低值的正方形,然后移至该正方形。
可以使用任何可用算法预先计算值。
这是我可以找到其实际工作方式的最佳信息。
http://gameai.com/wiki/index.php?title=Pac-Man#Respawn 当幽灵被杀死时,他们虚弱的眼睛又回到了起始位置。只需将鬼影的目标图块设置到该位置即可完成。导航使用相同的规则。
这实际上是有道理的。也许这不是世界上最高效的,但是不必担心其他状态或沿这些路线的任何事情的好方法,您只需更改目标即可。
旁注:我没有意识到,那些吃豆人程序员基本上是在很小的空间内以非常有限的内存制作了整个消息系统,这真是太了不起了。
我认为您的解决方案比这个简单,更适合解决该问题,是使新版本更“逼真”,鬼魂的眼睛可以穿过墙壁=)
这是ammoQ的洪水填充想法的模拟和伪代码。
queue q
enqueue q, ghost_origin
set visited
while q has squares
p <= dequeue q
for each square s adjacent to p
if ( s not in visited ) then
add s to visited
s.returndirection <= direction from s to p
enqueue q, s
end if
next
next
其想法是,这是广度优先的搜索,因此,每次遇到新的相邻平方s时,最佳路径是通过p。我确实相信是O(N)。
对于您如何实现游戏我不太了解,但是您可以执行以下操作:
一些伪代码:
x = getRelativeOppositeLatitudinalCoord()
y
origX = x
while(eyesNotInPen())
x = getRelativeOppositeLatitudinalCoordofGate()
y = getRelativeOppositeLongitudinalCoordofGate()
if (getRelativeOppositeLatitudinalCoordofGate() == 0 && move(y) == false/*assume zero is neither left or right of the the gate and false means wall is in the way */)
while (move(y) == false)
move(origX)
x = getRelativeOppositeLatitudinalCoordofGate()
else if (move(x) == false) {
move(y)
endWhile
我建议幽灵存储他从洞到吃豆人的路线。因此,只要幽灵死了,他就可以沿相反的方向跟随这条存储的路径。
我的方法需要占用大量内存(从吃豆子时代的角度来看),但是您只需要计算一次即可,并且适用于任何关卡设计(包括跳转)。
首次加载关卡时,将所有怪物巢穴节点标记为0(代表到巢穴的距离)。继续向外标记连接的节点1,连接到节点2的节点,依此类推,直到标记所有节点。(注意:如果巢穴有多个入口,这甚至可以工作)
我假设您已经具有代表每个节点及其邻居的连接的对象。伪代码可能看起来像这样:
public void fillMap(List<Node> nodes) { // call passing lairNodes
int i = 0;
while(nodes.count > 0) {
// Label with distance from lair
nodes.labelAll(i++);
// Find connected unlabelled nodes
nodes = nodes
.flatMap(n -> n.neighbours)
.filter(!n.isDistanceAssigned());
}
}
一旦所有节点都被标记,路由眼睛就变得微不足道了……只需选择具有最低距离标签的相邻节点即可(注意:如果多个节点的距离相等,则选择哪个节点都没有关系)。伪代码:
public Node moveEyes(final Node current) {
return current.neighbours.min((n1, n2) -> n1.distance - n2.distance);
}
对于我的PacMan游戏,我制定了一种“ shortest multiple path home
”算法,该算法适用于我所提供的迷宫(在我的规则范围内)。它也适用于它们的隧道。
加载关卡时,所有的path home data in every crossroad
物体都是空的(默认),并且一旦鬼魂开始探索迷宫,crossroad path home information
每次进入“新”十字路口或从另一条道路跌落到已知十字路口时,它们都会不断更新。
最初的吃豆人没有使用寻路或花哨的AI。它只是让游戏玩家相信它比实际深度更深,但实际上它是随机的。正如《游戏人工智能》 /伊恩·米林顿(Ian Millington),约翰·冯格(John Funge)所述。
不知道这是不是真的,但这对我来说很有意义。老实说,我没有看到人们在谈论这些行为。正如他们所说,红色/闪烁的ex一直没有跟随玩家。似乎没有人会故意跟随玩家。在我看来,他们追随您的机会是随机的。而且,很容易看到随机行为,特别是在很小的空间内被四个敌人和非常有限的转身选择时,被追赶的机会非常高。至少在最初的实施中,游戏非常简单。查看本书,它在第一章中。