Windows Phone xNa 4.0 3D Game Development

Source: Internet
Author: User

Author: Ma Ning

Program Code compiling environment Visual stuido 2010, Windows Phone 7 SDK, xNa 4.0 game studio, download link:

Http://files.cnblogs.com/aawolf/XNA_aawolf_3D.rar

Today, I have a little time to watch Windows Phone 7 development. As you can see, there are already a lot of development articles on Silverlight for phone and xNa 4.0, and they are of high quality. I would like to talk about xNa 4.0's 3D development field, which is just related to the current work, and xNa 4.0's 3D class library is designed very well, it is higher than the opengles class libraries of iPhone and Android. I will study 3D development in the future. Using xNa class library is also a good choice, and Windows Phone simulators also provide excellent 3D support. The only pity is that Windows Phone does not support C ++ 3D development.

If you have developed xNa 3.1 on Zune, you may remember that xNa 3.1 does not support 3D development. The 3D Support class added to xNa 4.0 is mainly included in Microsoft. xNa. framework. graphics namespace. If the 3D concept in xNa 4.0 is very similar to opengles, We can find many corresponding functions and methods. In a sense, xNa 4.0 3D support is an encapsulation of opengles 2.0.

1. A simple 3D Program

Let's start with a simple 3D program. The original introduction of this program is in the following link.

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

However, when porting to Windows Phone 7, we still encountered some minor problems, some were document problems, and some were interface changes. There is not much to say about how to create an xNa 2010 Project in Visual Studio 4.0. For details, refer to my "Windows Phone development tool first experience". The link is as follows:

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

The xNa 4.0 program is derived from Microsoft. xNa. framework. game class, developers need to reload the four methods of game: Initialize (initialization), loadcontent (loading content), unloadcontent (unload content), update (update) and draw (drawing).

First, we add the required private variables in the game1 class:

Matrix worldmatrix;

Matrix viewmatrix;

Matrix projectionmatrix;

Vertexpositionnormaltexture [] cubevertices;

Vertexdeclaration;

Vertexbuffer;

Basiceffect;

Martrix's Chinese name is "matrix", and another translation is "hacker empire "...... What is a matrix? We will not explain it, as long as we know that the matrix is the foundation of all 3D linear changes. We don't know what a matrix is, but we are in it. Three matrices are used in the game1 class: worldmatrix to describe the world coordinate system, viewmatrix to describe the camera coordinate system, and projectionmatrix to describe the projection coordinate system. These are the concepts of 3D graphics.

The other two important variables are vertexbuffer and basiceffect. Vertexbuffer contains a series of vectors that constitute the vertices of the cube to be displayed. basiceffect is used to describe a basic rendering effect, it describes basic elements such as coordinate system, color, and lighting. These elements are the basis for 3D graphic display.

Next, create a method called initmatrices to initialize the coordinate systems. Remember, the initmatrices function is created by ourselves. The Code is as follows:

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, 100366f );

}

Forget it. I don't want to explain it. Everyone knows what this code is doing. Next, create a function called initeffect to initialize basiceffect. The Code is as follows:

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 ction

Basiceffect. directionallight2.diffusecolor = new vector3 (0, 0, 0.5f );

Basiceffect. directionallight2.direction = vector3.normalize (New vector3 (0, 0,-1 ));

Basiceffect. directionallight2.specularcolor = vector3.one;

}

}

}

Then we need to initialize vertexdeclaration, cubevertices, and vertexbuffer variables. We will put this part of code in the initvertexbuffer function:

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 <vertexpositionnormaltexture> (cubevertices );

}

Forgive me for posting all the code for 36 vertices. If you do not post the code, someone will not complete the code, and then you will not see the complete cube.

The first one is mentioned here.Error pointThe article does not list the definitions of all 36 vertices, but the sample code usebasiceffect lists them. Another problem is that the vertexbuffer constructor has changed, the vertexbuffer constructor in the original and sample code is as follows:

Vertexbuffer = new vertexbuffer (

Graphics. graphicsdevice,

Vertexpositionnormaltexture. sizeinbytes * cubevertices. length,

Bufferusage. None

);

The correct statement should be:

Vertexbuffer = new vertexbuffer (

Graphics. graphicsdevice,

Typeof (vertexpositionnormaltexture ),

Cubevertices. length,

Bufferusage. None

);

Vertexbuffer adds a type parameter (the second parameter). We must input a derived type for the ivertextype interface. The constructor calculates the size of vertexbuffer using the length of the type and vertex list, this is obviously much better than the above implementation.

After the three initialization functions are implemented respectively, we need to call these three functions in the real initialization function initialize. Note that the initialize function is not added by ourselves, in the game1 class, there are:

Protected override void initialize ()

{

Initmatrices ();

Initeffect ();

Initvertexbuffer ();

Base. initialize ();

}

Now, we can add the painting method in the draw function:

Protected override void draw (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 );

}

This contains the second error point. The original text does not contain the following sentence (highlighted above ):

Graphicsdevice. setvertexbuffer (vertexbuffer );

If setvertexbuffer is not called, the program encounters the following exception during runtime:

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 med.

The calling method of the original text is completely different from that of usebasiceffect. Therefore, pay attention to it. After all, it is a beta version, and many documents have not yet been finalized.

Now, if we compile and run the program, we can see the drawn cube. However, I still want to add some more -- to rotate the cube.

Add the following two sentences to the update function (highlighted ):

Protected override void Update (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 );

Basiceffect. World = basiceffect. World * matrix;

Base. Update (gametime );

}

We have created a matrix that rotates 0.1 degrees along the X axis, multiplied by the world coordinate system in basiceffect, so that every update of the created cube rotates by degrees along the X axis. Because the angle is float, do not forget the f After 0.1f.

Well, the program looks like this at the end. In the first article, I left a lot of questions, such as the basic concepts of 3D, coordinate system, lighting, material, and rotation. I hope I can easily explain this knowledge later. My only hope now is not to wait until six months before I write another article ......

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.