详解Windows Phone XNA 4.0 3D游戏开发

移动开发 游戏开发
如果做过Zune上XNA 3.1开发的朋友可能会记得,在XNA 3.1中是不支持3D开发的,XNA 4.0中加入的3D支持类,主要包含在Microsoft.Xna.Framework.Graphics命名空间中。

微软前段时间发布基于XNA框架Windows Phone 7游戏开发实例,看到Silverlight for phone和XNA 4.0的开发文章已经有了不少,而且质量很高。而XNA 4.0的3D开发这个领域的文章还不是很多,XNA 4.0的3D类库设计的非常好,比iPhone和Android的OpenGLES类库高出一个档次。以后学习3D开发,用XNA类库也是个不错的选择,而且Windows Phone模拟器对3D的支持也非常好。唯一的遗憾是,Windows Phone不支持C++的3D开发。

51CTO推荐专题:Windows Phone应用开发详解

程序代码编译环境Visual Stuido 2010, Windows Phone 7 SDK, XNA 4.0 Game Studio, 下载链接:http://files.cnblogs.com/aawolf/XNA_aawolf_3D.rar

如果做过Zune上XNA 3.1开发的朋友可能会记得,在XNA 3.1中是不支持3D开发的,XNA 4.0中加入的3D支持类,主要包含在Microsoft.Xna.Framework.Graphics命名空间中。如果XNA 4.0中的3D概念与OpenGLES十分相似,我们可以找到很多相对应的函数、方法等,某种意义上,XNA 4.0的3D支持是对OpenGLES 2.0的封装。

一个简单的3D程序

我们就从一个简单的3D程序开始吧,这个程序的原来介绍在下面这个链接里。

http://msdn.microsoft.com/en-us/library/bb203926.aspx

不过移植到Windows Phone 7上时,还是遇到了一些小问题,有的是文档的问题,有的是接口变化。如何在Visual Studio 2010里创建XNA 4.0的工程就不多说了,大家可以参考我写的《Windows Phone开发工具初体验》,链接如下:

http://www.cnblogs.com/aawolf/archive/2010/08/28/1811438.html

XNA 4.0的程序是派生自Microsoft.Xna.Framework.Game的类,开发者需要重载Game的四个方法:Initialize(初始化)、LoadContent(加载内容)、UnloadContent(卸载内容)、Update(更新)和Draw(绘制)等方法。

首先,我们在Game1类中加入所需要的一些私有变量:

Matrix worldMatrix;  
 
Matrix viewMatrix;  
 
Matrix projectionMatrix;  
 
VertexPositionNormalTexture[] cubeVertices;  
 
VertexDeclaration vertexDeclaration;  
 
VertexBuffer vertexBuffer;  
 
BasicEffect basicEffect;  
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

Martrix 的中文名叫“矩阵”,还有个翻译叫“黑客帝国”……扯远了,什么是矩阵?我们就不解释了,只要知道矩阵是一切3D线性变化的基础就可以了。我们不知道矩阵是什么,却身处其中。在Game1类中用了三个矩阵:worldMatrix用来描述世界坐标系;viewMatrix用来描述摄影机坐标系;projectionMatrix用来描述投影坐标系。这些都是3D图形学的概念,不解释了。

另外两个重要的变量是vertexBuffer和basicEffect。vertexBuffer包含了一系列的向量,这些向量构成了我们要显示的正方体的各个顶点;basicEffect用来描述一个基础的渲染效果,其中描述了坐标系、颜色和灯光等基本的要素,这些要素是3D图形显示的基础。

接下来创建一个叫InitMatrices的方法,对各个坐标系进行初始化,记得,这个InitMatrices的函数是我们自己创建的,代码如下:

private void InitMatrices()  
 
