【问题标题】:Representing a Gameworld that is Irregularly shaped表示形状不规则的游戏世界
【发布时间】:2010-06-05 00:32:40
【问题描述】:

我正在做一个游戏世界不规则形状的项目(想象一下湖的形状)。这个形状有一个网格,上面有坐标。游戏世界只在形状的内部。 (再一次,想想 Lake)

我怎样才能有效地代表游戏世界?我知道许多世界基本上是正方形的,并且在 2 或 3 维数组中运行良好。我觉得如果我使用一个正方形的数组,那么我基本上是在浪费空间,并且增加了我需要遍历数组的时间。但是,我也不确定锯齿状数组在这里如何工作。

游戏世界的示例形状

X
XX
 XX   X XX
 XXX XXX
  XXXXXXX
XXXXXXXX
 XXXXX XX
   XX   X
  X

编辑: 游戏世界很可能需要通过每个有效位置。所以我会想一种方法让它很容易做到。

【问题讨论】:

  • 我认为存储世界的最佳方式选择很大程度上取决于你需要对游戏世界进行什么样的操作。
  • 当你遍历每个位置时,你会做什么?您需要查看附近的牢房吗?

标签: c#


【解决方案1】:

稀疏表示存在计算开销和复杂性,因此除非边界区域比您的实际世界大得多,否则简单地接受“浪费”的空间可能是最有效的。您实际上是在权衡额外的内存使用以更快地访问世界内容。更重要的是,“浪费空间”的实现更易于理解和维护,在需要更复杂的实现之前,这始终是可取的。如果您没有充分的证据表明它是必需的,那么最好保持简单。

【讨论】:

  • 在我的示例中,66% 的地图将被浪费空间。不过,在这一点上,我还不足以知道我是否需要稀疏表示。
  • 在这种情况下,请参阅 kevingessner 的回答。您最初可以基于数组对使用地图的原语进行编码。如果需要,您可以稍后使用不同的实现来节省内存,但您可能不需要并且可能会使用简单的数组获得更好的性能。
  • 我对我创建的对象进行了一些简单的测试。看起来循环通过它的性能可以满足我的需要,特别是因为它不需要实时功能
【解决方案2】:

您可以使用quadtree 来最大程度地减少表示中浪费的空间量。四叉树适用于以不同粒度划分二维空间 - 在您的情况下,最精细的粒度是游戏方块。如果您有一个没有任何游戏方块的整个 20x20 区域,则四叉树表示将允许您仅使用一个节点来表示整个区域,而不是数组表示中的 400 个节点。

【讨论】:

  • 四叉树的问题在于,游戏世界可能变成 3 维的。我会完善一个适用于 2 维或 3 维的解决方案
  • @Aaron M:四叉树的 3D 版本称为八叉树:en.wikipedia.org/wiki/Octree
  • 和Aaron,如果你需要扩展到3维,你可以使用八叉树。它只是四叉树的扩展,允许上下邻居以及左右邻居。
  • @Aaron 那么在这种情况下,您可以使用八叉树,它是四叉树 en.wikipedia.org/wiki/Octree 的 3D 大哥。 Quadtree 用于 Google 地球和 Google 地图,因此它们在 3D 方面也没有那么差,直到您需要同一棵树中的 2 个事物处于相同的 X、Y 坐标(并且取决于它们都在那里的原因,它可能仍然不是一个问题)。每个位置都可以有一个 Z 坐标作为视觉表示的属性。
  • 正如@Rangoric 提到的,四叉树在很多情况下都可以使用——如果你真的在湖上模拟游戏,四叉树是完美的。如果你正在做一个曲折的洞穴,一个又一个又一个又一个的洞穴,那么八叉树将是更可取的。但是,如果您将树生成和遍历代码与其他游戏代码分开,“升级”它应该是微不足道的。
【解决方案3】:

使用您想出的任何结构——您以后随时可以更改它。如果您对使用数组感到满意,请使用它。不用担心你将要使用的数据结构,开始编码吧。

