Important:
This is retired content. This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This content may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.
4/7/2010

Microsoft Corporation

February 2007

Summary

Learn how to use the game libraries in the Microsoft® .NET Compact Framework running on a Microsoft Windows Mobile® 5.0 device to render both two dimensions and three dimensions using the Managed DirectX® Mobile libraries. This includes creating a device, rendering sprites, vertices, matrix, and meshes. This HOL will take 1 hour and 30 minutes to complete.

Applies To

Microsoft .NET Compact Framework version 2.0Windows Mobile 5.0Microsoft Visual Studio® 2005Microsoft DirectX 9.0 SDKMicrosoft Direct3D®

The following applications are required to run this HOL:

  • Microsoft Windows® XP Professional

  • DirectX 9.0 SDK

    Download and install DirectX 9.0 .

  • Visual Studio 2005

    This HOL requires Visual Studio 2005 Standard, Professional, or Team System Editions. It will not work with any of the Express Editions. If you do not have the correct edition of Visual Studio 2005, find out how you can acquire it from the Visual Studio 2005 Developer Center .

  • Microsoft ActiveSync® 4.0

    ActiveSync 4.0 allows for connectivity between a Windows Mobile powered device and your computer.

    Download and install ActiveSync 4.0 .

  • Windows Mobile 5.0 SDKs.

    The Windows Mobile 5.0 SDKs for Pocket PC and Smartphone enable development for Windows Mobile powered devices in Visual Studio 2005.

    Download and install Windows Mobile 5.0 SDK for Pocket PC .

    Download and install Windows Mobile 5.0 SDK for Smartphone .

    Note:
    If you used an emulator in a previous HOL, you should do a hard reset of the emulator before starting this HOL. (On the emulator, click File, point to Reset, and then click Hard.)
    Note:
    During development, if you receive an error that indicates that the process or file is in use, the program is still running on the emulator, and you must close the program before you can deploy and run a new copy. This error may appear anytime in the HOL that you deploy the emulator.

Introduction

This HOL shows you how to use transforms to modify the rendered images to run all resolutions devices offer, including VGA Pocket PCs and Smartphones. By the end of this HOL, you will have a basic understanding about how to use these features when you create device-based casual games.

Managed Direct3D Mobile (Managed D3DM) will reduce the volume of code and increase your productivity. The interfaces are more intuitive--inheriting from the powerful and easy-to-use .NET Compact Framework common types. Managed code also frees you from having to deal with most memory management tasks, such as releasing objects. Managed D3DM is provided as a part of the .NET Compact Framework version 2.0. Managed D3DM runs on top of the native Direct3D Mobile, which is being delivered in all Windows Mobile 5.0 powered devices. At a minimum, each new Windows Mobile 5.0 device ships with software drivers, and some are planned to ship with hardware acceleration.

If you're interested in writing a three-dimensional game, you should work through all of the labs in this HOL. If you're interested in writing a two-dimensional game, you can skip Labs 2 and 3.

In this HOL, you will work with the Treo 700 device, which runs a software D3D driver. You can also experiment with the device emulator, which includes the reference software driver. This platform is too slow to do much, but it is available for investigation.

Lab 1: Create a Managed D3DM Device

The objective of this lab is to create a new managed D3DM device as your first Hello World application. The managed D3DM device is the parent of all graphical objects that are painted in your solution. This lab shows you how to create the new device and run it on a Pocket PC.

In this lab, you will perform the following exercise:

  • Creating a new managed D3DM device

Exercise 1: Creating a New Managed D3DM Device

In this exercise, you will use Visual Studio 2005 to create a blank C# project, write the code to create a device, and then compile and deploy the managed D3DM device to a Pocket PC.

To create new project in Visual Studio 2005
  1. In Visual Studio 2005, click File| New| Project.

  2. On the New Projectdialog box, open a blank C# project and select Smart Device| Windows Mobile 5.0 Pocket PC.

  3. On the Projectmenu, click Add Reference.

  4. Add the following references to the project:

    • Microsoft.WindowsMobile.DirectX

    • System.Drawing

    • System.Windows.Forms

    • System