{  
 
// Initialize the world, view, and projection matrices.   
 
float tilt = MathHelper.ToRadians(0); // 0 degree angle  
 
// Use the world matrix to tilt the cube along x and y axes.  
 
worldMatrix = Matrix.CreateRotationX(tilt) * Matrix.CreateRotationY(tilt);  
 
viewMatrix = Matrix.CreateLookAt(new Vector3(5, 5, 5), Vector3.Zero, Vector3.Up);  
 
projectionMatrix = Matrix.CreatePerspectiveFieldOfView(  
 
MathHelper.ToRadians(45), // 45 degree angle  
 
(float)GraphicsDevice.Viewport.Width /  
 
(float)GraphicsDevice.Viewport.Height,  
 
1.0f, 100.0f);  
 
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

 

算了,不解释了,大家知道这段代码在干什么就好了。接下来,创建一个叫做InitEffect的函数中,对basicEffect进行初始化,代码如下:

 

private void InitEffect()  
 
{  
 
// Initialize BasicEffect with transformation and light values  
 
basicEffect = new BasicEffect(graphics.GraphicsDevice);  
 
basicEffect.World = worldMatrix;  
 
basicEffect.View = viewMatrix;  
 
basicEffect.Projection = projectionMatrix;  
 
// primitive color  
 
basicEffect.AmbientLightColor = new Vector3(0.1f, 0.1f, 0.1f);  
 
basicEffect.DiffuseColor = new Vector3(1.0f, 1.0f, 1.0f);  
 
basicEffect.SpecularColor = new Vector3(0.25f, 0.25f, 0.25f);  
 
basicEffect.SpecularPower = 5.0f;  
 
basicEffect.Alpha = 1.0f;  
 
basicEffect.LightingEnabled = true;  
 
if (basicEffect.LightingEnabled)  
 
{  
 
basicEffect.DirectionalLight0.Enabled = true; // enable each light individually  
 
if (basicEffect.DirectionalLight0.Enabled)  
 
{  
 
// x direction  
 
basicEffect.DirectionalLight0.DiffuseColor = new Vector3(1, 0, 0); // range is 0 to 1  
 
basicEffect.DirectionalLight0.Direction = Vector3.Normalize(new Vector3(-1, 0, 0));  
 
// points from the light to the origin of the scene  
 
basicEffect.DirectionalLight0.SpecularColor = Vector3.One;  
 
}  
 
basicEffect.DirectionalLight1.Enabled = true;  
 
if (basicEffect.DirectionalLight1.Enabled)  
 
{  
 
// y direction  
 
basicEffect.DirectionalLight1.DiffuseColor = new Vector3(0, 0.75f, 0);  
 
basicEffect.DirectionalLight1.Direction = Vector3.Normalize(new Vector3(0, -1, 0));  
 
basicEffect.DirectionalLight1.SpecularColor = Vector3.One;  
 
}  
 
basicEffect.DirectionalLight2.Enabled = true;  
 
if (basicEffect.DirectionalLight2.Enabled)  
 
{  
 
// z direction  
 
basicEffect.DirectionalLight2.DiffuseColor = new Vector3(0, 0, 0.5f);  
 
basicEffect.DirectionalLight2.Direction = Vector3.Normalize(new Vector3(0, 0, -1));  
 
basicEffect.DirectionalLight2.SpecularColor = Vector3.One;  
 
}  
 
}  
 
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.

然后要对vertexDeclaration、cubeVertices和vertexBuffer变量进行初始化,我们将这部分代码放在InitVertexBuffer函数中:

private void InitVertexBuffer()  
 
{  
 
// Create a vertex declaration for the type VertexPositionNormalTexture  
 
vertexDeclaration = new VertexDeclaration(new VertexElement[]  
 
{  
 
new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),  
 
new VertexElement(12, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0),  
 
new VertexElement(24, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0)  
 
}  
 
);  
 
// Create the per vertex data  
 
cubeVertices = new VertexPositionNormalTexture[36];  
 
Vector3 topLeftFront = new Vector3(-1.0f, 1.0f, 1.0f);  
 
Vector3 bottomLeftFront = new Vector3(-1.0f, -1.0f, 1.0f);  
 
Vector3 topRightFront = new Vector3(1.0f, 1.0f, 1.0f);  
 
Vector3 bottomRightFront = new Vector3(1.0f, -1.0f, 1.0f);  
 
Vector3 topLeftBack = new Vector3(-1.0f, 1.0f, -1.0f);  
 
Vector3 topRightBack = new Vector3(1.0f, 1.0f, -1.0f);  
 
Vector3 bottomLeftBack = new Vector3(-1.0f, -1.0f, -1.0f);  
 
Vector3 bottomRightBack = new Vector3(1.0f, -1.0f, -1.0f);  
 
Vector2 textureTopLeft = new Vector2(0.0f, 0.0f);  
 
Vector2 textureTopRight = new Vector2(1.0f, 0.0f);  
 
Vector2 textureBottomLeft = new Vector2(0.0f, 1.0f);  
 
Vector2 textureBottomRight = new Vector2(1.0f, 1.0f);  
 
Vector3 frontNormal = new Vector3(0.0f, 0.0f, 1.0f);  
 
Vector3 backNormal = new Vector3(0.0f, 0.0f, -1.0f);  
 
Vector3 topNormal = new Vector3(0.0f, 1.0f, 0.0f);  
 
Vector3 bottomNormal = new Vector3(0.0f, -1.0f, 0.0f);  
 
Vector3 leftNormal = new Vector3(-1.0f, 0.0f, 0.0f);  
 
Vector3 rightNormal = new Vector3(1.0f, 0.0f, 0.0f);  
 
// Front face.  
 
cubeVertices[0] =  
 
new VertexPositionNormalTexture(  
 
topLeftFront, frontNormal, textureTopLeft);  
 
cubeVertices[1] =  
 
new VertexPositionNormalTexture(  
 
bottomLeftFront, frontNormal, textureBottomLeft);  
 
cubeVertices[2] =  
 
new VertexPositionNormalTexture(  
 
topRightFront, frontNormal, textureTopRight);  
 
cubeVertices[3] =  
 
new VertexPositionNormalTexture(  
 
bottomLeftFront, frontNormal, textureBottomLeft);  
 
cubeVertices[4] =  
 
new VertexPositionNormalTexture(  
 
bottomRightFront, frontNormal, textureBottomRight);  
 
cubeVertices[5] =  
 
new VertexPositionNormalTexture(  
 
topRightFront, frontNormal, textureTopRight);  
 
// Back face.  
 
cubeVertices[6] =  
 
new VertexPositionNormalTexture(  
 
topLeftBack, backNormal, textureTopRight);  
 
cubeVertices[7] =  
 
new VertexPositionNormalTexture(  
 
topRightBack, backNormal, textureTopLeft);  
 
cubeVertices[8] =  
 
new VertexPositionNormalTexture(  
 
bottomLeftBack, backNormal, textureBottomRight);  
 
cubeVertices[9] =  
 
new VertexPositionNormalTexture(  
 
bottomLeftBack, backNormal, textureBottomRight);  
 
cubeVertices[10] =  
 
new VertexPositionNormalTexture(  
 
topRightBack, backNormal, textureTopLeft);  
 
cubeVertices[11] =  
 
new VertexPositionNormalTexture(  
 
bottomRightBack, backNormal, textureBottomLeft);  
 
// Top face.  
 
cubeVertices[12] =  
 
new VertexPositionNormalTexture(  
 
topLeftFront, topNormal, textureBottomLeft);  
 
cubeVertices[13] =  
 
new VertexPositionNormalTexture(  
 
topRightBack, topNormal, textureTopRight);  
 
cubeVertices[14] =  
 
new VertexPositionNormalTexture(  
 
topLeftBack, topNormal, textureTopLeft);  
 
cubeVertices[15] =  
 
new VertexPositionNormalTexture(  
 
topLeftFront, topNormal, textureBottomLeft);  
 
cubeVertices[16] =  
 
new VertexPositionNormalTexture(  
 
topRightFront, topNormal, textureBottomRight);  
 
cubeVertices[17] =  
 
new VertexPositionNormalTexture(  
 
topRightBack, topNormal, textureTopRight);  
 
// Bottom face.   
 
cubeVertices[18] =  
 
new VertexPositionNormalTexture(  
 
bottomLeftFront, bottomNormal, textureTopLeft);  
 
cubeVertices[19] =  
 
new VertexPositionNormalTexture(  
 
bottomLeftBack, bottomNormal, textureBottomLeft);  
 
cubeVertices[20] =  
 
new VertexPositionNormalTexture(  
 
bottomRightBack, bottomNormal, textureBottomRight);  
 
cubeVertices[21] =  
 
new VertexPositionNormalTexture(  
 
bottomLeftFront, bottomNormal, textureTopLeft);  
 
cubeVertices[22] =  
 
new VertexPositionNormalTexture(  
 
bottomRightBack, bottomNormal, textureBottomRight);  
 
cubeVertices[23] =  
 
new VertexPositionNormalTexture(  
 
bottomRightFront, bottomNormal, textureTopRight);  
 
// Left face.  
 
cubeVertices[24] =  
 
new VertexPositionNormalTexture(  
 
topLeftFront, leftNormal, textureTopRight);  
 
cubeVertices[25] =  
 
new VertexPositionNormalTexture(  
 
bottomLeftBack, leftNormal, textureBottomLeft);  
 
cubeVertices[26] =  
 
new VertexPositionNormalTexture(  
 
bottomLeftFront, leftNormal, textureBottomRight);  
 
cubeVertices[27] =  
 
new VertexPositionNormalTexture(  
 
topLeftBack, leftNormal, textureTopLeft);  
 
cubeVertices[28] =  
 
new VertexPositionNormalTexture(  
 
bottomLeftBack, leftNormal, textureBottomLeft);  
 
cubeVertices[29] =  
 
new VertexPositionNormalTexture(  
 
topLeftFront, leftNormal, textureTopRight);  
 
// Right face.   
 
cubeVertices[30] =  
 
new VertexPositionNormalTexture(  
 
topRightFront, rightNormal, textureTopLeft);  
 
cubeVertices[31] =  
 
new VertexPositionNormalTexture(  
 
bottomRightFront, rightNormal, textureBottomLeft);  
 
cubeVertices[32] =  
 
new VertexPositionNormalTexture(  
 
bottomRightBack, rightNormal, textureBottomRight);  
 
cubeVertices[33] =  
 
new VertexPositionNormalTexture(  
 
topRightBack, rightNormal, textureTopRight);  
 
cubeVertices[34] =  
 
new VertexPositionNormalTexture(  
 
topRightFront, rightNormal, textureTopLeft);  
 
cubeVertices[35] =  
 
new VertexPositionNormalTexture(  
 
bottomRightBack, rightNormal, textureBottomRight);  
 
vertexBuffer = new VertexBuffer(  
 
graphics.GraphicsDevice,  
 
typeof(VertexPositionNormalTexture),  
 
cubeVertices.Length,  
 
BufferUsage.None  
 
);  
 
vertexBuffer.SetData(cubeVertices);  
 
}  
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.
  • 196.
  • 197.
  • 198.
  • 199.
  • 200.
  • 201.
  • 202.
  • 203.
  • 204.
  • 205.
  • 206.
  • 207.
  • 208.
  • 209.
  • 210.
  • 211.
  • 212.
  • 213.
  • 214.
  • 215.
  • 216.
  • 217.
  • 218.
  • 219.
  • 220.
  • 221.
  • 222.
  • 223.
  • 224.
  • 225.
  • 226.
  • 227.
  • 228.
  • 229.
  • 230.
  • 231.
  • 232.
  • 233.
  • 234.
  • 235.
  • 236.
  • 237.
  • 238.
  • 239.
  • 240.
  • 241.
  • 242.
  • 243.
  • 244.
  • 245.
  • 246.
  • 247.
  • 248.
  • 249.
  • 250.
  • 251.
  • 252.
  • 253.
  • 254.
  • 255.
  • 256.
  • 257.
  • 258.
  • 259.
  • 260.
  • 261.
  • 262.
  • 263.
  • 264.
  • 265.
  • 266.
  • 267.
  • 268.
  • 269.
  • 270.
  • 271.
  • 272.
  • 273.
  • 274.
  • 275.
  • 276.
  • 277.
  • 278.
  • 279.
  • 280.
  • 281.
  • 282.
  • 283.
  • 284.
  • 285.
  • 286.
  • 287.
  • 288.
  • 289.
  • 290.
  • 291.
  • 292.
  • 293.
  • 294.
  • 295.
  • 296.
  • 297.
  • 298.
  • 299.
  • 300.
  • 301.
  • 302.
  • 303.
  • 304.

请原谅我把36个顶点的代码都贴出来了,如果不贴出来,肯定会有人不补全,然后就看不到完整的正方体了。

这里就要说到***个错误点了:文章中没有列出所有36个顶点的定义,不过示例代码UseBasicEffect中列出了;另一个问题是VertexBuffer的构造函数发生了变化,原文和示例代码中的VertexBuffer构造函数是这样的: 

vertexBuffer = new VertexBuffer(  
 
graphics.GraphicsDevice,  
 
VertexPositionNormalTexture.SizeInBytes * cubeVertices.Length,  
 
BufferUsage.None  
 
);  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

而正确的写法应该是:

vertexBuffer = new VertexBuffer(  
 
graphics.GraphicsDevice,  
 
typeof(VertexPositionNormalTexture),  
 
cubeVertices.Length,  
 
BufferUsage.None  
 
);  
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

VertexBuffer增加了一个Type类型的参数(第二个),我们必须传入一个IVertexType接口的派生类型,构造函数会用类型和顶点列表的长度计算VertexBuffer的size,这显然比上边的实现好了许多。

分别实现了这三个初始化函数后,我们要在真正的初始化函数Initialize里调用这三个函数,注意Initialize函数不是自己添加的,在Game1类中本来就有:

protected override void Initialize()  
 
{  
 
InitMatrices();  
 
InitEffect();  
 
InitVertexBuffer();  
 
base.Initialize();  
 
}  
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

好了,我们在Draw函数里增加绘制方法:

protected override void Draw(GameTime gameTime)  
 
{  
 
GraphicsDevice.Clear(Color.CornflowerBlue);  
 
// TODO: Add your drawing code here  
 
RasterizerState rasterizerState1 = new RasterizerState();  
 
rasterizerState1.CullMode = CullMode.None;  
 
graphics.GraphicsDevice.RasterizerState = rasterizerState1;  
 
GraphicsDevice.SetVertexBuffer(vertexBuffer);  
 
foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)  
 
{  
 
pass.Apply();  
 
graphics.GraphicsDevice.DrawPrimitives(  
 
PrimitiveType.TriangleList,  
 
0,  
 
36  
 
);  
 
}  
 
base.Draw(gameTime);  
 
}  
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.

