【翻译】Managed DirectX(第六章),【翻译】Managed DirectX(第六章)
第六章 使用Managed DirectX编写游戏翻译:claymanclayman_joe@yahoo.com.cn仅供个人学习之用,勿用于任何商业用途,转载请注明作者^_^选择游戏 虽然很多关于3D游戏编程的高级主题还没有讨论,但我们已经有足够的背景知识来写一个简单游戏了。这一章,我们将使用至今学过的知识,再加上一点点新的东西来创建游戏。 真正开始写游戏之前,最好先拟一份计划。我们需要确定写什么类型的游戏,它将有哪些最基本的特性,等等。考虑到目前的技术限制,自然不能写太复杂的游戏。这将是一个简单的游戏。在MS-DOS环境下,曾经有一个叫做Donkey的游戏,玩家控制着车不能撞到路上的donkey。听起来足够简单吧,我们将创建一个三维版本,并且用普通的障碍物来代替donkey。这个游戏叫做躲避者(Dodger)。 开始编码之前,需要花一点时间来策划和设计游戏。我们需要怎样的游戏,玩的时候来控制。Well,显然,要有一个Car类来控制交通工具。接下来,使用另一个类来控制障碍物将会很不错。除此之外,主要的游戏引擎类必须完成所有的渲染操作并把所有对象组织起来。 如果尝试商业游戏,那么大部分时间将会花在游戏创意上。游戏创意将会写成详细的文档,包括了游戏主题和特性的各种细节。本书的着重于讨论游戏的实际开发工作,而不是游戏发行和创意,所以我们将略过这一步。 通常开之发写还必须写完整的技术文档(technical specification)(简称为spec)。它包以适当的细节列出了所以类,以及需要实现的各种方法、属性。通常还包括表示对象之间关系的UML图。这份文档的目的是让你在编码前坐下来认真考虑程序的设计。由于本书聚焦于代码的编写,我们同样略过这一步。需要说明的是,强烈建议你在写任何代码前花点时间撰写技术文档。 编写游戏 现在可以打开VS创建项目了。创建一个名为Dodger的windows应用程序。使用DodgerGame代替代码中所有出现Form1的地方。添加对DirectX程序集的引用。创建私有的device成员,如下修改构造函数: public DodgerGame() { this.Size = new Size(800,600); this.Text = Dodger Game; this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque,true);}这将会把窗口设置为800×600(注:实际代码中我将会创建一个全屏的游戏,另外如果现在运行程序,会发现我们创建了一个透明的窗口),设置窗口标题和样式(style),这样渲染代码才会正常工作。接下来修改程序的入口点:static void Main() {详见源码}这个应该很熟悉了吧,基本上就是之前每一章用来启动程序的代码。创建窗体、初始化图形引擎,运行窗体。在initializeGraphics内做如下改动:private void InitializeGraphics() {详见源码};创建了presentation parameters结构之后,确保有它有深度缓冲。这里有什么新内容呢?首先,保存了默认的适配器的序数号,接下来保存了creation flags,并把它的默认值设为software vertex processing。但是,现代图形卡都在硬件层实现了vertex processing。何必把宝贵的CPU资源用在显卡可以完成的任务上呢?答案是不需要这样做,但你不知道是否真的支持这种特性,于是有了接下来的代码。在真正创建device之前,需要先保存显卡的功能(capabilities,简称Caps),这样可以用来决定使用那一种flags创建device。因为你只是创建一个硬件设备,所以只储存这几个Caps就可以了。关于检查适配器所有Caps的内容回忆一下第二章吧。还记得使用顶点缓冲时需要在重置设备之后重建缓冲吗?我们为device订阅了created事件。当device重置之后,设定device的所有默认状态,添加如下代码:private void OnDeviceReset(object sender,EventArgs e) {详见源码};(注意:类似于这里的代码,你可能会使用一个层(layer)来检查支持的灯光。这种情况下,先检查是否支持一盏灯,如果可以,则创建它。然后再用类似的方法检测是否支持第二盏灯。这样即使最差的情况你也能获得一盏灯光)这里和前面学过的代码也很类似,通过projection fransform和view transform来设置摄像机。对于这个游戏来说,我们的摄像机不需要移动,所以只需要在重置设备之后设置一次就可以了(与设备相关的状态都会在重值之后丢失)。环境光不是最好的选择,我们已经知道他不能产生真实的光影效果,所以方向光将是不错的选择。但并不能确定设备是否支持这种光源。创建了设备之后,就不需要再使用先前的Caps结构了,device会为你保留着这些信息。如果device支持方向光,而且支持一盏以上的灯光,你应该使用它;否则,使用默认的环境光。它虽然不真实,但总比黑色的场景要好吧。最后,重载OnPaint方法,:protected override void OnPaint(PaintEventArgs e){详见源码};这里没有什么新内容,当然你可以把背景改为任何你喜欢的颜色。现在已经为加载模型做好了准备。创建变量来储存.X文件中的赛道模型吧。 private Mesh roadMesh = null; private Material[] roadMaterials = null; private Texture[] roadTextures = null;接下来修改一下前一章里的load mesh方法。最大的改变是将把它改为