在编写代码时,从底层数组构建抽象,例如将其包装在语义模型中;然后,如果您(通过分析)意识到它浪费空间或执行所需的操作很慢,您可以将其换掉而不会造成问题。在您知道自己需要什么之前,不要尝试优化。

【讨论】:

    【解决方案4】:

    使用列表或地图等数据结构,并且只插入有效的游戏世界坐标。这样,您唯一要保存的是有效位置,并且您不会浪费内存来保存非游戏世界位置,因为您可以从数据结构中缺乏存在来推断这些位置。

    【讨论】:

      【解决方案5】:

      最简单的方法是只使用数组,并用一些特殊的标记标记非游戏空间的位置。锯齿状数组也可以,但我用的不多。

      【讨论】:

        【解决方案6】:

        您可以将世界呈现为土地(或水)斑块的(无向)图。然后每个补丁都有一个规则的形式,世界就是这些补丁的组合。每个补丁都是图中的一个节点,并且与它的所有邻居都有图边。

        这可能也是任何一般世界最自然的表示(但它可能不是最有效的表示)。从效率的角度来看,对于高度不规则的地图,它可能会胜过数组或列表,但对于能够很好地适应矩形(或其他规则形状)且偏差很少的地图,它可能会胜过。

        高度不规则地图的示例:

        x
         x   x
          x x    x
           x     x
            x xxx
             x
            x
           x
          x
        

        几乎没有办法有效地将它(无论是在空间比还是在访问时间上)装入一个规则的形状。另一方面,通过应用基本几何变换(它是一个缺少小位的平行四边形),以下内容非常适合常规形状:

        xxxxxx  x
         xxxxxxxxx
          xxxxxxxxx
           xx   xxxx
        

        【讨论】:

          【解决方案7】:

          另一个可以让您在 O(1) 时间内访问游戏世界位置并且不会浪费太多空间的选项是哈希表,其中键是坐标。

          【讨论】:

            【解决方案8】:

            另一种方法是存储一个边列表 - 沿每条直边的线向量。这种方式很容易检查是否包含,四叉树甚至每个顶点上的简单位置哈希都可以加快信息查找速度。我们用每条边的高度分量来模拟棒球场的墙壁,效果很好。

            【讨论】:

              【解决方案9】:

              这里没有人解决一个大问题:将其存储在磁盘上和存储在内存中之间的巨大差异。

              假设您正在谈论一个游戏世界,正如您所说,这意味着它将非常大。您不会一次将整个事物存储在内存中,而是将其直接存储在内存中,并在玩家四处走动时对其进行更新。

              这个附近区域应该尽可能简单、方便和快速地进入。它绝对应该是一个数组(或一组随着玩家移动而被换出的数组)。它会经常被游戏引擎的许多子系统引用:图形和物理将处理加载模型、绘制模型、将玩家保持在地形之上、碰撞等;声音需要知道玩家当前站立的地面类型,才能播放适当的脚步声;等等。与其在所有子系统之间广播和复制这些数据,不如将其保存在全局数组中,它们可以随意访问,并且以 100% 的速度和效率。这确实可以简化事情(但要注意全局变量的后果!)。

              但是,在磁盘上您肯定要压缩它。一些给出的答案提供了很好的建议;您可以序列化数据结构,例如哈希表,或仅填充位置的列表。你当然也可以存储一个八叉树。无论如何,您都不想在磁盘上存储空白位置;根据您的统计,这意味着 66% 的空间被浪费了。当然,有时会忘记优化并让它只是工作,但您不想将 66% 的空文件分发给最终用户。还要记住,磁盘不是完美的随机存取机器(SSD 除外);机械硬盘至少应该还有几年的时间,而且它们按顺序运行最好。看看您是否可以组织您的数据结构,以便读取操作是顺序的,因为您在玩家移动时流式传输更多附近的地形,您可能会发现它是一个明显的差异。不过,不要相信我的话,我还没有真正测试过这种东西,它是有道理的,对吧?

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多