×

VB.Net游戏编程入门经典(5)

Kalet Kalet 发表于2009-03-20 12:00:13 浏览339 评论0

抢沙发发表评论

1.5  优化计算量


随着游戏中对象个数的增长,执行全部必需的计算工作将变得异常困难,因此有必要寻找一种加速计算的方法。对计算本身而言,可以进行简化的程度已经非常受限,因此就需要把计算量尽量保持在较低层次。


首先需要考虑的方法是仅仅对当前屏幕上的那些对象进行计算。如果确实需要对屏幕外的对象进行计算的话,那就对它们尽量少做一些计算(相对于当前屏幕上的对象而言)。

VB.Net游戏编程入门经典(5)

接下来较为理性的做法是,努力确定哪些对象是较为邻近的,然后只对这些对象进行冲突计算,使用“分区方法”(zoning method)可以做到这一点。一种简单的方法是,把一个较大的区域分解为几个连续的较小的块,并且仅对那些重要的部分进行检测,检测时要尽量精简冲突检测算法和减小检测区域。在类似Doom或Quake这样的复杂游戏中,这种方法是非常普遍使用的。但是,如果绝大多数对象都是固定在屏幕上的,并且尺寸一致,就可以使用“平铺游戏区域”方法(这种方法有时称为“分区方法”)来计算冲突。这种方法在二维游戏中很常见(关于这一点,在后面的章节中会更多地涉及到)。这里,如果有很多对象但只需要对其中一个进行检测的话(比如一颗可以射向多个敌人或障碍物的子弹),那么就可以把屏幕简单地分解成几个区域并只对特殊区域进行特殊的冲突检测即可。


在接下来的章节中,我们将讨论上述的每一种方法。


1.5.1  平铺游戏区域


“平铺游戏区域”方法是受限的“分区方法”,这种方法下的分区中每块只有一个对象,使用一个二维数组,并且数组的每个位置指向屏幕上的每一个小块。当移动对象时,我们要做的就是检查给定位置上的数组元素以确定该位置是否会发生冲突。本章对该方法做了一个小小的变更,我们使用了一个“位数组(bit array)”并且每一位对应于屏幕的每一个小块。这种方法是可行的,因为我们只需要存储少量信息即可—— 该块要么为空、要么存在对象。如果需要存储对象的额外信息(例如,对象类型的标识),则必须创建一个整型数组来存储一系列数字,然后创建一个“对照表(mapping table)”,表中的每个数字代表一个特定的对象类型(如同下一章中的相应内容所示)。图1-16显示了一个“平铺区域”类型的游戏,游戏的每个屏幕对象存储在一个数组中。



图1-16  在平铺游戏区域中,系统有一个数组以便对应每个屏幕对象


1.5.2  位分区


如果一个游戏具有很多对象,但对象之间很少发生冲突,则通过把屏幕分割为多个区域并只对同一区域内的对象进行冲突检测可以将计算量减少到最小。分割区通常依据希望进行检测的冲突区域个数而建立,因此它们与屏幕的分辨率无关。通常情况下,我们把整个游戏区域分割成几个小的区域,创建一个数组来存储每个小区域的y轴和x轴信息。因此,如果欲把屏幕分割为64个小区域(8×8),则需要一个8元素的数组来存储每个块的y轴信息,另一个8元素的数组来存储每个小区域的x轴信息。图1-17显示了这种分割方法的一个示例。



图1-17  把屏幕分割为256个区


如果只是想知道某个特定的区域是否包含对象(不考虑是哪个对象)的话,则可以使用字节(而不是数组)来存储分区信息,字节的每一位代表屏幕上的一个分区,这就是位分区方法。可以根据程序使用的变量所包含的位的个数把屏幕分割成多个块,如一个字节可以把屏幕分割成64(8×8)块、一个16位整数可以把屏分割成256(16×16)块、一个32位整数可以把屏幕分割成1024(32×32)块等。


使用位分区方法,需要在游戏的每个循环过程中重新对变量赋值,而对于每个对象而言,程序可以处理它的任何移动动作。然后计算每个对象所处的区域(取对象的当前位置乘以每个轴(x轴、y轴)上的区域个数,然后除以屏幕的宽度或高度),从而对代表x轴、y轴变量计算结果的位进行赋值。如果对象所处的位置和对象的尺寸(在x轴上用宽度表示,在y轴上用高度表示)之和正好位于另一个区域的范围之内,则必须对变量所包含的第二个位进行赋值。

VB.Net游戏编程入门经典(5)

如果检查变量值时发现两个变量(x轴、y轴)上相应位的值均已被设置,则该区域必定包含一个对象,那么

就需要检查所有的对象以确定是哪个对象位于该区。如果屏幕上含有15个对象并且仅存在一个冲突的话,则使用这种方法只需要对给定数目的对象执行一遍检测即可(最差情况是对14个对象进行检测),而不需要对14个对象进行15次检测。当然,这种方法也有一些缺点:


●       不能确定是哪个对象对该位设置了值,因此必须对所有对象进行检测以确定冲突所在。


●       当通过某位时,该位在x区被一个对象设置,同时在y区又被其他对象设置,这种情况下将会产生一些“ghost对象”,如图1-18所示。


当希望检测一组对象相对于其他多个对象的冲突时(例如屏幕上的多个子弹相对于多个敌人),该方法最为有效;如果需要检测所有对象相对于其他任何一个对象的冲突,那么最好使用“位数组分区”方法,这方面内容我们将在以下章节叙述。



图1-18  使用位分区情况下,如果屏幕存在尺寸大的对象(如图中的砖块),将产生很多“ghost对象”


1.5.3  位数组分区


如果屏幕上有有限个对象的话,则可以使用两个数组而非变量来定义分区。每个对象对应于数组元素的某个特定位,因此可以使用字节数组来管理8个对象、使用16位数组来管理16个对象,以此类推,同时还需要创建一个对照表把每个位和每个特定对象联系起来。每个数组的大小定义了某一维上一个分区的像素个数。例如,在640×480的分辨率下,创建两个数组,每个数组包含10个元素,将会得到宽为64像素、高为48像素的分区。


利用前面介绍的方法中的类似思想来定义一个分区(或多个分区),任何一个对象都有可能存在于该分区(或多个分区),然后查看x数组元素和y数组元素是否均不为零。如果它们均不为零并且两个数组中的位组相同,则必定有另一个对象(不是ghost对象)位于自身附近,然后仅仅对相应于该位组的对象执行冲突检测即可。如图1-19所示。



  图1-19  使用分区数组,可以对每个分区存在哪些对象一目了然。VB.Net游戏编程入门经典(5)
 图中显示了对应于每个对象的数组元素的位组



群贤毕至

访客