这里包含了第二个错误点,原文没有下面这句(上文高亮标出):

GraphicsDevice.SetVertexBuffer(vertexBuffer);

如果没有SetVertexBuffer的调用,程序在运行时会遇到下面的异常:

An unhandled exception of type 'System.InvalidOperationException' occurred in Microsoft.Xna.Framework.Graphics.dll

Additional information: A valid vertex buffer (and a valid index buffer if you are using indexed primitives) must be set on the device before any draw operations may be performed.

原文的调用方式和UseBasicEffect的实现方式完全不同,所以大家要注意一下。毕竟是Beta版,很多文档还没有***完成。

好了,到这里,其实我们编译运行该程序的话,就可以看到绘制出的立方体来了。但是,我还想再加点——让立方体旋转起来。

在Update函数中增加下面两句(高亮显示):

protected override void Update(GameTime gameTime)  
 
{  
 
// Allows the game to exit  
 
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)  
 
this.Exit();  
 
// TODO: Add your update logic here  
 
Matrix matrix = Matrix.CreateRotationX(0.1f);  
 
basicEffectbasicEffect.World = basicEffect.World * matrix;  
 
base.Update(gameTime);  
 
}  
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

我们创建了一个沿X轴旋转0.1度的矩阵,与basicEffect中的世界坐标系相乘,就可以使我们绘制出来的立方体每次Update时,都沿着X轴旋转0.1f度。因为角度是float型,千万别忘了0.1f之后的那个f。好了,程序***的样子就是这样的。在***篇文章里,我留了很多问题,比如3D的基本概念、坐标系、灯光、材质、旋转,希望在后边能够比较从容地解释这些知识。我现在唯一的希望是,不要等到六个月后才有时间再写第二篇……

