Introduction
With the release of Windows Phone 7.5, the new Microsoft Phone OS is starting to get noticed in a positive way. So it’s time to take a closer look at development for the platform.
There are two programming models for user interface development on the Windows Phone OS: Silverlight and XNA.
Silverlight, the .NET Framework’s less capable sibling, provides a relatively productive ecosystem for line of business application development. Silverlight incorporates a wide range of user interface controls, and there is a growing market for third party controls, that enables us to quickly design the kind of user interfaces we want to provide for our line of business applications. If you are going to create Silverlight applications for Windows Phone 7.5, download the “Silverlight for Windows Phone Toolkit” found at http://silverlight.codeplex.com/.
XNA on the other hand enables us to write code that uses DirectX 9 to accelerate graphics output. Tasks such as video playback and graphics rendering are moved from the CPU to the GPU, freeing the CPU up to process other things.
When we developed for the initial release of Windows Phone, we had to choose between Silverlight and XNA and stick to that model. On Windows Phone 7.5, Silverlight applications can embed XNA models and XNA applications can embed Silverlight user interface elements – a huge improvement.
I’ll assume that you know your way around Visual Studio 2010, .NET and C#. You also need to install the Windows Phone Software Development Kit (SDK) 7.1 which provides you with the tools that you need to develop software for both Windows Phone 7.0 and Windows Phone 7.5 devices. The SDK includes the XNA Game Studio 4.0 Refresh so there is no need to install that separately.
Anatomy of a Game
When we are developing for XNA on Windows Phone we are working inside a framework, so it’s pretty important that we have a firm grasp on the basics.
XNA Game Studio 4.0 adds a number of project templates to Visual Studio, and the one we’re going to use is called “Windows Phone Game (4.0)” located under Visual C# -> XNA Game Studio 4.0. I called the project “AnatomyOfAGame
” and renamed the generated “Game1
” class to “GameSkeleton
”.
We really need to understand the generated code, since this is how the framework expects our game to work:
public class GameSkeleton : Microsoft.Xna.Framework.Game
{
The XNA Framework “Game
” class implements the game loop; and it provides the window which displays our game – “Game
” also contains a number of virtual methods that enables communication between our game and the XNA Framework.
GraphicsDeviceManager graphics;
The “GraphicsDeviceManager
” provides the functionality that allows us to handles the configuration and management of the graphics device.
SpriteBatch spriteBatch;
“SpriteBatch
” allow us to draw Sprites in the form of textures. Sprites are bitmaps that are drawn directly to a render target, bypassing the pipeline for transformations, lighting or effects. It’s possible to create some fairly nice games using sprites alone.
The generated constructor is fairly simple:
public GameSkeleton()
{
graphics = new GraphicsDeviceManager(this);
The first step is to create the “GraphicsDeviceManager
” for this game, and next we need to tell the “ContentManager
” where it should look for content.
Content.RootDirectory = "Content";
The “Content
” property provides access to the “ContentManager
” which is the run-time component responsible for loading managed objects from the binary files located in the “AnatomyOfAGameContent
” content project.
Content is produced at design time, and it is usually all the parts of your game that are not code; such as bitmaps, models and sound-bites. Content is added to the project through the Content Pipeline, and it’s called the Content Pipeline because it’s a set of processes that gets applied to a game's art and other data assets when the game is built. “RootDirectory
” tells the “ContentManager
” where it’s supposed to look for those resources.
TargetElapsedTime = TimeSpan.FromTicks(333333);
The “TargetElapsedTime
” specifies the target time period for the game loop for a fixed-step game. In a fixed-step game, “Update
” is called periodically as specified by “TargetElapsedTime
”, and when “Update
” has completed, the game will check to see if it’s time to call “Update
” again before calling “Draw
”. When “Draw
” has completed, the game is idle until it is time to call Update
once more.
InactiveSleepTime = TimeSpan.FromSeconds(1);
}
“InactiveSleepTime
” specifies the time to sleep when the game is inactive.
protected override void Initialize()
{
base.Initialize();
}
“Initialize
” is where we are supposed to query for any required services, and load non-graphics resources. It’s important that we call the “Initialize
” of the base class as this ensures that “Initialize
” will be called on any game components that have been added to the “Components
” collection of the game. “Initialize
” is called before the game enters the “Update
”/”Draw
” loop.
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
}
“LoadContent
” is called by “Initialize
” and at other times when the game content needs to be reloaded, such as when the “DeviceReset
” event occurs.
protected override void UnloadContent()
{
}
“UnloadContent
” is called when graphics resources need to be unloaded, and it’s where we are supposed to unload any game-specific graphics resources.
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
{
this.Exit();
}
base.Update(gameTime);
}
“Update
” is where all the excitement happens, where we move things around, check for collisions, and make our phone squeak and tremble. In short: Where we process game logic.
The argument “gameTime
” provides us with timing information through three properties:
public TimeSpan ElapsedGameTime { get; }
The amount of elapsed game time since the last update.
public bool IsRunningSlowly { get; }
“IsRunningSlowly
” indicates whether the game loop is taking longer than its TargetElapsedTime
. When this is the case our game should catch up with the delay as this allows for a smoother game experience.
public TimeSpan TotalGameTime { get; }
TotalGameTime
specifies the game time since the start of the game.
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.DarkKhaki);
base.Draw(gameTime);
}
}
“Draw
” is called by the XNA framework when it is time to draw a frame. By calling the “Draw
” method of the base class, we ensure that drawable game components are drawn too.
We have now created something that doesn’t do very much, but at least we now have an understanding of how things are supposed to work.
Farseer Physics XNA WP7
Before going further, I’d like to introduce the Farseer Physics engine, which you can download from http://farseerphysics.codeplex.com/. Farseer Physics engine is an open source 2D physics engine for .NET that can be used for commercial projects – which is quite nice.
The solution for this article includes the original, nearly unmodified, Farseer Physics Engine 3.3.1 for Windows Phone projects. The only change I’ve made is to update the projects to the Windows Phone Software Development Kit (SDK) 7.1. This by the way was achieved by simply clicking the “Upgrade Windows Phone Project” item on the project menu.
Now that we have a physics engine in place, it’s a bit easier to make our games do interesting stuff.
XNAImage – Image Processing for the XNA Framework
When you start to play around with the XNA framework and Farseer Physics, it pretty soon becomes obvious that it would be nice to create sprites at runtime. The HarlinnXNA
project includes a class named “XNAImage
” that will help us create artwork on the fly.
This class allows us to draw lines, circles, splines, bezier curves, and many other things that comes in handy when we need to render shapes for our games – and the Farseer Physics library is pretty shape oriented. We will start looking at that class, and how it can be used together with the Farseer Physics library in my next article on XNA for Windows Mobile.
XNAImage Update - 11th of November
The XNAImageIntro
project demonstrates how XNAImage
can be used to render images at runtime. XNAImage
is based on the WriteableBitmapEx project, and supports all the image manipulation features of WriteableBitmapEx
. This means that we can use the library to create textures at runtime and then assign the generated image to a texture.
texture = new Texture2D(GraphicsDevice,
rect.Width, rect.Height, false, SurfaceFormat.Color);
textureImage = new XNAImage(rect.Width, rect.Height, Color.CornflowerBlue);
When we create a Texture2D
object that we want to use with an XNAImage
- we have to specify the SurfaceFormat.Color
format so that the pixel format of the texture matches the pixel format of the XNAImage
.
Now that we have created our XNAImage
object, we can start drawing directly to the image:
Color color = Color.Green;
textureImage.FillEllipseCentered(480/3, 275, 75, 75, color);
color = Color.Blue;
textureImage.FillEllipseCentered(480*2/3, 275, 75, 75, color);
And we can create another image, and fill it with perlin noise:
XNAImage noisyImage = new XNAImage(200, 200);
noisyImage.PerlinNoise(1.2, 0.025, 0.9, 3, 5);
Perlin noise is useful when we want to create various effects like flames, smoke, and clouds in our games. The image can then be blitted to the target image like this:
textureImage.Blit(new Rectangle(140, 400, 200, 100),
noisyImage, new Rectangle(0, 0, 200, 100),BlendMode.Subtractive);
textureImage.Blit(new Rectangle(140, 500, 200, 100),
noisyImage, new Rectangle(0, 100, 200, 100));
The first blit operation, blends the source image and the target image using subtractive blending, while the second just overlays the target rectangle. Once we have completed our image, we assign it to the Texture2D
object:
texture.Assign(textureImage);
XNAImage
is a "work in progress", but it provides a number of features that are very useful for game UI development:
Blit
FillRectangle
FillEllipse
FillEllipseCentered
FillPolygon
FillQuad
FillTriangle
FillBeziers
FillCurve
FillCurveClosed
Convolute - apply image filters
PerlinNoise
DrawLineBresenham
DrawLineDDA
DrawLine
DrawLineAa
DrawPolyline
DrawTriangle
DrawQuad
DrawRectangle
DrawEllipse
DrawEllipseCentered
DrawBezier
DrawBeziers
DrawCurveSegment
DrawCurve
DrawCurveClosed
Crop
Resize
Rotate
RotateFree
Flip
In the end, XNAImage
will enable us to create images like the one at the top at the article; and if there is enough interest, this will be shared with the development community here on CodeProject. While the WriteableBitmapEx
library provided a nice initial set of features, XNAImage
has a long way to go before we have something with a reasonable API.
Game Studio 4.0 changed the Color type
According to the SurfaceFormat documentation the Texture2D
class uses a 32-bit ARGB pixel format with alpha, using 8 bits per channel when it's created with format set to SurfaceFormat.Color
.
It turns out that Microsoft forgot to update the documentation, as Game Studio 4.0 changes the Color type from BGRA to RGBA byte ordering. Most games will never notice the change, as we not only updated the Color struct, but also changed our texture and vertex declaration creation code to match. If you have code that creates Color format textures directly, setting their contents from a byte array rather than a strongly typed Color[], you will need to swap the order of your red and blue channels.
The inner workings of XNAImage
originally assumed that we were dealing with pixels in the ARGB format, so this was a bit of a surprise - as of 11th of November, this has mostly been fixed.
History
- 8th of November 2011 - Initial posting
- 9th of November 2011 -
XNAImage
bug warning - 11th of November 2011 -
XNAImage
updated - 12th of November 2011 - Made a few changes