如何在2D平铺游戏中快速计算视野?


24

我有一个图块矩阵,在某些图块上有对象。我想计算哪些图块对播放器可见,而哪些则不可见,所以我需要非常有效地做到这一点(因此即使我有一个大矩阵(100x100)和很多对象,它也可以足够快地进行计算)。

我尝试使用Bresenham的line算法来做到这一点,但是速度很慢。另外,它给了我一些错误:

----XXX-        ----X**-     ----XXX-
-@------        -@------     -@------
----XXX-        ----X**-     ----XXX-
(raw version)   (Besenham)   (correct, since tunnel walls are 
                              still visible at distance)

(@ is the player, X is obstacle, * is invisible, - is visible)

我敢肯定这是可以做到的-毕竟,我们有NetHack,Zangband,他们都以某种方式解决了这个问题:)

您可以为此推荐什么算法?


对于我的需求,我将定义可见这样的:瓷砖是可见的,当在瓷砖的至少一部分(例如角落)可以连接到播放器瓷砖的中心用一条直线,其不相交任何的障碍。


1
哎呀,我的错,NetHack没弄错视线:)
Rogach'1

可以在fadden.com/tech/fast-los.html上找到一些较旧的想法,尽管这种想法可以追溯到CPU相当慢并且最好避免使用浮点计算的时代。
流行的

Answers:


10

您对visible的定义如下:

当瓷砖的至少一部分(例如角落)可以以不与任何障碍物相交的直线连接到玩家瓷砖的中心时,瓷砖是可见的

您可以通过追踪播放器磁贴中的光线并将其与场景相交来真正实现此概念。一旦射线碰到障碍物(或超过一定的距离阈值),您就可以避免每次迭代,因为您只对玩家可以直接看到的图块感兴趣。我将为您分解该过程:

  1. 指定您要赋予算法的精度级别。这就是您要追踪的光线数量。
  2. 将整个360度圆除以所选的精度,以知道在每条射线之间旋转多少度。
  3. 从0度开始并增加在步骤2中确定的数量,创建一条射线,其原点位于播放器磁贴的中心,方向由当前角度确定。
  4. 对于每条射线,从玩家方块开始,沿着射线的方向行走,直到碰到障碍物方块。将该图块添加到可见图块列表中,然后继续进行下一个射线。您可能还想增加一个最大距离来“放弃”,以防发现碰撞。

这是一张显示3条示例射线的图片。深色瓷砖是每条射线的“结果”,即发生碰撞的位置。不过,您需要在整个圈子中重复一次:

在此处输入图片说明

调整最大距离和光线数量以提高性能。太少了,您会错过瓷砖,太多了,您的性能会受到影响。同样,光线必须传播得最远,“误差”将变得越大,您将需要越精确。

编辑

查看以下有关光线投射的教程,尤其是步骤3和步骤4,以帮助您实现算法的交点:

http://www.permadi.com/tutorial/raycast/rayc7.html


我应该沿着每条射线“行走”一个固定的距离(例如0.3点),还是需要对每条射线运行像Besenham算法一样的东西?
Rogach 2012年

如果您仅前进固定距离,则会遇到瓷砖遗失的问题。查看有关raycasting的本教程。我也会将其修改为我的答案。您基本上可以分别检查水平和垂直碰撞。
David Gouveia,2012年

1
该算法虽然很好,但是需要大量的光线才能正确处理1瓦宽的长隧道。
HolyBlackCat

@HolyBlackCat-仅当您在所有方向上以均匀角度发出光线时,情况才会如此。但是,您可以避免发送大部分光线,而只将它们扔到场景中的直线末端。这是一个很好的解释:redblobgames.com/articles/visibility
Rogach '16

8

我宁愿投下阴影射线而不是视线射线。

假设这是您的查看区域(潜在的可见区域)

######################
#####.............####
###................###
##..................##
#....................#
#....................#
#..........@.........#
#....................#
#....................#
##..................##
###................###
#####.............####
######################

#块不可见,而#块不可见。可见

让我们设置一些障碍X:

######################
#####.............####
###................###
##.....X.....XXX....##
#......X.......X.....#
#...X.XX.............#
#...X......@.........#
#...X..........X.....#
#...XXXXXX...........#
##..................##
###....X...........###
#####.............####
######################