To create a managed D3DM device
  1. Click Project| Add New Item.

  2. In the Add New Itemdialog box, delete all the code in the new class.

  3. Add all of the needed references and class definitions by adding the following code.

    Copy Code
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using Microsoft.WindowsMobile.DirectX;
    using Microsoft.WindowsMobile.DirectX.Direct3D;
    
    namespace Microsoft.Samples.MD3DM
    {
    	// The main class for this sample
    	public class CreateDevice : Form
    	{
    		// The global variables for this project
    		Device device = null;
    
    		// CreateDevice here
    
    		//InitializeGraphics here
    
    		//Render here
    
    		//OnPaint here
    
    		// OnPaintBackground here
    
    		// OnKeyPress here
    
    		// Main here
    
    }
    }
    
  4. Replace // CreateDevicehere by adding the following code to the CreateDeviceclass. This code sets the Textand MinimizeBoxproperties so the form can be closed.

    Copy Code
    	public CreateDevice()
    	{
    		// Set the caption
    		this.Text = "Hello World";
    		this.MinimizeBox = false;
    }
    
  5. Initialize the managed D3DM subsystem by adding InitializeGraphics. Replace //InitializeGraphicshere with the following code.

    Copy Code
    public bool InitializeGraphics()
    	{
    		try
    		{
    			// Set up the D3D parameters
    			PresentParameters presentParams = new
    PresentParameters();
    
    			// Causes the display to appear in a window rather than
    			// full screen
    			presentParams.Windowed = true;
    
    			// When a new frame is swapped to the front buffer,
    			// the old frame will be discarded
    			presentParams.SwapEffect = SwapEffect.Discard;
    
    			// The first parameter of 0 indicates that the Device
    object
    			// should use the system's physical adapter. The second
    parameter 
    			// identifies the device type. When working with D3DM,
    the only 
    			// supported device type is the default. The third
    parameter is a 
    			// reference to the current form which will be doing
    the 
    			// rendering.The forth parameter, CreateFlags, allows
    you to set 
    			// various options for the device. The final parameter,
    
    			// presentParams, contains the details about how the
    image will 
    			// be displayed in the render area, what buffers it
    will use, and 
    			// the formats it will have. 
    			device = new Device(0, DeviceType.Default, this,
    				CreateFlags.None, presentParams);
    	}
    		catch (DirectXException)
    		{
    			return false;
    	}
    		return true;
    }
    
  6. Set up the render logic to draw each frame with the color of blue. Replace // Renderhere with the following code.

    Copy Code
    private void Render()
    {
    		if (device != null)
    		{
    			//Clear the back buffer to a blue color 
    			device.Clear(ClearFlags.Target, Color.Blue,
    					1.0f, 0);
    			//Begin the scene
    			device.BeginScene();
    
    			// Rendering of the scene objects can happen here
    
    			//End the scene
    			device.EndScene();
    			device.Present();
    	}
    }
    	
    
  7. Create a game loop by overriding OnPaint. Replace //OnPainthere with the following code.

    Copy Code
    protected override void OnPaint(PaintEventArgs e)
    	{
    		// Render on painting
    		this.Render();
    
    		// Render again
    		this.Invalidate();
    }
    
  8. Do not include any logic here because you are filling the entire back buffer with blue in the Renderfunction. Add the following code to your class.

    Copy Code
    	protected override void OnPaintBackground(PaintEventArgs e)
    	{
    		// Do nothing to ensure that the rendering area is not
    overdrawn
    }
    
  9. Add OnKeyPressto detect when the user presses the ESC to exit the application. Replace //OnKeyPresshere with the following code.

    Copy Code
    	protected override void OnKeyPress(KeyPressEventArgs e)
    	{
    		// Esc was pressed
    		if ((int)(byte)e.KeyChar == (int)Keys.Escape)
    		this.Close();
    }
    
  10. Create Mainto launch the application. Replace //Mainhere with the following code.

    Copy Code
    	static void Main()
    	{
    		CreateDevice frm = new CreateDevice();
    
    		// Initialize Direct3D
    		if (!frm.InitializeGraphics())
    		{
    			MessageBox.Show("Could not initialize Direct3D. " +
    				"This tutorial will exit.");
    			return;
    	}
    
    		Application.Run(frm);
    }
    
To compile and deploy the managed D3DM project
  1. Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.

  2. On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.

  3. Click Deploy. Visual Studio deploys the project.

  4. Click Yeswhen the device prompts you to accept the project from an unknown publisher. You should see the blue managed D3DM device with the title Hello World.

  5. On the managed D3DM device, click OKto close it.

Summary

In this lab, you performed the following exercise:

  • Creating a new managed D3DM device

Lab 2: Create a Spinning Triangle with Managed D3DM

The objective of this lab is to create a simple object, a triangle, from a vertex buffer, render the object, and then make it rotate by using the Hello World application as a starting point.

In this lab, you will perform the following exercises:

  • Creating a triangle

  • Changing the triangle's perspective

Exercise 1: Creating a Triangle

This exercise uses the skeleton managed D3DM device that you created in the first lab to draw a triangle with three vertices. Triangles are the building blocks of all D3D drawings; given enough triangles, you can draw anything.

To modify the Hello World code to draw a triangle
  1. Modify the global variables in the CreateDeviceclass to include a VertexBuffervariable. Replace // The global variables for this projectwith the following code.

    Copy Code
    VertexBuffer vertexBuffer = null;
    PresentParameters presentParams = new PresentParameters();
    
  2. Change the form text in the CreateDevicefunction. Replace this.Text = "Hello World";with the following code.

    Copy Code
    		this.Text = "Spinning Tringle";
    
  3. Modify the code in InitializeGraphicsby replacing all of the code in the tryblock with the following code.

    Copy Code
    presentParams.Windowed = true;
    presentParams.SwapEffect = SwapEffect.Discard;
    device = new Device(0, DeviceType.Default, this,
    					CreateFlags.None, presentParams);
    device.DeviceReset += new EventHandler(this.OnResetDevice);
    this.OnCreateDevice(device, null);
    this.OnResetDevice(device, null);
    
  4. Add OnCreateDeviceto the CreateDeviceclass to configure the device on creation, as shown in the following code.

    Copy Code
    	void OnCreateDevice(object sender, EventArgs e)
    	{
    		Pool vertexBufferPool;
    		Caps caps;
    		Device dev = (Device)sender;
    		// Get the device capabilities
    		caps = dev.DeviceCaps;
    
    		if (caps.SurfaceCaps.SupportsVidVertexBuffer)
    			vertexBufferPool = Pool.VideoMemory;
    		else
    			vertexBufferPool = Pool.SystemMemory;
    
    		// Now create the VertexBuffer
    		vertexBuffer = new VertexBuffer(
    			typeof(CustomVertex.PositionColored), 3, dev, 0,
    			CustomVertex.PositionColored.Format, vertexBufferPool);
    		vertexBuffer.Created += new EventHandler(
    			this.OnCreateVertexBuffer);
    		this.OnCreateVertexBuffer(vertexBuffer, null);
    }
    
  5. Add OnResetDeviceto configure the device on reset, as shown in the following code.

    Copy Code
    	void OnResetDevice(object sender, EventArgs e)
    	{
    		Device dev = (Device)sender;
    		// Turn off culling, so you see the front and back of the
    triangle
    		dev.RenderState.CullMode = Cull.None;
    		// Turn off D3D lighting because you are providing your own
    vertex
    		// colors
    		dev.RenderState.Lighting = false;
    }
    
  6. Add OnCreateVertexBufferto configure the triangle when the buffer is created or recreated, as shown in the following code.

    Copy Code
    	void OnCreateVertexBuffer(object sender, EventArgs e)
    	{
    		VertexBuffer vb = (VertexBuffer)sender;
    		CustomVertex.PositionColored[] verts =
    			 (CustomVertex.PositionColored[])vb.Lock(0, 0);
    		verts[0].X = -1.0f;
    		verts[0].Y = -1.0f;
    		verts[0].Z = 0.0f;
    		verts[0].Color =
    System.Drawing.Color.DarkGoldenrod.ToArgb();
    
    		verts[1].X = 1.0f;
    		verts[1].Y = -1.0f;
    		verts[1].Z = 0.0f;
    		verts[1].Color =
    System.Drawing.Color.MediumOrchid.ToArgb();
    
    		verts[2].X = 0.0f;
    		verts[2].Y = 1.0f;
    		verts[2].Z = 0.0f;
    		verts[2].Color = System.Drawing.Color.Cornsilk.ToArgb();
    		vb.Unlock();
    }
    
  7. Modify Renderto draw the TriangleList. Replace // Rendering of the scene objects can happen herewith the following code.

    Copy Code
    device.SetStreamSource(0, vertexBuffer, 0);
    device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
    
