4.2 Game


     前几章您已经使用过了Game类,但这些章主要讲的是从Program类和单元测试中调用Run方法来启动游戏,以及如何使用InitializeUpdateDraw等方法,并没有讨论基本的设计。当然,如果做的只是一些简单的游戏,掌握这些知识就够了。但随着游戏的规模逐渐变大以及需要更多的游戏特性,您或许就需要好好考虑游戏类的设计了。

     Game类中提供了保存图形设备的GraphicsDeviceManager实例以及保存内容管理器的相应变量。然后,在Program类中创建您的游戏类实例,并调用其Run方法就可以运行游戏了。和以往使用托管DirectXOpenGL不同的是,现在您不必再去管理您自己的游戏窗口、创建游戏循环、处理Windows消息等等,这些工作XNA都已经帮您做好了。正因为如此,您可以将您的游戏放到没有窗口类以及Windows事件的Xbox 360平台上运行!

     您可以使用游戏类的Window属性来对游戏窗口进行相关操作,比如设置窗口标题、是否允许用户更改窗口大小、调用底层的Windows句柄进行互操作等等。所有这些方法在Xbox 360平台上是不起作用的,在Xbox 360上没有窗口,没有窗口标题,当然也无法改变窗口大小。正如在上一个游戏中,您使用了Window.Title属性来设置简单的文本以向用户显示当前级别以及分数。这样做是因为XNA不支持字体,要想在屏幕上显示文本,您得自己创建位图字体并逐一渲染所有的字母。在接下来的几个游戏以及本章的俄罗斯方块游戏中,您都将用到该特性,稍后将介绍为此而创建的TextureFont类。

     另外值得一提的是,您可以在游戏类的构造函数中使用下面的方法设置自己偏爱的分辨率,这个例子使用了1024×768的全屏模式:

graphics.PreferredBackBufferWidth = 1024;
graphics.PreferredBackBufferHeight 
= 768;
graphics.IsFullScreen 
= true;

     当然,并不能保证游戏就会正确地在所设置的分辨率下运行。比如,如果在一个最高只支持1024×768分辨率的系统上设置了1600×1200的分辨率,那么游戏将使用可用的最大分辨率。

     您已经知道,游戏在渲染每一帧的时候都要调用UpdateDraw方法,but how do you incorporate new game components without overloading the game class itself ?下面就来看一下Tetris游戏的类以及组件设计关系图(如图4-1所示)。

图4-1

4-1
 

     可以看到,这里有三个游戏类,而不是像之前的游戏那样只有一个,这样做是为了使主游戏类更加简短。BaseGame类保存图形设备管理器和内容管理器,以及游戏当前使用的分辨率的宽度和高度值。UpdateDraw方法处理新的InputSound以及TextureFont类,这样在主游戏类中就不用再更新它们。TetrisGame类用来从内容管道加载所有的图像,初始化所有的sprites和游戏组件,这些将在稍后介绍。

     最后,TestGame类继承自TetrisGame类,以便访问所有的texturessprites以及游戏组件,它只用于调试模式下来进行单元测试。TestGame类的功能和前几章的很类似,不过在这里它被从游戏主类中分离出来,以一种更好的方式进行组织。TetrisGame类使用了几个单元测试,以确保游戏的每个部分都能按照预期正常运行。