您在视图区域中有一个X列表,然后将每个障碍物后面的每个图块都标记为隐藏:将障碍物标记为隐藏时,将其从列表中删除。

######################
#####.............####
###................###
##.....X.....XXX....##
#......X.......X.....#
#...X.XX.............#
#...X......@.........#
#...X..........X.....#
#...XXXXX*...........#
##......##..........##
###....*#..........###
#####.###.........####
######################

在上面的示例中,您可以看到底墙最右边投射的阴影以及该阴影如何从您必须检查的障碍物列表中删除隐藏的障碍物(X必须检查; *已检查)。

如果您使用一些二进制分区对列表进行排序,那么首先检查Cosest X,则可能会稍微加快检查速度。

您可以使用一种“ Naval Battles”算法来一次检查X块(基本上是在寻找可以使卷影锥变宽的方向的正切X)。

[编辑]

需要两条光线才能正确投射阴影,并且由于图块是矩形的,因此可以使用可用的对称性进行很多假设。

可以使用障碍砖周围的简单空间分区来计算射线坐标:

空间分区示例

每个矩形区域构成了一个选择,即应选择将瓷砖的哪个角作为阴影锥边缘。

可以进一步推动这种推理,以连接多个相邻的图块,并让它们按如下方式投射单个更宽的圆锥体。

第一步是确保没有障碍物朝向观察者方向,在这种情况下,应考虑使用最近的障碍物:

选择最近的障碍物

如果黄色图块是障碍,则该图块将变为新的红色图块。

现在让我们考虑圆锥的上边缘:

候选图块

蓝色瓷砖都是使阴影锥变宽的所有可能的候选方法:如果其中至少一个是障碍物,可以使用围绕瓷砖的空间分配来移动射线,如前所示。

仅当观察者在随后的橙色线上方时,绿色方块才是候选者:

延长检查

相同的代表另一条射线以及观察者围绕红色障碍物的其他位置。

基本思想是为每个圆锥形铸件覆盖尽可能多的区域,并尽可能快地缩短要检查的障碍物清单。


有趣的方法,由于其减性性质,可能是一个更好的主意。阅读完这篇文章后,我可能也会以这种方式实现它。
David Gouveia 2012年

我可以预见在这样的情况下的问题这样。黄色的球员,蓝色和紫色的障碍物。播放器应该能够看到紫色的障碍物(如绿色射线所示)。但是穿过蓝色障碍物的红色阴影射线拒绝了紫色瓷砖。但是我想视线版本可能会比这有更大的问题。
David Gouveia 2012年

这个问题来自“隐藏”的定义:当光线与瓷砖相交时,它将(几乎)永远不会完全覆盖它。渲染线段时使用别名解决了相同的问题。我个人认为,当瓷砖的主要部分被覆盖时,瓷砖是隐藏的,可以定义隐藏的瓷砖是否被完全覆盖,您可能会发现它是否暴露出可能使阴影锥变宽的一面...无论如何,您可能仅列出完全覆盖的块。
FxIII 2012年

@DavidGouveia-还有什么更大的问题?
Rogach'1

@DavidGouveia-我已经尝试过使用阴影“锥体”方法,但是效率很低。至于可见光的精确度-如果您直接站在墙壁附近,大约5500束光线就足以在每个方向上看到20块墙砖,而可见光只有一个砖块就远得多。至于在更远的距离上缺少一些瓷砖-那么,不是每个人都拥有完美的视力,是吗?
罗加奇

8

您尝试解决的问题有时称为“视野”,简称FOV。正如您以roguelikes为例,您应该看一下RogueBasin Wiki对这个主题的看法(甚至有实现的链接):http ://www.roguebasin.com/index.php?title=Field_of_Vision

有很多算法各有优缺点-RogueBasin也提供了非常方便的比较:http ://www.roguebasin.com/index.php?title = Comparative_study_of_field_of_view_algorithms_for_2D_grid_based_worlds


真的很好,完整的摘要!
Rogach 2012年

该网站是一个很棒的资源,感谢您共享该链接。它还包含A *寻路原理的令人难以理解的描述:-)
uliwitness 2014年

答案链接现在转到网站主页-roguebasin.com/index.php?title=Category:FOV似乎很合理。
2016年


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.