To compile and deploy the managed D3DM project
  1. Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.

  2. On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.

  3. Click Deploy. Visual Studio deploys the project.

  4. Click Yeswhen the device prompts you to accept the project from an unknown publisher. You should see the blue managed D3DM device with a triangle drawn in the center of it.

  5. On the managed D3DM device, click OKto close it.

Exercise 2: Changing the Triangle's Perspective

In this exercise, you will add a view matrix to change the triangle's perspective, so the triangle appears to rotate.

To change perspective in code by using matrices
  1. Create SetupMatricesby setting up the world view, and then by changing that view each frame, as shown in the following code.

    Copy Code
    private void SetupMatrices()
    	 {
    		// For the world matrix, you will rotate the object about
    		// the y-axis. Set up the rotation matrix to generate 1
    full 
    		// rotation (2*PI radians) every 1000 ms. To avoid the loss
    of
    		// precision inherent in very high floating point numbers,
    the
    		// system time is modulated by the rotation period before
    		// conversion to a radian angle.
    		int iTime = Environment.TickCount % 1000;
    		float fAngle = iTime * (2.0f * (float)Math.PI) / 1000.0f;
    		device.Transform.World = Matrix.RotationY(fAngle);
    
    		// Set up the view matrix. A view matrix can be defined
    given
    		// an eye point, a point to look at, and a direction for
    which
    		// way is up. In this code, you set the eye five units back
    along the
    		// z-axis and up three units, look at the origin, and
    define
    		// "up" to be in the y-direction.
    		device.Transform.View = Matrix.LookAtLH(
    			new Vector3(0.0f, 3.0f, -5.0f),
    			new Vector3(0.0f, 0.0f, 0.0f),
    			new Vector3(0.0f, 1.0f, 0.0f));
    
    		// For the projection matrix, you set up a perspective
    transform
    		// (which transforms geometry from three-dimensional view
    space to 
    		// two-dimensional viewport
    		// space, with a perspective divide that makes objects
    smaller in
    		// the distance). To build a perpsective transform, you
    need the
    		// field of view (1/4 pi is common),
    		// the aspect ratio, and the near and far clipping planes
    		// (which define at what distances geometry should be no
    longer
    		// be rendered).
    		device.Transform.Projection =
    			Matrix.PerspectiveFovLH((float)Math.PI / 4,
    			1.0f, 1.0f, 100.0f);
    }
    
  2. Call SetupMatrices, as shown in the following code, from the Renderfunction by adding a call to it just after the BeingScene.

    Copy Code
    SetupMatrices();
    
To compile and deploy the managed D3DM project
  1. Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.

  2. On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.

  3. Click Deploy. Visual Studio deploys the project.

  4. Click Yeswhen the device prompts you to accept the project from an unknown publisher. You should see the blue managed D3DM device with a triangle drawn in the center of it.

  5. On the managed D3DM device, click OKto close it.

Summary

In this lab, you performed the following exercises:

  • Creating a triangle

  • Changing the triangle's perspective

Lab 3: Create a Spinning Mesh

Three-dimensional modeling software can represent an object by using complicated geometry. Data representing this geometry is called a mesh and is commonly stored in a Direct3D .x file. Direct3D uses meshes to load the objects from these files. This lab introduces the topic of meshes and shows how to load, render, and unload a mesh. Managed D3DM uses meshes in a file format that is a subset of the .x format with the extension .md3dm. A mesh contains the data for a complex model. It is an abstract data container that contains resources, such as textures and materials, and attributes, such as position data and adjacency data.

Lab Objective

The objective of this lab is to show you how to convert an .x file, load that mesh on a device, and change the perspective to make it appear to spin.

In this lab, you will perform the following exercises:

  • Converting an .x file to an .md3dm file

  • Loading a mesh onto a device

  • Creating a Spinning Tiger Project

