4.3游戏组件

      TetrisGame类使用继承自基类的Components属性(在Microsoft.Xna.Framework.Game类中)来保存所有的游戏组件,您可以向这个列表中添加任何继承自GameComponent类的自定义组件类,当游戏启动或者更新的时候这个自定义类会被自动调用。但是在绘制游戏的时候它是不被调用的,因为GameComponent类没有Draw方法。不过,您还是可以实现自己的draw方法,或者直接使用包含Draw方法的DrawableGameComponent类。XNA does not have a direct Draw support for the game components; you have to call it yourself to make sure all components are called in the correct order。因为这个原因以及其他几个原因(forcing you to use this model with almost no advantages, makes unit tests harder, your own game classes might be more effective or specific, and so on),在本书的稍后几章中您不会使用太多的游戏组件。It is generally a nice idea, but you can live without it because you have to create game components yourself anyway and you have to call Draw for them yourself too. Just for the Update method, it does not make much sense to use them

      正如我在第一章中所说,要让大家分享自己的游戏组件,以便其他人也可以使用它们。比如,一个帧计数器组件,甚至是一个fullblown 3D landscape rendering engine都可以作为一个游戏组件来实现。but just because someone does not use a game component does not mean it is harder to copy over。例如,如果您有一个复杂的游戏组件,像场景渲染模块,那它很可能包含一些其他类,而且使用自己的渲染引擎,which might not work out of the box in your engine if you just copy one file over。不管怎样,移植外部的代码经常需要进行很多的重构操作,直到这些代码可以在您自己的游戏引擎中工作。在XNA Framework beta 1中有一个图形设计器,在XNA Game Studio Express中利用它您可以方便地向游戏类甚至其他的游戏组件中增删组件,这样您一行代码都不用写就可以增加游戏特性。因为这个功能非常复杂,有很多bug,还不支持Xbox 360,在XNA Framework beta 2中就被舍弃了。

      It is not a sure thing that game components will not be used, and maybe it does not matter to most programmers that the designer is missing and you have to call the Draw methods yourself. Then a lot of game components might be available and it would be useful to know all the basics about them。本章的Tetris游戏可以包含下面的几个组件:
  • 网格:包含颜色方块以及下落的方块
  • 记分板:包含当前级别,得分,最高分,以及消除的方块行数
  • 下一个要显示的方块
  • 其他:帧计数器,输入处理等等
      在这里我只把网格和下一个要显示的方块实现为组件,all the code is just way too simple for implementing several new classes just for them。如果您要重复使用记分板功能,您可以将其做成一个组件,但我还想不到我以后要做的什么游
戏会用到这样的记分板。


      下面我们来进一步地了解一下Game类以及要增加的组件(如图4-2所示):
图4-2

4-2
 

      灰色箭头所指的方法会被自动调用,因为TetrisGridNextBlock都被添加到了Game类的Components属性中。在TetrisGame.Draw中,调用了TetrisGrid类的Draw方法,而它又调用了NextBlock.Draw方法。TetrisGame只使用了TetrisGrid类,然后TetrisGrid类中又使用了NextBlock类。

      可以看出,在为这三个游戏类应用游戏组件的时候,您不得不考虑到其中的调用顺序,这样您就不必把所有的实现都装进一个大类中,从而让游戏更有组织。虽然对于有经验的程序员使用这样的设计方式很不错,但对于初学者来说提前在XNA中应用这种组件思想也是一个非常好的选择。