Don't believe them. Games programmers, that is.
They moan about how hard it is to make games in today's world.
They spout off almost-unimaginable figures of how much games cost to make, blissfully unaware that the figures they bandy about so easily dwarf the GDP of some smaller countries.
And then of course, they complain about how high the piracy rate is, which apparently 'costs the industry more money than Microsoft makes in a year', thus somehow justifying DRM that's more invasive than being strip-searched at Heathrow.
Listen carefully, for we shall say this only once: making games is easy. Really easy. And no, we don't mean using numpty tools clicking on buttons to 'make' simple little 2D games. We mean making full-blown 3D games with physics, networking, sound effects and more. I'm talking vertex shaders, pixel shaders, particle systems, multithreading, peer-to-peer games that work on any modern Windows PC – and can even work on Xbox 360 if you're so inclined.
All these features are possible thanks to a magic piece of software called XNA, which stands – cunningly enough – for XNA's Not Acronymed. XNA is a very thin piece of programming created by Microsoft, and it sits directly on top of DirectX. If you've ever tried to program with DirectX before, you'll know that it's an absolute nightmare… But XNA is different.
If you've never programmed at all before, then XNA will save you years of hard work, because it's designed to make it easy to drop in all the features that people want in modern games.
Yes, it does mean programming things. But on the flip side, that means you have complete creative control over your game – you can make everything from Frogger to Halo 3 if you have the talent around, because everything that DirectX can do, XNA can do, too.
You'll need this
Before you unleash your brain to code the game you've been plotting for years (and don't try to deny it – every real gamer has a dream game idea they've been nursing), you need to install some software. Don't worry, it's free: Microsoft very kindly enables just about all the XNA functionality on Windows for no charge.
If you want to take your game and run it on an Xbox 360, which enables support for playing online using Xbox Live, you need to pay a small annual fee to Microsoft. However, if you pay that fee, you also gain the right to sell your game on the Xbox Live Marketplace; Microsoft acts as your publisher and gives you a 70 per cent cut of all the money your game makes.
That's all the software you need to create your games, but if you want to run them on other computers you need to have those people download and install the XNA 3.0 redistributable – that includes only the bits required to play XNA games, not to make them.
You may also need to install the .NET Framework but a lot of people already have that installed. .NET 3.5 (the latest version) comes with Visual C# 2008, so you don't need it if you've already installed Visual C#.
So, that's the software sorted out. In terms of hardware, remember that XNA is built on top of DirectX 9.0c – in order for a PC to play games you make (even simple ones), it must fully support DX9.
It should also support – at the absolute minimum – shader model 2.0, which is any card marketed as supporting DX9. You can get away with cards that support only shader model 1.1, but it will limit you if you want to do more advanced effects.
If you've got high-end hardware capable of DX10 or later, don't get carried away – XNA is designed to be compatible with both Windows and X360, which means the most you should aim for is the Xbox's curious superset of shader model 3.0.
Once you have the right software (that will take a little time) and the right hardware (only antediluvian PCs are ruled out here), you're all set to code.
Wait… How do you code?
We get asked this question a lot: "What's the best way to start programming?" Some people like to buy books. Some people like to get a computer games programming degree. But they are – and we don't want to put too fine a point on this – stupid.
You don't read books if you want to learn to ride a bike. You don't need a degree to play GTA4 (although it might take one to get the damn thing working). So if you think programming is different, you're wrong: the best way to learn to code is to just to dive in. Steal code from other people. Copy and paste stuff, then edit it a little to get what you want. Try things out, because if they don't work you've lost nothing.
So, in this tutorial we're not going to get bogged down talking about theory. And we're not going to explain to you what every line of code does, because, quite frankly, it's irrelevant. Go with the flow; you'll pick up the theory later. For now, dive in: we're going to produce a simple little top-down shooter called Bang.
The player will control a spaceship, and asteroids will fly around the screen begging to be shot. All the source code for this project can be downloaded from the PC Format website. To get started, go into the Bang folder and double-click on the file Bang.sln.
Visual C# 2008 Express Edition (VC# from on) will start and load the project for editing. If you get a Windows message box saying something like 'Windows cannot open the file Bang.sln', then you must have skipped over the 'install Visual C#' step – go back and try again.
VC# is an incredibly powerful development environment. In this one program you can write all your code, debug it and deploy it to your Xbox. Don't worry about debugging for now – a wise man once said that debugging is harder than coding, so if you write your code as cleverly as you possibly can, then you are – by definition – not smart enough to debug it.
Once VC# has loaded, you'll see all the source code for our game. It totals 300 lines, but that includes empty and almost-empty lines. For now, go to the Debug menu and click Start Debugging: this will start the game up and you should be able to play it.
The keys we've used are WSAD to move the player, with the cursor keys to aim lasers. OK, now stop playing. No, really, stop – it's time to take a look at how the program works.
Behind the curtain
When you create a blank XNA project using the File > New Project menu, VC# writes a little bit of code for you – just enough to get you a blank window with a pale blue background.
It creates five basic pieces of code for you: Initialize(), LoadContent(), UnloadContent(), Update() and Draw(). These are known as methods, which is a neat little piece of coder jargon designed to fool people into thinking programming is hard.
These five methods are magic because they get called for you by XNA:
Initialize() gets called when your game starts up.
LoadContent() is called when DirectX is ready to start loading game data (pictures, sound, etc).
UnloadContent() is called when your game is ending and you need to clean up after yourself. You can ignore this.
Update() is called every tick so you can make changes to your game world.
Draw() is called every tick so you can draw your game world to the screen.
Of course, that raises another question: just what is a tick? Think about it this way: your computer is doing all sorts of things behind your back.
In the case of the Xbox 360, it's managing RAM, it's checking whether your friends are online and it's busy calculating when would be the most annoying time to show you its Red Ring of Death. Your game has to play nicely with all the other things the computer is doing, which means it only has control for part of the time.
What happens is that your PC says: 'OK, Bang – go ahead and update yourself. Now wait a nanosecond while I finish downloading this page in Firefox. OK, I'm done; go ahead and update yourself again.'
Those 'update yourself' parts are ticks: the bits where you have control. They can happen once a second, a hundred times a second or even more, depending on how much work you do in your Update() and Draw() methods.
As soon as your game starts, XNA starts calling Update() then Draw(), Update() then Draw(), and will continue calling those two methods until your game finishes: either when players click the Close button in Windows, chooses the Return to Dashboard option on the 360, or you write some code to tell the game to quit.
Alternatively, your game will also quit if it crashes, but that only happens if you write bad code. And you don't write bad code, do you?
What do you do if you want to load a texture into your game? What about something trickier, like a font? Or, trickier still, a 3D model?
All of this used to require lots of programming – you had to write code to read JPEGs, code to read PNGs, code to load animations, and much more. But all this is taken away from you with XNA: to load a game asset, there are now just three steps:
1. Add the asset to your solution. If you look on the right of the VC# window you'll see the Solution Explorer, which contains things like Properties, References, Content, and some files ending with .cs (that's the file extension used for XNA code). To add some game content to your solution, right-click on Content then choose Add > Existing Item then choose what you want to add. The file will automatically be copied to the Content directory for your game.
2. Tell XNA that you want to load that asset in your game. You also need to tell it what type of asset it is. If you look near the top of Game1.cs you'll see lines like 'Texture2D sfcAsteroid' – that means 'give me some space in memory that will hold a texture, and let me refer to that in my code as sfcAsteroid.' If you were wondering, 2D textures are the most common type: it's a picture with a width and a height, but no depth.
3. In the LoadContent() method, ask XNA to load the asset into the memory you requested. For example,'sfcAsteroid=Content.Load<Texture2D>("asteroid");' means 'load the asset named 'asteroid' into the texture memory reserved for me at sfcAsteroid'. XNA names assets by removing filenames' extensions then looking in the Content directory. That's it. All the work of loading JPEGs, PNGs and TGAs, as well as all the work of handling memory compression techniques such as DXTC, is ultimately boiled down to a single line of code:
Drawing the world
For a 2D game, you may think we can just draw pixels to the screen with the bitmapping method. But we' don't: DirectX doesn't really 2D much; if you've got an uber-fast 3D graphics card, why not use it? So, XNA does some magic for us: whenever we say, 'Draw this sprite in 2D, please,' XNA actually creates two triangles and maps our texture onto them in 3D space. This has several obvious advantages:
1. Your graphics card is doing all the work.
2. We can spin and scale sprites for free.
3. You can apply all sorts of pixel shader effects to your sprites.
The downside? Well, there isn't one: when we write our code, it looks like it's all done in real 2D – all the XNA wizardry is done behind the scenes. At the very least, your Draw() method should include:
GraphicsDevice.Clear(Color.Black); spriteBatch.Begin(SpriteBlendMode. AlphaBlend, SpriteSortMode. Immediate, SaveStateMode.SaveState); spriteBatch.End(); base.Draw(gameTime);
That clears the screen to black so that we don't see the stuff we drew in the last tick, then starts drawing sprites, finishes drawing sprites, and calls base. Draw().
That last part is required, because both Xbox 360 and Games for Windows have a 'guide' system built-in that can draw a user interface on top of your game. When you end your Draw() method with a call to base.Draw(), it means 'I'm done; now let the computer draw anything else it needs before this tick is over'.
What goes between the Begin() and End() call of the sprite batch is down to you. It all gets drawn in order, meaning that if you draw one sprite then another, the second sprite will be drawn on top of the first.
The reason it all has to go inside Begin() and End() is because the sprites get batched (hence the name) into one lump before being sent to the GPU, which is faster than sending individual sprites as needed.
Making a move
Every time the Update() method gets called, it's your chance to make your game world come to life. To make your game playable, you need to read and act on player input. You need to move enemies and perhaps even create new ones. You need to look for network traffic, manipulate animations, check for collision between game objects, and a whole lot more. But in this simple little game all we do is update the player, update the asteroids, update the player's lasers, then check for any collisions between lasers and asteroids.
As your game grows, you'll need to add more and more code to this Update() method, so in the example code on your disc you'll see that I've created my own little methods for handling different updating tasks – this prevents the Update() method from becoming too cluttered. There's a lot of code here, but you can understand most of it once you get your head around one particular part:
KeyboardState keys = Keyboard. GetState();
UfoVelocity.Y -= 1.0f;
UfoVelocity.Y += 1.0f;
UfoVelocity.X -= 1.0f;
UfoVelocity.X += 1.0f;
UfoVelocity *= 0.93f;
UfoVelocity = Vector2.
Clamp(UfoVelocity, new Vector2(-10.0f, -10.0f), new Vector2(10.0f, 10.0f));
UfoPosition += UfoVelocity;
Parts of that are easy to understand: 'if IsKeyDown(Keys.W)', for example, means that the rest of the line will be run by XNA only if the W key is being pressed on the keyboard.
You can see that if the key is being held down, UfoVelocity.Y has 1.0 subtracted from it – the 'f' part is short for 'floating-point', which is a fancy programmer word meaning 'a number with a decimal point in', such a 3.1.
Subtracting 1 from UfoVelocity.Y means that the player will start to move upwards, but straight after all the keypress checks is a line that multiplies the velocity by 0.93f. Multiplying a number by another number that's less than 1 has the effect of making it proportionally smaller, so this multiplication has the effect of slowing the player down as if there were some air friction.
After that, there's a call to the Vector2.Clamp() method. 'Clamping' a number means to ensure it falls within a specific range – in this example, we want to ensure that a player's velocity falls within the range -10.0f to 10.0f, otherwise they would be able to reach stupidly fast speeds.
Once the velocity has been clamped to acceptable levels, we add the player's velocity to their current position, which has the effect of moving the player as requested.
Over to you
You can add various other features to the game: asteroids are created and moved in much the same way the player is moved, you can fire lasers, and those lasers can collide with asteroids.
Try your hand at adapting the game by implementing these challenges:
Fun: Make those asteroids collide dangerously with the player.
Tricky: Make asteroids that move off the screen re-appear on the other side as if they had wrapped around.
Taxing: Make the laser recharge rather than have infinite shots.
Mayhem: Load more than one asteroid image: create different types of asteroid rather than just one type.
All code required to implement these can be figured out from existing code in your download: steal code freely, copy and paste like you mean it, then fiddle to get what you want.
XNA takes all the hard work out of making games, so you can focus on coming up with an original idea then implementing it with awesome-looking assets. Have fun!
First published in PC Format, Issue 223
Sign up for the free weekly TechRadar newsletter
Get tech news delivered straight to your inbox. Register for the free TechRadar newsletter and stay on top of the week's biggest stories and product releases. Sign up at http://www.techradar.com/register