Note:
This lab has a weakness in the OnResetDevicemethod, where resources are loaded from the assembly. If the assembly name and the default namespace is not Lab3; it will fail. If you fail to run the tiger, check the default namespace by opening the project's properties (click Project| Properties). The Applicationtab includes the default namespace. If the value is not Lab3, change it.

Exercise 1: Converting an .x File to an .md3dm File

Visual Studio 2005 includes a sample that converts .x files to .md3dm files. You will use the application that you build from that sample to create an .md3dm file.

To convert an .x file to an .md3dm file
  1. Open a Command Promptwindow (click Start| Run, and then type cmd).

  2. Type cd c:.

  3. Type cd C:\HOL320\Tools\.

  4. Type MeshConvertercs.exe Tiger.x Tiger.md3dmto convert the Tiger.x file to Tiger.md3dm.

To set up a new Pocket PC project
  1. In Visual Studio 2005, click File| New| Project.

  2. In the New Projectdialog box, open a new C# project, and then select SmartDevices| Windows Mobile 5.0 Pocket PC.

  3. Add an empty project, and name it Lab3. (The project name is referenced in the code.)

  4. On the Projectmenu, click Add Reference.

  5. Add the following references:

    • Microsoft.WindowsMobile.DirectX

    • System.Drawing

    • System.Windows.Forms

    • System

To embed the Tiger.md3dm file and Tiger.bmp file as resources in your project
  1. Click Project| Add Existing Item.

  2. Click Add Resource| Add Existing File.

  3. Change Files of Typeto All Files.

  4. Change the Look Invalue to C:\HOL320\Tools\.

  5. Add Tiger.md3dmand Tiger.bmp(holding down SHIFT and clicking the left mouse button selects multiple files).

  6. Get the properties of each resource by looking in Solution Explorer, right-clicking the resource, and then choosing Properties.

  7. Change the Build Actionvalue to Embedded Resourceto compile these resources into the assembly.

  8. Click Project| Add Existing Item.

  9. Browse to C:\HOL320\Tools\Create Project, and add MeshLoader.cs. MeshLoader.cs is a part of the Mesh sample and includes the code to load an .md3dm mesh.

Exercise 2: Loading a Mesh onto a Device

This exercise leads you through loading the mesh.

To add a new class
  1. Click Project| Add New Item.

  2. On the Add New Itemdialog box, add a new code file.

To add a class definition
  1. Add all of the needed references and class definitions by adding the following code:

    Copy Code
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using Microsoft.WindowsMobile.DirectX;
    using Microsoft.WindowsMobile.DirectX.Direct3D;
    using System.Reflection;
    
  2. Add a namespace and the class definitions by adding the following code:

    Copy Code
    namespace Microsoft.Samples.MD3DM
    {
    	public class Meshes : Form
    	{
    		// The D3D rendering device
    		Device device = null;
    
    		// The mesh object in the system
    		Mesh mesh = null;
    
    		// Materials for the mesh
    		Material[] meshMaterials;
    
    		// Textures for the mesh
    		Texture[] meshTextures;
    
    		// The display parameters for drawing a D3D window
    		PresentParameters presentParams = new PresentParameters();
    
    		//InitializeGraphics here
    
    //Add OnDeviceReset
    
    //SetupMatrices here
    
    //Render here
    
    //OnPaint here
    
    //OnPaintBackGround here
    
    //OnKeyPress here
    
    //OnResize here
    
    //Main here
    }
    }
    

Exercise 3: Creating a Spinning Tiger Project

This exercise shows you how to change the perspective of the Tiger project to make it appear to spin.

