基于网格的布局游戏和删除项目

时间:2011-02-24 23:14:07

标签: algorithm c#-4.0 xna

假设我有一个入侵者的集合(简单网格):

When everything is still intact

在此图像中,只有C型入侵者可以射击。

射击被射击,入侵者被摧毁:

Invader Destroyed

现在,第二行第三列中的入侵者类型B也可以触发。请注意,屏幕上只能同时有三个随机入侵者镜头。所以集{C,C,B,C,C,C}中只有三个入侵者可以射击。

我将如何实施此功能?我在想两个解决方案:

  1. 使用数组[] [](或[,])数组。当入侵者被射击时,入侵者所在的地方被设置为空。然后,当入侵者开火的时候,第一行就会有一个循环。遇到null会使它检查null上方的空格。它是空的吗?然后对 上方的空间执行相同的操作。最上面一行的空格是否为空?转到第一行的下一列。

  2. 每个入侵者类型都有一个位置(我使用Point)。为每个位置分配行号(使用的集合将是某种字典)。因此,在查看图像时,所有C都得到1,所有B得到2,所有A得到3。 A picture 1024 words?在这张图片中,位置(2,2)处的C被破坏。然后它应该从中减去1点的Y值,它将是(2,1)。如果集合中存在类似的位置,则将该位置(2,1)的入侵者分配到被破坏的入侵者的位置(2,2)。。像这样,我不必有一个包含一堆空值的锯齿状数组。

  3. 我对它应该是什么样子的想法 - >当游戏开始时,第一组是{C C C C C},然后它将是{C C B C C C}。从这一组中,将随机选择三个进行射击。

    那么,有什么想法吗?

4 个答案:

答案 0 :(得分:1)

我不同意Mirkules。我建议你不要只为可以射击的入侵者保留一个单独的数据结构。一般来说,坚持DRY pattern以防止以后出现逻辑问题总是一个好主意。对于一个简单的应用程序,您可以将整个程序放在头脑中,这可能不是什么大问题。但是当你开始处理更大的项目时,记住你需要在修改任何一个相关结构时更新多个数据结构变得更加困难。

过早优化是万恶之源。您可能甚至不需要担心在如此微不足道的水平上进行优化。根据我的经验,当您花费大量时间处理这些类型的问题时,您最终会获得良好的代码,但您没有太多可以展示的代码。相反,我更愿意花时间让我的应用程序执行我想要的操作,然后在以后重构它。看到我的应用程序正常工作,让我有动力继续编写更多代码。

祝你好运。 Xna在编写游戏时非常有趣!

答案 1 :(得分:0)

我会保留所有入侵者的2D数组。此外,如果你维护一个单独的数据结构,只需要指向可以触发的入侵者的指针,而不是每次你必须触发时必须遍历整个数组(导致程序在开始以来会有更多的入侵者)。因此,在您的第一个图表中,您的数据结构将包含所有“C”,并在第二个图表中包含{C,C,B,C,C,C}。当需要点火时,你只需要引用这个数据结构,得到他们的指针,然后只在任何一个入侵者身上调用“fire()”。

你没有完全解释如何选择可以触发的三个入侵者,所以我猜它是随机选择的 - 在这种情况下,你所要做的就是选择0(含)和n之间的随机数-1(其中n是数据结构中的入侵者数量,在本例中为6)。

最后,当需要销毁一个入侵者时,如果你有二维阵列而且你知道了这个位置,那么将被杀死的入侵者从“射击小队”数据结构中弹出并分配上面的一个很容易他到射击队(即invaderArray [KilledInvader.row-1] [KillerInvader.column])

希望这是有道理的。

答案 2 :(得分:0)

入侵者可以更改列吗?它可以传递一个位于其前面的入侵者吗?

假设两个问题的答案都是否定的,我会为每一列维护一个队列/列表。然后,可以触发的入侵者集是每个队列中的第一个元素。当一个入侵者被摧毁时,你只需将它从队列中弹出即可。再说一次,假设只有前排可以被破坏。

每个入侵者都必须保持一个更新和绘图的位置。

答案 3 :(得分:0)

在游戏开发中,特别是在Xbox 360上的C#和尤其是这样的托管语言中,一般来说,首要任务应该是避免在游戏运行时分配内存。节省内存和减少操作次数是次要问题。

null(32位,XNA运行)只有四个字节!

包含指向入侵者指针的2D数组([,])似乎完全合适。特别是因为它允许您通过其在数据结构中的位置来确定每个入侵者隐式的位置。 (你甚至需要创建单独的入侵者对象并指向它们吗?只需使用一个数字来表示它们是什么类型的入侵者。)

循环使用该数据结构(以您建议的方式)将非常快,它可能是一个“免费”操作。因为处理器本身可以比你将它带入缓存更快地处理数据。

你甚至不是每一帧都这样做 - 只有当你的入侵者开火时!我愿意打赌,当入侵者被摧毁时,计算并存储数据会 更慢 ,然后在入侵者开火时加载它。

(基本上你提出的是缓存/预先计算数据。一种有用的性能优化技术 - 但仅在实际需要时

你应该更加担心每一帧发生的成本,而不是仅偶尔由定时器和用户输入触发的成本。

不要使用锯齿状数组([][])。这基本上是一个数组数组。它使用更多的内存并涉及一个额外的间接层,这反过来也可能会降低数据的局部性(这意味着你的数据可能不会在一次命中中结束在缓存中 - 这就是“慢速位”) 。它还增加了GC必须考虑的对象数量。出于同样的原因,请不要使用Dictionary


在游戏开发中,当你工作时,至少要记住这种性能的东西是有帮助的(在其他地方,这将是完全过早的优化)。

但是,对于像 Space Invaders 这样简单的东西,你几乎可以做任何你喜欢的事情!最简单的事情也是如此。