【编辑推荐】

  1. Windows Phone 7核心控件Panorama和Pivot月底发布
  2. 微软应用开发大赛曝光Windows Phone 7首批应用
  3. 微软发布Windows Phone 7游戏开发实例 基于XNA框架
  4. Windows Phone 7 平面设计师的T型台
  5. Windows Phone 7开发之Silverlight游戏编辑器

 

 

责任编辑:冰凝儿 来源: CSDN博客
相关推荐

2010-08-10 09:11:12

Windows PhoNXA

2011-03-16 10:24:22

3D开发Windows Pho

2013-06-14 09:41:59

2023-08-18 08:00:00

游戏开发3D模型

2021-12-28 10:52:10

鸿蒙HarmonyOS应用

2016-06-01 09:19:08

开发3D游戏

2011-05-25 16:07:17

2013-11-21 19:36:56

畅游游戏引擎Genesis-3D

2012-12-24 08:48:25

iOSUnity3D

2012-05-28 15:55:47

XNA 重力感应

2012-05-22 14:26:15

XNA 横竖屏设置

2012-12-24 09:04:04

iOSUnity3D

2022-09-07 12:00:26

Python3D游戏

2021-09-26 10:45:27

前端游戏CSS

2012-05-25 09:09:25

Windows Pho

2017-07-21 11:28:57

前端Threejs3D地图

2017-07-12 23:08:03

白鹭引擎

2010-08-06 15:44:28

Windows PhoWindows PhoSilverlight

2011-05-04 11:31:09

Windows PhoWindows Pho游戏开发

2012-02-02 16:37:51

Silverlight常用控件
点赞
收藏

51CTO技术栈公众号