To add code to the project and render it
  1. Replace //InitializeGraphics hereby adding the following code to the InitializeGraphicsmethod in the Meshesclass.

    Copy Code
    bool InitializeGraphics()
    	 {
    		try
    		{
    			// Draw the graphics inside a standard window
    			presentParams.Windowed = true;
    
    			// Discard the current frame when drawing a new one
    			presentParams.SwapEffect = SwapEffect.Discard;
    
    			// Create a 16-bit depth buffer 
    			presentParams.EnableAutoDepthStencil = true;
    			presentParams.AutoDepthStencilFormat = DepthFormat.D16;
    
    			// Create the D3D device
    			device = new Device(0, DeviceType.Default, this,
    				CreateFlags.None, presentParams);
    			device.DeviceReset += new System.EventHandler(
    				this.OnResetDevice);
    			this.OnResetDevice(device, null);
    	}
    		catch (Exception)
    		{
    			return false;
    	}
    
    		return true;
    }
    
  2. Replace //Add OnDeviceResetby adding the following code.

    Note:
    GetManifestResourceStreamstarts with the path to the default namespace. Project1 is referenced as the default. Check the default namespace property before completing this step.
    Copy Code
    void OnResetDevice(object sender, EventArgs e)
    	{
    		string[] textureFilenames = null;
    
    		Device dev = (Device)sender;
    
    		// Turn on the zbuffer
    		dev.RenderState.ZBufferEnable = true;
    
    		// Turn on ambient lighting 
    		dev.RenderState.Ambient = System.Drawing.Color.White;
    
    		// Turn on perspective correction for textures.
    		// This provides a more accurate visual at the cost
    		// of a small performance overhead
    		dev.RenderState.TexturePerspective = true;
    
    		// Load the mesh from the specified file.
    		//Note Project1 refers to the defalut namespace
    		mesh = MeshLoader.LoadMesh(device,
    		 
    Assembly.GetExecutingAssembly().GetManifestResourceStream(
    			"Lab3.Tiger.md3dm"), MeshFlags.SystemMemory,
    			out meshMaterials, out textureFilenames);
    
    
    		// Extract the material properties and texture names
    		meshTextures = new Texture[meshMaterials.Length];
    		for (int i = 0; i < meshMaterials.Length; i++)
    		{
    
    			// Set the ambient color for the material
    			// (D3DX does not do this)
    			meshMaterials[i].Ambient = meshMaterials[i].Diffuse;
    
    			// Create the texture
    			meshTextures[i] = TextureLoader.FromStream(dev,
    				 
    Assembly.GetExecutingAssembly().GetManifestResourceStream(
    					"Lab3." + textureFilenames[i]));
    }
    }
    
  3. Replace //SetupMatrices hereby adding the following code.

    Copy Code
    void SetupMatrices()
    	{
    		// For the world matrix, you will just leave it as the
    identity
    		device.Transform.World =
    			Matrix.RotationY(Environment.TickCount / 1000.0f);
    
    		// Set up the view matrix. A view matrix can be defined
    given
    		// an eye point, a point to look at, and a direction for
    which
    		// way is up. In this code, you set the eye five units back
    along the
    		// z-axis and up three units, look at the origin, and
    define
    		// "up" to be in the y-direction.
    		device.Transform.View = Matrix.LookAtLH(
    			new Vector3(0.0f, 2.0f, -3.0f),
    			new Vector3(0.0f, 0.0f, 0.0f),
    			new Vector3(0.0f, 1.0f, 0.0f));
    
    		// For the projection matrix, you set up a perspective
    		// transform (which transforms geometry from
    three-dimensional view 
    		// space to two-dimensional
    		// viewport space, with a perspective divide that makes
    objects 
    		// smaller in the distance). To build a perpsective
    transform,
    		// you need the field of view (1/4 pi is common), the
    aspect
    		// ratio, and the near and far clipping planes (which
    define at
    		// what distances geometry should be no longer be
    rendered).
    		device.Transform.Projection =
    			Matrix.PerspectiveFovLH((float)(Math.PI / 4), 1.0f,
    1.0f,
    			100.0f);
    }
    
  4. Replace //Render herewith the following code.

    Copy Code
    private void Render()
    	 {
    		if (device == null)
    			return;
    
    		//Clear the back buffer to a blue color 
    		device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,
    			System.Drawing.Color.Blue, 1.0f, 0);
    		//Begin the scene
    		device.BeginScene();
    		// Set up the world, view, and projection matrices
    		SetupMatrices();
    
    		// Meshes are divided into subsets; one for each material.
    		// Render them in a loop
    		for (int i = 0; i < meshMaterials.Length; i++)
    		{
    			// Set the material and texture for this subset
    			device.Material = meshMaterials[i];
    			device.SetTexture(0, meshTextures[i]);
    
    			// Draw the mesh subset
    			mesh.DrawSubset(i);
    	}
    
    		//End the scene
    		device.EndScene();
    		device.Present();
    }
    
  5. Replace //OnPaint herewith the following code.

    Copy Code
    	protected override void
    OnPaint(System.Windows.Forms.PaintEventArgs e)
    	{
    		// Render the mesh to the screen
    		Render();
    
    		// Invalidating the window will cause it to be redrawn in
    		// the future
    		Invalidate();
    }
    
  6. Replace //OnPaintBackGround herewith the following code.

    Copy Code
    	protected override void OnPaintBackground(
    		System.Windows.Forms.PaintEventArgs e)
    	{
    		// Doing nothing ensures the background will never overdraw
    		// the previous rendering
    }
    
  7. Replace //OnKeyPress herewith the following code.

    Copy Code
    	protected override void OnKeyPress(KeyPressEventArgs e)
    	{
    		// If ESC was pressed, then shut down
    		if ((int)e.KeyChar == (int) Keys.Escape)
    			this.Close();
    }
    
  8. Replace //OnResize herewith the following code.

    Copy Code
    	protected override void OnResize(EventArgs e)
    	{
    		base.OnResize(e);
    }
    
  9. Replace //Main herewith the following code.

    Copy Code
    static void Main()
    	{
    		Meshes meshForm = new Meshes();
    
    		// Initialize Direct3D
    		if (!meshForm.InitializeGraphics())
    		{
    			MessageBox.Show("Could not initialize Direct3D. " +
    				"This tutorial will exit.");
    			return;
    	}
    
    		// Run the form
    		try
    		{
    			Application.Run(meshForm);
    	}
    		catch (Exception e)
    		{
    			MessageBox.Show("An error occured and this sample needs
    " +
    				" to  close:" + e.Message);
    	}
    }
    
To compile and deploy the managed D3DM project
  1. Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.

  2. On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.

  3. Click Deploy. Visual Studio deploys the project.

  4. Click Yeswhen the device prompts you to accept the project from an unknown publisher.

  5. On the managed D3DM device, click OKto close it.

Summary

In this lab, you performed the following exercises:

  • Converting an .x file to an .md3dm file

  • Loading a mesh onto a device

  • Creating a Spinning Tiger Project

Lab 4: Create a Simple Two-Dimensional Sprite Casual Game

Traditional two-dimensional casual games are based on animated sprites. Managed D3DM offers a Spriteclass that allows you render and rotate sprites.

Managed D3DM handles sprites as textures. These textures get loaded then displayed on the managed D3DM device through the Spriteclass. The Spriteclass takes parameters to allow different areas of the texture to be rendered. This lab refers to these areas as tiles. Moving from area to area renders the animations of the sprite, causing it to appear to rotate, as shown in Figure 1. The Spriteclass also places the sprite on the managed D3DM device, thus allowing it to move from frame to frame. Finally sprites can be transformed to allow the texture to be modified, in this example, scaled to fit the screen.

