
Lab 4: Create a Simple Two-Dimensional Sprite Casual Game
Traditional two-dimensional casual games are based on animated sprites. Managed D3DM offers a Sprite class 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 Sprite class. The Sprite class 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 Sprite class 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
-
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 Project menu, click Add Reference.
-
Add the following references:
-
Microsoft.WindowsMobile.DirectX
-
System.Drawing
-
System.Windows.Forms
-
System
-
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 Action value to Embedded Resource to compile donuts.bmp into the assembly.
The sprite data is stored in the TileSet class.
To add the data class TileSet
-
Click Project | Add New Item.
-
In the Add New Item dialog 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.
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
-
Click Project | Add New Item.
-
On the Add New Item dialog box, add a new code file.
-
Name the new class SpriteLab.cs.
-
Add the following code to the new class.
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.
public CreateDevice()
{
// Set the caption
this.Text = "Sprite Sample";
this.MinimizeBox = false;
// Add Key Event Handler here
}
-
Under the CreateDevice class, add the following 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.
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.
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, OnPointBackground and Main, which finishes the sample.
// 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
-
Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.
-
On the Deploy dialog box, select Windows Mobile 5.0 PocketPC Device.
-
Click Deploy. Visual Studio deploys the project.
-
Click Yes when the device prompts you to accept the project from an unknown publisher.
-
On the managed D3DM device, click OK to 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
-
Add the following rotateSprite function above the Main function.
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 rotateSprite from the Render function.
To compile and deploy the managed D3DM project
-
Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.
-
On the Deploy dialog box, select Windows Mobile 5.0 PocketPC Device.
-
Click Deploy. Visual Studio deploys the project.
-
Click Yes when the device prompts you to accept the project from an unknown publisher.
-
On the managed D3DM device, click OK to 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
-
Above the Main function, add the following function to move the sprite.
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 moveSprite function to the Render function.
-
Above the Main function, add the following code to change the spriteVelocity by using the navigation pad.
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 CreateDevice function.
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.CreateDevice_KeyDown);
To compile and deploy the managed D3DM project
-
Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.
-
On the Deploy dialog box, select Windows Mobile 5.0 PocketPC Device.
-
Click Deploy. Visual Studio deploys the project.
-
Click Yes when 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 OK to 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
To compile and deploy the managed D3DM project
-
Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.
-
On the Deploy dialog box, select Windows Mobile 5.0 PocketPC Device.
-
Click Deploy. Visual Studio deploys the project.
-
Click Yes when 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 OK to 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
-
Above the Main function, add the calculateScale function.
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.
scale = calculateScale();
-
Replace //Add calculate sprite center here with the following code. Transforms need the sprite center calculated.
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 Render function.
sprite.Transform = Matrix.Translation(spriteCenter) * Matrix.Scaling(scale, scale, 1.0f);
To compile and deploy the managed D3DM project
-
Press F5 to compile and run the application. If any compilation issues occur, you need to fix them.
-
On the Deploy dialog box, select Windows Mobile 5.0 PocketPC Device.
-
Click Deploy. Visual Studio deploys the project.
-
Click Yes when 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 OK to close it.