3D游戏开发
创建一个新的工程,打开vs2008 选择File----New----Project. 当创建一个新工程的窗口显示的时候,选择Visual c#---XNA Game Studio 3.0. 给工程起名叫3D Madness,选择一个存放工程的路径,点击确定.
3D游戏跟2D游戏有很多区别,现在我们来具体的看一下一些关键的区别
坐标系统
第一个区别是,3D比2D多了一维的坐标系统.2D 坐标系中,绘图就像在屏幕中打印一个图片,你在屏幕的二维坐标中画一个图片.坐标(0,0)代表的是屏幕的左上角,X坐标轴向右,Y坐标轴向下.
如果说2D就像是在画一个图片的话,那么3D就像是在用一个手持的录像机录像.3D的显示是基于三维的坐标系统的.这种坐标系统,有时候被成为是世界坐标系,世界坐标系的最中间的圆点坐标为(0,0,0), 3D的图形你不可能只简单的画在屏幕上了.因为屏幕是二维的.我们能看到的只是摄像机拍到的东西.所以3D的图形,我们只关心两个元素:物体在世界的那个位置,摄像机放在世界的那个位置,摄像机朝向的角度.
摄像机的位置不同,角度不同,我们在看到的3d模型的位置就不同,可能是在屏幕的中间,也可能是在屏幕的下面,也可能就不在我们所能看到的屏幕上….
有很多总不同的3D坐标系,最常见的坐标系是X轴向右,Y轴向上,但是Z轴的方向是没有明确定义的.两种不同的3D坐标系统的存在,左手坐标系统和右手坐标系统.
伸出你的手,如图所示,拇指指向的方向是Z轴,手指的方向是X轴,卷曲手指的方向是Y轴.

在XNA中用的是右手坐标系统…就是说,从圆点开始,向右是X轴,向上是Y轴,朝着你的方向是Z轴.
摄像机
现在你明白了什么是坐标系统,我们来谈一谈什么是摄像机.这个相机不是陈冠希的摄像机.其实在屏幕上画一个3D的场景,就是拿一个手持的摄像机,观察相机里的图像.你要决定的是,摄像机在哪个位置,朝向哪个方向等等一些因素.
这些摄像机的属性存储在一个叫 Matrix(矩阵) 的类里. 矩阵运算其实是个特别复杂的数学问题,大学学的线性代数早就还给老师了.这里我们也不讨论这个问题.不过简单的说,你做3D图形显示的时候,他们的核心都是在进行过矩阵运算.幸运的是XNA提供的API能够处理全部的无聊的可怕的矩阵运算,我们所要做的就只剩下了,渐渐淡淡的了解 Matrix这个类,来表示一个摄像机~哈哈,开心吧.
XNA中有两个Matrix类可以表现摄像机…view(视图)类和projection(投影)类.view 类来控制在世界的哪个地方放摄像机啊,摄像机朝向方向啊,这些问题…
Projection 投影类定义摄像机的角度啊,摄像机能看多远啊等等问题.
整个Matrix类就用来把3D的世界表现在2D的屏幕上.
创建一个矩阵视图.我们用Matrix类的静态方法CreatLookAt(),这个静态的方法 返回一个Matrix的类,他接受一下的几个参数.

camaraPositon 是个vector3类型的 他用来描述摄像机的位置
cameraTarge vector3 类型, 摄像机朝向的坐标
cameraUpVector vector3类型 标志哪个个方向是向上的
Vector3是个什么类型呢,其实Vector3就是个三维坐标类型表示(X,Y,Z)
CreateLookAt() 方法的第三个参数标志了一个摄像机的向上的方向
拿一个手持的摄像机,你可以斜着拿,你也可以倒着拿,你爱怎么拿就怎么拿,对吧. 但是你你怎么拿的肯定会影响到你录制的结果.在XNA中着同样也是一个问题.
你给摄像机定义一个向上的向量,所以XNA就知道了,摄像机的方向.
创建projection 要用到Matrix的另外的一个静态的方法,这个静态的方法叫Matrix.CreatePerspectiveFieldOfView,这个方法同样的返回一个Matrix类,并且接受的参数如下