Figure 1. Donut.bmp appears to be rotating

Lab Objective

The objective of this lab is to render a static sprite, animate a sprite, move the sprite on the screen and detect collisions, and scale the sprite according to the device's screen.

In this lab, you will perform the following exercises:

  • Rendering a static sprite

  • Animating a sprite

  • Moving a sprite

  • Detecting collisions

  • Scaling a sprite according to screen size

Exercise 1: Rendering a Static Sprite

This exercise will lead you through rendering a static sprite, including creating the project, constructing the data class, and rendering one of tiles of the sprite.

To create a new project
  1. In Visual Studio 2005, click File| New| Project.

  2. In the New Project dialog box, open a new C# project, and then select SmartDevices| Windows Mobile 5.0 Pocket PC.

  3. Name the project Lab4.

  4. On the Projectmenu, click Add Reference.

  5. Add the following references:

    • Microsoft.WindowsMobile.DirectX

    • System.Drawing

    • System.Windows.Forms

    • System

  6. Click Project| Add Existing Item.

  7. Add donuts.bmp to the project. (Select Files of Type Image Files, and then locate file at C:\HOL320\Image.)

  8. Get the properties of each resource by looking in Solution Explorer, right-clicking the resource, and then choosing Properties.

  9. Change the Build Actionvalue to Embedded Resourceto compile donuts.bmp into the assembly.

The sprite data is stored in the TileSetclass.

To add the data class TileSet
  1. Click Project| Add New Item.

  2. In the Add New Itemdialog box, add a new class.

  3. Name the new class TileSet.cs.

  4. Delete all of the code in the new class.

  5. Add the following code to the new class.

    Copy Code
    using System;
    using Microsoft.WindowsMobile.DirectX;
    using Microsoft.WindowsMobile.DirectX.Direct3D;
    
    namespace SpriteLab
    {
    	public class TileSet
    	{
    		private Texture texture;
    		//Returns the sprite texture
    		public Texture Texture
    		{
    			get
    			{
    				return texture;
    		}
    	}
    		private int xOrigin;
    		//Returns the x starting location
    		public int XOrigin
    		{
    			get
    			{
    				return xOrigin;
    		}
    	}
    		private int yOrigin;
    		//Returns the y starting location
    		public int YOrigin
    		{
    			get
    			{
    				return yOrigin;
    		}
    	}
    		private int numberFrameRows;
    		//Returns the number of frames in a row
    		public int NumberFrameRows
    		{
    			get
    			{
    				return numberFrameRows;
    		}
    	}
    		private int numberFrameColumns;
    		//Returns the number of frames in a column
    		public int NumberFrameColumns
    		{
    			get
    			{
    				return numberFrameColumns;
    		}
    	}
    		private int xExtent;
    		//Returns the x coordinate for the center of the sprite 
    		public int ExtentX
    		{
    			get
    			{
    				return xExtent;
    		}
    	}
    
    		private int yExtent;
    		//Returns the y coordinate for the center of the sprite 
    		public int ExtentY
    		{
    			get
    			{
    				return yExtent;
    		}
    	}
    
    		//Class constructor
    		public TileSet(Texture tex, int StartX, int StartY, int
    RowCount, int ColumnCount, int xWidth, int yHeight)
    		{
    			xOrigin = StartX;
    			yOrigin = StartY;
    			xExtent = xWidth;
    			yExtent = yHeight;
    			numberFrameRows = RowCount;
    			numberFrameColumns = ColumnCount;
    			texture = tex;
    	}
    }
    }
    
