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. |
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 installDirectX 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 theVisual 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 installActiveSync 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.
Lab 1: Create a Managed D3DM Device
Lab 2: Create a Spinning Triangle with Managed D3DM
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.
-
In Visual Studio 2005, click File| New| Project.
-
On the New Projectdialog box, open a blank C# project and select Smart Device| Windows Mobile 5.0 Pocket PC.
-
On the Projectmenu, click Add Reference.
-
Add the following references to the project:
- Microsoft.WindowsMobile.DirectX
- System.Drawing
- System.Windows.Forms
- System
- Microsoft.WindowsMobile.DirectX
-
Click Project| Add New Item.
-
In the Add New Itemdialog box, delete all the code in the new class.
-
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 } }
-
Replace
// CreateDevice
here 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; }
-
Initialize the managed D3DM subsystem by adding InitializeGraphics. Replace
//InitializeGraphics
here 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; }
-
Set up the render logic to draw each frame with the color of blue. Replace
// Render
here 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(); } }
-
Create a game loop by overriding OnPaint. Replace
//OnPaint
here with the following code.Copy Code protected override void OnPaint(PaintEventArgs e) { // Render on painting this.Render(); // Render again this.Invalidate(); }
-
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 }
-
Add OnKeyPressto detect when the user presses the ESC to exit the application. Replace
//OnKeyPress
here 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(); }
-
Create Mainto launch the application. Replace
//Main
here 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); }
-
Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.
-
On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.
-
Click Deploy. Visual Studio deploys the project.
-
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.
-
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.
-
Modify the global variables in the CreateDeviceclass to include a VertexBuffervariable. Replace
// The global variables for this project
with the following code.Copy Code VertexBuffer vertexBuffer = null; PresentParameters presentParams = new PresentParameters();
-
Change the form text in the CreateDevicefunction. Replace
this.Text = "Hello World";
with the following code.Copy Code this.Text = "Spinning Tringle";
-
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);
-
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); }
-
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; }
-
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(); }
-
Modify Renderto draw the TriangleList. Replace
// Rendering of the scene objects can happen here
with the following code.Copy Code device.SetStreamSource(0, vertexBuffer, 0); device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
-
Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.
-
On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.
-
Click Deploy. Visual Studio deploys the project.
-
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.
-
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.
-
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); }
-
Call SetupMatrices, as shown in the following code, from the Renderfunction by adding a call to it just after the BeingScene.
Copy Code SetupMatrices();
-
Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.
-
On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.
-
Click Deploy. Visual Studio deploys the project.
-
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.
-
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.
-
Open a Command Promptwindow (click Start| Run, and then type cmd).
-
Type cd c:.
-
Type cd C:\HOL320\Tools\.
-
Type MeshConvertercs.exe Tiger.x Tiger.md3dmto convert the Tiger.x file to Tiger.md3dm.
-
In Visual Studio 2005, click File| New| Project.
-
In the New Projectdialog box, open a new C# project, and then select SmartDevices| Windows Mobile 5.0 Pocket PC.
-
Add an empty project, and name it Lab3. (The project name is referenced in the code.)
-
On the Projectmenu, click Add Reference.
-
Add the following references:
- Microsoft.WindowsMobile.DirectX
- System.Drawing
- System.Windows.Forms
- System
- Microsoft.WindowsMobile.DirectX
-
Click Project| Add Existing Item.
-
Click Add Resource| Add Existing File.
-
Change Files of Typeto All Files.
-
Change the Look Invalue to C:\HOL320\Tools\.
-
Add Tiger.md3dmand Tiger.bmp(holding down SHIFT and clicking the left mouse button selects multiple files).
-
Get the properties of each resource by looking in Solution Explorer, right-clicking the resource, and then choosing Properties.
-
Change the Build Actionvalue to Embedded Resourceto compile these resources into the assembly.
-
Click Project| Add Existing Item.
-
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.
-
Click Project| Add New Item.
-
On the Add New Itemdialog box, add a new code file.
-
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;
-
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.
-
Replace
//InitializeGraphics here
by 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; }
-
Replace
//Add OnDeviceReset
by adding the following code.Note: GetManifestResourceStream
starts 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])); } }
-
Replace
//SetupMatrices here
by 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); }
-
Replace
//Render here
with 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(); }
-
Replace
//OnPaint here
with 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(); }
-
Replace
//OnPaintBackGround here
with 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 }
-
Replace
//OnKeyPress here
with 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(); }
-
Replace
//OnResize here
with the following code.Copy Code protected override void OnResize(EventArgs e) { base.OnResize(e); }
-
Replace
//Main here
with 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); } }
-
Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.
-
On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.
-
Click Deploy. Visual Studio deploys the project.
-
Click Yeswhen the device prompts you to accept the project from an unknown publisher.
-
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.
-
In Visual Studio 2005, click File| New| Project.
-
In the New Project dialog box, open a new C# project, and then select SmartDevices| Windows Mobile 5.0 Pocket PC.
-
Name the project Lab4.
-
On the Projectmenu, click Add Reference.
-
Add the following references:
- Microsoft.WindowsMobile.DirectX
- System.Drawing
- System.Windows.Forms
- System
- Microsoft.WindowsMobile.DirectX
-
Click Project| Add Existing Item.
-
Add donuts.bmp to the project. (Select Files of Type Image Files, and then locate file at C:\HOL320\Image.)
-
Get the properties of each resource by looking in Solution Explorer, right-clicking the resource, and then choosing Properties.
-
Change the Build Actionvalue to Embedded Resourceto compile donuts.bmp into the assembly.
The sprite data is stored in the TileSetclass.
-
Click Project| Add New Item.
-
In the Add New Itemdialog box, add a new class.
-
Name the new class TileSet.cs.
-
Delete all of the code in the new class.
-
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; } } }
-
Click Project| Add New Item.
-
On the Add New Itemdialog box, add a new code file.
-
Name the new class SpriteLab.cs.
-
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 } }
-
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 }
-
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; }
-
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 }
-
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 }
-
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); }
-
Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.
-
On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.
-
Click Deploy. Visual Studio deploys the project.
-
Click Yeswhen the device prompts you to accept the project from an unknown publisher.
-
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.
-
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); }
-
Replace
//rotateSprite
code here with the following code to call rotateSpritefrom the Renderfunction.Copy Code rotateSprite();
-
Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.
-
On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.
-
Click Deploy. Visual Studio deploys the project.
-
Click Yeswhen the device prompts you to accept the project from an unknown publisher.
-
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.
-
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 }
-
Replace
//moveSprite
code here with the following code to add the moveSpritefunction to the Renderfunction.Copy Code moveSprite();
-
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; } }
-
Replace
// Add Key Event Handler here
with 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);
-
Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.
-
On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.
-
Click Deploy. Visual Studio deploys the project.
-
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.
-
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.
-
Replace
//Add collision logic here
with 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; }
-
Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.
-
On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.
-
Click Deploy. Visual Studio deploys the project.
-
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.
-
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.
-
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; }
-
Replace
//Add call to calculate scale here
with the following code.Copy Code scale = calculateScale();
-
Replace
//Add calculate sprite center here
with the following code. Transforms need the sprite center calculated.Copy Code spriteCenter.X = spritePosition.X + tileSet.ExtentX; spriteCenter.Y = spritePosition.Y + tileSet.ExtentY;
-
Replace
//Add transform here
with the following code to add the transform to the Renderfunction.Copy Code sprite.Transform = Matrix.Translation(spriteCenter) * Matrix.Scaling(scale, scale, 1.0f);
-
Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.
-
On the Deploydialog box, select Windows Mobile 5.0 PocketPC Device.
-
Click Deploy. Visual Studio deploys the project.
-
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.
-
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