FieldOfView float类型 摄像机视角的弧度…通常用弧度表示 比如说45°就是π/4;
aspectRatio float类型 摄像机的外观比例.一般说是屏幕的宽度比上屏幕的高度.
nearPlaneDistance float类型 近端的梯形,也就是离多进物体会看不到.
farPlaneDistance float类型 多远后的东西摄像机看不到.
这个近端跟远端形成的椎体里的物体一般来说都会被draw到屏幕上,除非有在前面的物体挡着了. 这个椎体叫viewable frustum ,椎体外的东西是不会被绘制到屏幕上的.

Nearplane和Farplane之间的椎体.会被draw 到屏幕上,进的和远的都不会被绘制….
好了说了这么多没用的废话.我们现在开始do点代码.
把摄像机做成一个组建 是个不错的想法.这样以后你再给游戏增加个cameras,就变的很是方面了.好了,右键工程Add----New Item ----Game Component. 给文件起个名字叫Camera.cs 然后点add

在Camera.cs类中 增加两个类级别的属性来表示 view 和 projection
然后,更改构造器来接受3个Vector3的变量,分别表示摄像机初始的position target 和 up Vectors.在构造器中通过调用Matrix.CreateLookt来初始化View .调用Matix.CreatePerspectiveFieldOfView 来初始化projection
下面是camera.cs构造器的完整代码
Public Camera(Game game,Vector3 pos, Vector3 target, Vector3 up)
:base (game)
{
View =Matrix.createLookAt(pos,target,up);
Projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.PiOver4,
(float)Game.Window.ClientBounds.Width/
(float)Game.Window.ClientBounds.Height,
1,
100);
}
注意,要把屏幕的宽和高强制转化为float 这样就不会因为int类型损失,造成屏幕的畸形
好了 在你的game.cs里加如下面的代码
类级别的定义
Camera camera;
Game1 类的初始化方法里 假如下面的代买 来初始化
// Initialize camera
Camera = new Camera(this ,new Vector3(0,0,5),
Vector3.Zero, Vector3.Up);
Components.Add(camera);
哈哈 运行一下吧~你太厉害了 就让一个摄像机成功的工作了…看看你令人惊人的成就
多美丽的界面啊

呃….可能你会说不就是个垃圾蓝色界面么…
Come on ,man 想想你做了啥,你创建了一个摄像机在(0,0,5)这个位置,并且告诉了摄像机向(0,0,0)这个位置观看,你制定了(0,1,0)这个位置是向上的位置.
干的太漂亮了.这个蓝色的界面实在是太他妈的帅了~加油.
绘制基元
好了,现在你有了一个摄像机,let get ready to go~ 3D图形绘制的基础是三角形,也就是说,所有的3d图形都是通过绘制三角形来完成的,如果你画足够多的三角形,你就可以描述出所有可能的形状.只要三角形离得够进,画的够小,能画出来光滑的,圆形的表面.
好了 let’s rock and roll
为了画第一个三角形,我们要定义一些点,来表示三角形.
好了,到game1 类里面 在类空间里,创建一个VertexPositionColor的类数组
VertexPositionColor[] verts;
我们用这些对象来创建这些点
VertexPositionColor这个对象可以表示点的位置和颜色
我们在构造器里来给他们赋值.在LoadContent方法里
把点初始化了,代码如下:
//Initialize vertices
Verts = new VertexPositionColor[3];
Verts[0] = new VertexPositionColor(new vector3(0,1,0),Color.Blue);
Verts[1]= new VertexPositionColor(new vector3(1,-1,0),Color.Red);
Verts[2]=new VertexPositionColor(new Vector3(-1,-1,0),Color.Green);
下面在Game1的draw方法里,你需要做些事情来完成对VertexDeclaration的调用.简单的说 就是你要告诉你的图形设备,你要发送一些信息了.这些信息是VertexDeclaration类型的.
在GraphicsDevice.Clear的方法下面添加下面的代码
GraphicsDevice.VertexDeclaration=
New VertexDeclaration(GraphicsDevice,VertexPositionColor.VertexElements);
好了,接下来设置下效果和显示属性
BasicEffect effect = new BasicEffect(GraphicsDevice,null);
effect.World= Matrix.Identity;
effect.View=camera.view;
effect.projection=camera.projection;
effect.VertexColorEnabled=true;
//Begin effect and draw for each pass
effect.Begin();
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
Pass.Begin();
GraphicsDevice.DrawUserPrimitives<VertexPositionColor>
(PrimitiveType.TriangleStrip,verts,0,1);
Pass.End();
}
effect.End();
运行下游戏吧,一个特别酷的方框就被渲染出来了.看看效果

浙公网安备 33010602011771号