To create the SpriteLab class code that will render one sprite
  1. Click Project| Add New Item.

  2. On the Add New Itemdialog box, add a new code file.

  3. Name the new class SpriteLab.cs.

  4. Add the following code to the new class.

    Copy Code
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using Microsoft.WindowsMobile.DirectX;
    using Microsoft.WindowsMobile.DirectX.Direct3D;
    using System.Reflection;
    
    namespace SpriteLab
    {
    	// The main class for this sample
    	public class CreateDevice : Form
    	{
    		// Global variables for this project
    		Device device = null;   //MD3DM Device
    		Texture texture = null; //Sprite bmp
    		Rectangle tilePosition; //Location of tile
    		TileSet tileSet = null; //Local TileSet
    		Sprite sprite; 	//Sprite Varible 
    		Int16 countX = 0;  //Count to Track Columes of Tiles
    		Int16 countY = 0;  //Count to Track Rows of Tiles
    		Vector3 spritePosition = new Vector3(50, 50, 0); //Start
    Location of Sprite
    		Vector3 spriteCenter = new Vector3(0, 0, 0);  //Sprite
    Center, 0,0,0 
    		Vector2 spriteVelocity = new Vector2(1, 1); // x,y
    velocity
      float scale = 1; 		//Configure Scale for screen size
    
      //Implementation here
    
    }
    }
    
  5. Under //Implementation here, add the following code.

    Copy Code
    public CreateDevice()
    		{
    			// Set the caption
    			this.Text = "Sprite Sample";
    			this.MinimizeBox = false;
    // Add Key Event Handler here
    	}
    
  6. Under the CreateDeviceclass, add the following code.

    Copy Code
    public bool InitializeGraphics()
    		{
    			try
    			{
    				// Set up the D3D parameters
    				PresentParameters presentParams = new
    PresentParameters();
    
    				// Causes the display to appear in a window rather
    than
    				// full screen
    				presentParams.Windowed = true;
    
    				// When a new frame is swapped to the front buffer,
    				// the old frame will be discarded
    				presentParams.SwapEffect = SwapEffect.Discard;
    
    			// The first parameter of 0 indicates that the Device
    object
    			// should use the system's physical adapter. The second
    parameter 
    			// identifies the device type. When working with D3DM,
    the only 
    			// supported device type is the default. The third
    parameter is a 
    			// reference to the current form which will be doing
    the 
    			// rendering.The forth parameter, CreateFlags, allows
    you to set 
    			// various options for the device. The final parameter,
    
    			// presentParams, contains the details about how the
    image will 
    			// be displayed in the render area, what buffers it
    will use, and 
    			// the formats it will have. 
    		device = new Device(0, DeviceType.Default, this,
    CreateFlags.None, presentParams);
    				device.DeviceReset += new EventHandler(
    					this.OnResetDevice);
    				this.OnResetDevice(device, null);
    		}
    			catch (DirectXException)
    			{
    				return false;
    		}
    			return true;
    	}
    
  7. Under InitializeGraphics, add the following code.

    Copy Code
    void OnResetDevice(object sender, EventArgs e)
    		{
    			Device dev = (Device)sender;
    			//Create sprite object on device
    			sprite = new Sprite(dev);
    			//Get the donuts resource out of the assembly and
    assign to
    			//texture
    			//Default parameters for TextureLoader.FromStream 
    //(device, stream,D3DX.Default, D3DX.Default, D3DX.Default, 
    // D3DX.Default, Usage.None, Format.Unknown,
    // Pool.VideoMemory,(Filter)D3DX.Default, (Filter)D3DX.Default, 0)
    			//Load texture from the resource, and set the color
    black as the
    			//alpha blended color
    			texture = TextureLoader.FromStream(dev,
    Assembly.GetExecutingAssembly()
    .GetManifestResourceStream("Lab4.donuts.bmp"), 
    D3DX.Default, D3DX.Default, D3DX.Default, D3DX.Default, 
    Usage.None, Format.Unknown, Pool.VideoMemory, (Filter)D3DX.Default,
    (Filter)D3DX.Default, Color.Black.ToArgb());
    			//Configure TileSet to the size of tile in bmp
    			tileSet = new TileSet(texture, 0, 0, 6, 5, 32, 32);
    			//Set tilePosition including the offset to the center
    of the 
    			//sprite
    			tilePosition = new Rectangle(tileSet.XOrigin, 
    tileSet.YOrigin, tileSet.ExtentX * 2, tileSet.ExtentY * 2);
    
    			//Add a call to Calcualte Scale here
    	}
    
  8. Add the following code to render the sprite.

    Copy Code
    private void Render()
    		{
    
    			//Clear the back buffer to a blue color 
    			device.Clear(ClearFlags.Target,
    System.Drawing.Color.BlueViolet,
    				1.0f, 0);
    
    			//Begin the scene
    			device.BeginScene();
    
    			sprite.Begin(SpriteFlags.AlphaBlend);
    
    //Add transform here 
    
    		
    			//Draw a sprite at the current position 
    			sprite.Draw(tileSet.Texture, tilePosition, 
    spriteCenter, spritePosition, Color.White.ToArgb());
    			sprite.End();
    
    
    			//End the scene
    			device.EndScene();
    			device.Present();
    
    			//rotateSprite code here
    		
    			//moveSprite code here
    		 
    }
    
  9. Add the following code for OnPaint, OnPointBackgroundand Main, which finishes the sample.

    Copy Code
    // Called to repaint the window
    		protected override void OnPaint(PaintEventArgs e)
    		{
    			// Render on painting
    			this.Render();
    
    			// Render again
    			this.Invalidate();
    	}
    
    		// Called to repaint the window's background
    		protected override void OnPaintBackground(PaintEventArgs e)
    		{
    			// Do nothing to ensure that the rendering area is not
    overdrawn
    	}
    
    
    		static void Main()
    		{
    			CreateDevice frm = new CreateDevice();
    
    			// Initialize Direct3D
    			if (!frm.InitializeGraphics())
    			{
    				MessageBox.Show("Could not initialize Direct3D. " +
    					"This tutorial will exit.");
    				return;
    		}
    
    			Application.Run(frm);
    	}
    
To compile and deploy the managed D3DM project
  1. Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.

  2. On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.

  3. Click Deploy. Visual Studio deploys the project.

  4. Click Yeswhen the device prompts you to accept the project from an unknown publisher.

  5. On the managed D3DM device, click OKto close it.

Exercise 2: Animating a Sprite

In this exercise, you will move from tile to tile with each render loop, which makes the donut appear to spin.

To rotate the sprite
  1. Add the following rotateSpritefunction above the Mainfunction.

    Copy Code
     private void rotateSprite()
    		{
    			//Change the count to move to the next sprite tile
    			if (++countX > 4)
    			{
    				countX = 0;
    				if (++countY > 5)
    				{
    					countY = 0;
    			}
    		}
    			//Set the coordinates for the current tile
    			tilePosition.X = tileSet.XOrigin + (countX *
    tileSet.ExtentX * 2);
    			tilePosition.Y = tileSet.YOrigin + (countY *
    tileSet.ExtentY * 2);
    	}
    
  2. Replace //rotateSpritecode here with the following code to call rotateSpritefrom the Renderfunction.

    Copy Code
    rotateSprite();
    
To compile and deploy the managed D3DM project
  1. Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.

  2. On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.

  3. Click Deploy. Visual Studio deploys the project.

  4. Click Yeswhen the device prompts you to accept the project from an unknown publisher.

  5. On the managed D3DM device, click OKto close it.

