暴米花 发表于 2006-12-21 12:32:00

[Clayman的专栏]中文XNA教程(一)——A Beginners Guide to XNA

我们会设置一个,专门发布Clayman写的XNA文章。<p>作者:Mike Fleishauer &amp; clayman<br/>本文版权归原作者所有,仅供个人学习使用,请勿转载,勿用于任何商业用途。<br/>由于本人水平有限,难免出错,不清楚的地方请大家以原著为准。欢迎大家和我多多交流。<br/>Blog:http://blog.csdn.net/soilwork<br/>clayman_joe@yahoo.com.cn&nbsp; <br/>special thanks to Mike Fleishauer ^_^</p><p>&nbsp;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xna beta发布已经快半个多月,终于有时间开始学习。以后的一段时间,打算把Mike Fleishauer的文章结合自己的理解,陆续出一些教程。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 虽然我们将会由浅入深,逐步学习XNA,但在开始之前,你最好具备以下知识:熟悉C#, 有基本的程序设计经验,一定的图形学知识,包括3D、2D坐标变换,纹理,光照等等,当然,如果你看过我原来翻译的managed dirctx kick start或者本来就熟悉MDX,那么学起来将会更加得心应手。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 此外,你还需要以下工具:<br/>1.&nbsp;&nbsp; Visual Studio Express 2005(注意,当前的XNA GSE还无法集成到VS pro中)<br/>2.&nbsp;&nbsp; XNA Game Studio Express<br/>3.&nbsp;&nbsp; 最新版本的DirectX SDK<br/>4.&nbsp;&nbsp; 当然,最好还有Mech Commander2的源代码(Mech Commander2是MS发行的一个游戏,现在开源了,大概800m,这个连接不是太稳定,多试几次)。<br/>&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一切准备就绪了,但我们还需要弄清楚一些概念:<br/>XNA / XNA Framework:他是一个托管的专门针对游戏开发(不仅仅是绘图)的函数库,基于Direct3D 9和.net framework 2.0,可以同时在Windows和Xbox360上运行。<br/>Managed DirectX 2.0:MDX 1.0的升级版,用于在.net framework 2.0下使用directx,但ms后来决定提供一个完全用于游戏开发的API,而不仅仅只是一套绘图函数库,因此, 把MDX 2.0整合到了XNA中,单独的MDX 2.0也成为了一个被取消的计划。<br/>&nbsp;<br/>假设你从来没有使用过VC# Express,首先打开程序:<br/></p><p><img src="http://www.xnacn.net/UpFile/UpAttachment/2006-9/2006917154512.jpg" border="0" alt=""/></p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 让我们来创建你的第一个游戏,选择 File -&gt; new project</p><p><img src="http://www.xnacn.net/UpFile/UpAttachment/2006-9/2006917154548.jpg" border="0" alt=""/></p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 选择 Windows Game(XNA)摸版,输入一个你喜欢的名字,然后单击OK。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 恭喜,你已经使用XNA创建了你的第一个windows游戏^_^<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 选择 Build-&gt; Build Solution,然后按下F5(或者 Debug -&gt; Start Debugging),现在可以看到你的程序在运行了:一个淡蓝色的窗口。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 好吧,我承认它并不是很有吸引力,但作为nxa的“hello world”程序,它其实传达了许多很重要的概念。来看看模板生成的代码:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打开Program.cs文件:<br/><font color="#0000ff">using System;<br/>namespace WindowsGame1<br/>{<br/>&nbsp;&nbsp;&nbsp; static class Program<br/>&nbsp;&nbsp;&nbsp; {<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// The main entry point for the application.<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using (Game1 game = new Game1())<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; game.Run();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br/>&nbsp;&nbsp;&nbsp; }<br/>}</font><br/>&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp; 很简单,所有程序都需要一个入口点,这里就是程序开始运行的地方。在main方法中,我们创建了Game1类的一个实例,并且调用了它的run方法。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 来看看类Game1,大部分工作都在这里完成。打开Game1.cs文件:<br/><font color="#0000ff">using System;<br/>using System.Collections.Generic;<br/>using Microsoft.Xna.Framework;<br/>using Microsoft.Xna.Framework.Audio;<br/>using Microsoft.Xna.Framework.Components;<br/>using Microsoft.Xna.Framework.Graphics;<br/>using Microsoft.Xna.Framework.Input;<br/>using Microsoft.Xna.Framework.Storage;<br/>&nbsp;<br/>namespace WindowsGame1<br/>{<br/>&nbsp;&nbsp;&nbsp; ///&lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp; /// This is the main type for your game<br/>&nbsp;&nbsp;&nbsp; ///&lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp; partial class Game1 : Microsoft.Xna.Framework.Game<br/>&nbsp;&nbsp;&nbsp; {<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Game1()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InitializeComponent();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected override void Update()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // The time since Update was called last<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float elapsed = (float)ElapsedTime.TotalSeconds;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // TODO: Add your game logic here<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Let the GameComponents update<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UpdateComponents();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected override void Draw()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Make sure we have a valid device<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!graphics.EnsureDevice())<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; graphics.GraphicsDevice.Clear(Color.CornflowerBlue);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; graphics.GraphicsDevice.BeginScene();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // TODO: Add your drawing code here<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Let the GameComponents draw<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DrawComponents();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; graphics.GraphicsDevice.EndScene();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; graphics.GraphicsDevice.Present();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br/>&nbsp;&nbsp;&nbsp; }<br/>}</font><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这里的代码同样简单明了。Game1继承于Microsoft.Xna.Famework.Game,Game类是一个游戏的基本骨架。这个对象把你从创建窗口、设置图形卡等其他琐碎设置的操作中解放出来,省略了大量每次编写游戏时都需要重复的代码。如果你熟悉MDX,那么这个类的功能相当于sdk sample framework中的Framework类,搭建了游戏的基本框架,设置了许多属性。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先,无论你否使用,代码自动添加了XNA的几个程序集的引用。一般来说,总是会用到这些程序集,因此保留这些代码。接下来,实现了一个默认的构造函数,Update方法以及Draw方法。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们依次来看这几个方法:<br/><font color="#0000ff">protected override void Update()<br/>{<br/>&nbsp;&nbsp;&nbsp; float elapsed = (float)ElapsedTime.TotalSeconds;<br/>&nbsp;&nbsp;&nbsp;&nbsp; UpdateComponents();<br/>}</font><br/>&nbsp;&nbsp;&nbsp;&nbsp; 一旦程序开始运行之后,就会不停调用Update()方法。可以把这里认为是你的“game loop”。这里将有大量的事件将要发生,包括AI计算,玩家的位置移动,输入等等,所有更新操作都在这里处理。对这个程序来说,我们只是简单的更新程序运行至今的时间。之后,调用了UpdateComponents()方法,它将自动调用程序中其他子组件的Update方法。确保调用这个方法很重要,组件(component)在xna中扮演了很重要的角色,为了保证这些组件的行为正确,这是必须的。<br/><font color="#0000ff">protected override void Draw()<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp; if (!graphics.EnsureDevice())<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br/>&nbsp;&nbsp;&nbsp;&nbsp; graphics.GraphicsDevice.Clear(Color.CornflowerBlue);<br/>&nbsp;&nbsp;&nbsp;&nbsp; graphics.GraphicsDevice.BeginScene();<br/>&nbsp;&nbsp;&nbsp;&nbsp; DrawComponents();<br/>&nbsp;&nbsp;&nbsp;&nbsp; graphics.GraphicsDevice.EndScene();<br/>&nbsp;&nbsp;&nbsp;&nbsp; graphics.GraphicsDevice.Present();<br/>}</font><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这里是程序的心脏也是灵魂部分。它完成了实在在屏幕上绘图的操作。当然,代码依然很简单。当程序创建时,将会创建一个名为graphics的对象,它是GraphicsComponent类的一个实例。GraphicsComponent是XNA中一个很重要也是很基本的类,提供了原来MDX中Presentationparameters和Deivce的功能。特别是GraphicsComponent的GraphicsDevice成员,其方法和属性和MDX中的Device都是类似的。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 来看代码:<br/>-首先,确保创建了可用的设备,否则,跳出这个方法<br/>-把屏幕清理为背景颜色Cornflower Blur,当然,这里可以把背景设置为任何颜色,但通常都是黑色。<br/>-告诉显卡你将要开始在场景中绘制物体<br/>-告诉每个子组件绘制其本身<br/>-告诉图形卡绘图操作已经完成<br/>-最后,把绘制好的图形呈现到屏幕上<br/>&nbsp;&nbsp;&nbsp;&nbsp; 简单明了。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 好了,这里你可能会问如何改变窗口的大小呢,如何全屏显示呢?嗯嗯,在Solution Explorer中右击Game1,选择设计视图。选择graphics组件。如前所属,我们在程序运行时就创建了一个GraphicsComponent对象。看一下属性窗口:</p><p><img src="http://www.xnacn.net/UpFile/UpAttachment/2006-9/2006917154718.jpg" border="0" alt=""/></p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这些都是GraphicsComponent所暴露的默认公共属性。如果需要全屏显示,只需要把IsFullScreen的值该为true就可以了。如果你查看代码,可以看到在Game1的InitializeComponent()方法中自动生成了this.graphics.IsFullScreen = true;。如何还需要自动改变窗口大小,则需要改变Game1的AllowUserResizing属性,在构造函数中添加this.AllowUserResizing = true;,此外,你还可以改变Game1的IsMouseVisible属性,选择是否显示鼠标。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 再次强调,组件在XNA中的重要性。你的游戏是一个组件,同样,他也包含了许多其他组件,你可以把组件理解为搭建游戏的积木。你已经看到了,在update和draw方法中,我们依次调用每一个组件的update和draw方法。这个效果将会传播到每个组件的子组件。将来,我们将会看到更多的组件,比如目录组件,地形组件,FPS计数器之类的助手组件等等。后面的章节我们将逐渐讨论这些组件。<br/>&nbsp;&nbsp;&nbsp;&nbsp; ok,第一讲到此结束。</p>
页: [1]
查看完整版本: [Clayman的专栏]中文XNA教程(一)——A Beginners Guide to XNA