Writing a sprite-based game
[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]
Creating a 2D action game is a rite of passage for developing on any platform.
Writing 2D games
There are lots of way to start writing 2D games: after all, the most basic requirements are only that you can display an image at a specific position on the screen and react to user input.
As an iOS developer, you may have written games using nothing more them UIImage controls, or you may have rolled your own sprite routines in OpenGL ES. When porting an app to Windows 8, there is no direct correlation between iOS and Windows technologies, and so you'll have to weigh up the pros and cons of several different approaches. For example, while games which use the XAML canvas or HTML canvas solutions are both quick and easy to develop, they may lack the performance you need for complex action. On the other hand, DirectX and C++ can appear overkill for simpler apps.
Here's a quick summary of the closest Windows 8 technology to common iOS development patterns. There's no direct match, but this will give you an idea of what's involved.
iOS Technology | Windows 8 Technology |
---|---|
UIKit (UIImage, UIButton, UILabel etc.) | XAML canvas or HTML canvas |
OpenGL ES code, with sprites rendered as quads or point sprites. | DirectX, with sprites rendered as textures.
ANGLE for Windows Store. |
SpriteKit | DirectX, with sprites rendered as textures. |
Third party framework, such as Cocos2D. | Third party framework, such as Cocos2D-X. |
Third party game authoring tool, such as Unity3D. | Third party game authoring tool, such as Unity3D. |
Introducing MonoGame
MonoGame is a good solution for those coming from iOS development looking for a basic sprite library. MonoGame is an open source C# wrapper for DirectX, designed to make it easy to write 2D sprite-based games. It offers a good balance between performance and ease-of-use.
If you have previous experience writing casual games for Windows, Windows Phone or Xbox, you probably know about the XNA game framework. XNA is no longer supported on Windows or Windows Phone, but MonoGame is attempting to fill the gap. MonoGame was originally conceived to be a cross-platform version of XNA. Now, MonoGame lets you finish any existing XNA projects you may have, but also write a game from scratch for Windows, and have it run on Windows Phone, iOS and Android.
Building an app with MonoGame
MonoGame supports Visual Studio Express editions, so it's completely free to start writing sprite-based games for Windows 8. with Once you have installed MonoGame, Visual Studio will offer several new project templates. For best performance, use the MonoGame Windows Store Project template. However, if you would like to make use of XAML controls (perhaps to provide text overlays, buttons or other controls) you can also use a MonoGame Windows Store (XAML) Project.
The C# project created by the template is easy to understand, and creates several methods for you to implement, including LoadContent(), Update(), and Draw().
MonoGame will render sprites for you, however there is a catch. In order to draw the images, MonoGame expects them in a format called .xnb. You cannot simply include PNG files and expect them to render. Back in the days of XNA, a content pipeline approach allowed your project to contain PNGs, and the .xnb files were created automatically. MonoGame now supports its own content pipeline (see this page on GitHub for information), or use the following technique:
Install Visual Studio 2012 Express for Phone, as this still supports building XNA apps for Windows Phone 7. Yes, the process feels a little clunky at first, but it works. All you need to do is create a new Windows Phone 7 XNA project, drop in your PNG artwork, build the project (you don't need to run it, building is enough) and then copy the .xnb files into your new Windows 8 project. The same approach is used for sound effects and shaders.
Example C# code
Here is the start of a game in which the player's sprite must bump into target sprites and destroy them for points. It's going to change the world of gaming. First of all, we create a list to store the locations of the target sprites, and a variable to store the location of the player's object:
private List<Vector2> ball_locations;
private Vector2 player;
Then we initialize them in the Initialize() method:
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
ball_locations = new List<Vector2>();
for (float y = 40; y < 700; y += 60)
for (float x = 100; x < 500; x += 60)
{
ball_locations.Add(new Vector2(x,y));
}
player = new Vector2(1000, 400);
}
If you hadn't guessed, Vector2 is a new data type which contains X and Y co-ordinates. Together with Vector3, it's extremely useful when writing games!
In the LoadContent() method, we load the .xnb files which contain the images we need. These .xnb files have been built in a separate Windows Phone XNA project, as mentioned earlier. In this example, we use two images: a star field image for the background, and a single white ball image. MonoGame allows images to be tinted as they are drawn, so we don't need to create a ball of every possible color.
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
_spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
_backgroundTexture = Content.Load<Texture2D>("starfieldImage");
_ball = Content.Load<Texture2D>("ballImage");
}
Now we get to draw our objects. MonoGame, like XNA, uses an object called a SpriteBatch to render the sprites. You must create a SpriteBatch, and then call its Begin() and End() methods, with the sprites drawn in between. It's also important to clear the screen every frame, and so in this example the star field image is drawn to fill the entire screen.
protected override void Draw(GameTime gameTime)
{
_spriteBatch.Begin();
// Draw backgound (also clears screen)
_spriteBatch.Draw(_backgroundTexture, GraphicsDevice.Viewport.Bounds, Color.White);
// Draw the target balls in alternating colors
int i = 0;
foreach (Vector2 v in ball_locations)
{
switch (i)
{
case 0: _spriteBatch.Draw(_ball, new Rectangle((int)v.X, (int)v.Y, 50, 50), Color.Red); break;
case 1: _spriteBatch.Draw(_ball, new Rectangle((int)v.X, (int)v.Y, 50, 50), Color.Green); break;
case 2: _spriteBatch.Draw(_ball, new Rectangle((int)v.X, (int)v.Y, 50, 50), Color.Blue); break;
case 3: _spriteBatch.Draw(_ball, new Rectangle((int)v.X, (int)v.Y, 50, 50), Color.Yellow); break;
}
i++; if (i > 3) i = 0;
}
// Draw player's ball
_spriteBatch.Draw(_ball, new Rectangle((int)player.X, (int)player.Y, 50, 50), Color.White);
_spriteBatch.End();
base.Draw(gameTime);
}
}
}
When running, this app looks something like this:
Obviously there is still a lot of work to do! Updating the location of the various on-screen objects is done in the Update() method, which is called every frame automatically. Displaying text is also something that takes a little work: you can either opt to use a XAML project, and so overlay a TextBlock control and Button objects, or you can use the MonoGame SpriteBatch text rendering. The text rendering will be faster if you use SpriteBatch rendering, but you will need to create a font object in an XNA project, in the same way we created the .xnb images from PNG files.
If you are interested in creating games in MonoGame, the MonoGame.net website has many tutorials and help files. The book Windows 8 and Windows Phone 8 Game Development by Adam Dawes is also an excellent guide.
Related topics
From XNA to MonoGame (Gamasutra)
Code libraries, toolkits and other sources of help