Exercise 3: Moving a Sprite

In this exercise, you will move the sprite around the screen. You will move the sprite location based on an x and y velocity set by using the direction keys.

To move the sprite
  1. Above the Mainfunction, add the following function to move the sprite.

    Copy Code
    		private void moveSprite()
    		{
    		
    			//Add collision logic here
    
    			//Advance sprite by adding to its position the velocity
    		 
    			spritePosition.X += spriteVelocity.X;
    			spritePosition.Y += spriteVelocity.Y;
    
    //Add calculate sprite center here
    		
    	}
    
  2. Replace //moveSpritecode here with the following code to add the moveSpritefunction to the Renderfunction.

    Copy Code
    moveSprite();
    
  3. Above the Mainfunction, add the following code to change the spriteVelocityby using the navigation pad.

    Copy Code
    private void CreateDevice_KeyDown(object sender, KeyEventArgs e)
    		{
    			//Use rocker to modify the velocity 
    			if ((e.KeyCode == System.Windows.Forms.Keys.Up))
    			{
    				// Rocker Up
    				// Up
    				spriteVelocity.Y -= 1;
    		}
    			if ((e.KeyCode == System.Windows.Forms.Keys.Down))
    			{
    				// Rocker Down
    				// Down
    				spriteVelocity.Y += 1;
    
    		}
    			if ((e.KeyCode == System.Windows.Forms.Keys.Left))
    			{
    				// Left
    				spriteVelocity.X -= 1;
    		}
    			if ((e.KeyCode == System.Windows.Forms.Keys.Right))
    			{
    				// Right
    				spriteVelocity.X += 1 + 1;
    
    		}
    
      }
    
  4. Replace // Add Key Event Handler herewith the following code to add the navigation pad event handler to the CreateDevicefunction.

    Copy Code
    this.KeyDown += new
    System.Windows.Forms.KeyEventHandler(this.CreateDevice_KeyDown);
    
To compile and deploy the managed D3DM project
  1. Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.

  2. On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.

  3. Click Deploy. Visual Studio deploys the project.

  4. Click Yeswhen the device prompts you to accept the project from an unknown publisher. You should see the blue managed D3DM device with the rotating donut. You can use the navigation pad to move it around.

  5. On the managed D3DM device, click OKto close it.

Exercise 4: Detecting Collisions

You will notice from the last procedure that the donut moves off the screen and keeps going. In this exercise, you add will code to detect collisions with walls and change the velocity of the donut.

To detect walls and change the velocity by 90 degrees
  • Replace //Add collision logic herewith the following collision code to add it to the moveSpritefunction.

    Copy Code
    			//Simple collision detection with end of screen.
    
    			if ((spritePosition.X * scale) > (this.Width -
    (tileSet.ExtentX * 2 *	scale)) || (spritePosition.X * scale)
    < 0)
    			{
    				//If the sprite hits either the left or right side
    of screen, 
    				//provide the reciprocal velocity   
    				spriteVelocity.X *= -1;
    		}
    
    
    			if ((spritePosition.Y * scale) > (this.Height -
    (tileSet.ExtentY * 2 * scale)) || (spritePosition.Y * scale) <
    0)
    			{
    				//If the sprite hits either the top or bottom of
    the screen, 
    				//provide the reciprocal velocity	 
    				spriteVelocity.Y *= -1;
    
    		}
    
To compile and deploy the managed D3DM project
  1. Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.

  2. On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.

  3. Click Deploy. Visual Studio deploys the project.

  4. Click Yeswhen the device prompts you to accept the project from an unknown publisher. You should see the blue managed D3DM device with the rotating donut. You can use the navigation pad to move the donut around.

  5. On the managed D3DM device, click OKto close it.

Exercise 5: Scaling a Sprite According to Screen Size

The donut image is created for a VGA screen with a screen resolution of 640 x 480. But not all devices have a VGA resolution. In this exercise, you will use a transform to modify the size of the donut according to the screen size.

To scale the donut to the current screen
  1. Above the Mainfunction, add the calculateScalefunction.

    Copy Code
    		private float calculateScale()
    		{
    			//Donunts.bmp is drawn for a VGA resolution. If the
    device is not
    			//VGA resolution, provide a scale to modify the image.
    			float vgaWidth = 480;
    
    			return this.Width / vgaWidth;
    	}
    
  2. Replace //Add call to calculate scale herewith the following code.

    Copy Code
    scale = calculateScale();
    
  3. Replace //Add calculate sprite center herewith the following code. Transforms need the sprite center calculated.

    Copy Code
    			spriteCenter.X = spritePosition.X + tileSet.ExtentX;
    			spriteCenter.Y = spritePosition.Y + tileSet.ExtentY;
    
  4. Replace //Add transform herewith the following code to add the transform to the Renderfunction.

    Copy Code
    sprite.Transform = Matrix.Translation(spriteCenter) *
    Matrix.Scaling(scale, scale, 1.0f);
    
To compile and deploy the managed D3DM project
  1. Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.

  2. On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.

  3. Click Deploy. Visual Studio deploys the project.

  4. Click Yeswhen the device prompts you to accept the project from an unknown publisher. You should see the blue managed D3DM device with the rotating donut. You can use the navigation pad to move it around.

  5. On the managed D3DM device, click OKto close it.

Conclusion

In this lab, you performed the following exercises:

  • Rendering a static sprite

  • Animating a sprite

  • Moving a sprite

  • Detecting collisions

  • Scaling a sprite according to screen size