2.6问题解答     希望本章不会有太多的难题。本章主要接触了两个主要问题:单元测试和Sprites。或许在Xbox 360上运行游戏您还有些问题,我已经在第一章的结尾处写了一些提示和技巧,您可以去看看。

     另外一个问题是理解为什么会抛出异常,并且要如何解决它。大多数人都不会有这样的问题,但对于少数不熟悉异常尤其是XNA异常的人来说却是个问题。您要紧盯着异常,查看完整的堆栈跟踪,看看是否有带有详细描述信息的内部异常。

     就像托管的DirectX,有时您会遇到底层DirectX Framework异常,而且有时候会很混乱,您可以到Internet和MSDN查找对应错误代码的帮助信息。在这些情况下,上下文信息(Context)要比具体的错误信息本身更重要,比如,在编译一个Shader失败之后您会得到很奇怪的错误代码,此时您应该检查Shader文件是否存在,是否能够被正确编译,您的硬件是否能够处理它,而不是努力去理解这些错误代码是什么意思。您可以使用Nvidia的FX Composer工具来检查Shader文件是否有效。

     如果您在使用单元测试的时候遇到问题,您可以看看下一章的“问题解答”部分,那里讲了很多关于单元测试的问题。而且要记住,此处您使用的单元测试和标准的程序没有什么区别,您要像对待最终的应用程序一样对它们进行调试并一步步地跟踪。

     最后是一些在XNA中使用Sprites的提示:
    • 如果您要在其他东西的上面渲染很多Sprites的话,您会遇到很多随机的排序次序问题,以及使用不同Texture的问题,而且背景Sprite有时会掩盖它前面的所有东西。就像您在这个XNA Pong游戏中看到的,这里使用了单独的SpriteBatch调用过程来渲染背景,这样它就被独立出来,不会干扰菜单和游戏中的Sprite的渲染。
    • 要一次性渲染所有的Sprite,尤其是当您可以使用混合模式对它们进行排序的时候。调用一次SpriteBatch一次性渲染所有的Sprite会使速度快很多,关于这一点您可以看看Pong游戏中的DrawSprites方法。如果您使用不同的混合模式,比如光效处理使用加成运算(Additive),而其他的Sprite使用Alpha混合,此时您要分两个过程来渲染,先渲染Alpha混合元素,然后在最上面添加加成运算的光特效,这样做您的游戏性能会提升200%-300%。
    • 要考虑分辨率问题以及如何处理不同的宽度和高度,您可以在Initialize方法中获取当前使用的分辨率,代码如下:
      width = graphics.GraphicsDevice.Viewport.Width;
      height 
      = graphics.GraphicsDevice.Viewport.Height;
    • 不能强制使用某个特定的分辨率,因为在Xbox 360上它可能不能正常工作,在Windows平台上它也只能是一个预设的分辨率。比如,您想在个人电脑上测试720p 16:9(1024×768)分辨率,您必须要有一台支持这个分辨率的显示器,可以是窗口模式(windowed mode)或者全屏模式(fullscreen mode)。在游戏主类(在本章中就是PongGame类)的构造器中添加下面的代码把分辨率预设为720p,并在Initialize方法中使用上面的方式来获取宽度和高度以检查它是否正确。
      graphics.PreferredBackBufferWidth = 1280;
      graphics.PreferredBackBufferHeight 
      = 720;
    • 在XNA中不支持字体处理,要显示文本,您可以像本章中使用已经包含文本的纹理图片,或者像第五章一样写自己的字体处理系统。对于这两种方案您都要使用Sprite来渲染文本或者每次渲染一个字母。 
    • 在XNA中Sprite并不是唯一的方式来展现2D数据,您可以写自己的Shaders,甚至可以做比Sprite类本身提供的更多的高级特效。作为一个例子,可以看看第五章中如何使用Shaders来渲染2D线条。

2.7本章摘要

     我希望您能喜欢本章中的内容,并掌握创建游戏的整个过程。Pong可能并不是最好玩的游戏,但它涵盖了对于任何一个游戏项目来说都可能包含的从头至尾的所有东西。对于大一些的游戏项目,只用一章的篇幅是讲不完的,但在这里您至少已经学习了一些概念、单元测试以及一些敏捷方法学的基本术语。下一章要学习辅助类的设计,然后再深入研究Game类和游戏组件,这之后,您就可以准备写一个包含很多非常酷的特效的3D引擎,它将在本书最后一部分使用XNA写一个大的、好玩的游戏时用到。同时,您还将学习一些其他的小的、但好玩的游戏项目。

     本章最重要的一点是敏捷开发给游戏编程带来的好处。即使您可以即时地对游戏做一些修改,有一个非常容易的、严谨的方式来解决问题,但先做一个游戏构思——哪怕只有一页纸那么多,仍然很重要。另外,单元测试也很有帮助,不过在下一章中您将看到单元测试还可以自动化地完成,并且对于本书中其他项目都要使用的一些辅助类来说单元测试也很有用。

     看一看在本章中您学到的内容:
    • 写下您的想法并有一个小的游戏构思非常重要
    • 让您的游戏构思保持在一页纸的篇幅内会很有帮助
    • 使用严谨的步骤来解决问题,并从问题最高层面的角度来使用单元测试,而不用去考虑具体的实现细节。通过这种方式您能够快速地提取出游戏构思的关键部分,并写一个单元测试,这时候就会很容易地发现您具体要实现什么样的方法了
    • 创建纹理素材,把它们加载到项目中,然后把它们作为Sprite渲染出来
    • 一次性渲染所有Sprite可以提升游戏性能
    • 使用一个合适的计算公式可以帮助您创建分辨率独立(resolution-independent)的游戏,这样游戏就可以在任何分辨率下很好地运行于Xbox 360上
    • 学会使用XACT添加音效,第9章有更加详细的讲解
    • 处理游戏输入以支持两个Gamepad控制器和多个玩家的键盘操作
    • 使用BoundingBox结构进行2D碰撞检测
    • 如果始终把z值设为0,您可以使用Vector3来代替Vector2
    • 使用单元测试来进行碰撞检测非常重要,并可以大大减少您的测试工作量。即使您当前正在处理与碰撞完全不同的部分,仍然可以切换到碰撞检测的单元测试中再次进行检测