I thought I would begin the real meat-and-two-veg of this blog with a short series of (three or four) posts describing some of the most useful, bread-and-butter tools that any XNA game needs during development. In the last post of the series, I’ll make the code available for free, for you to use, improve, and generally do with as you will.
In fact: there is absolutely no reason that the ideas and techniques I’m about to demonstrate should be limited to XNA games alone. The code I’ve written could be used in a non-XNA C# game with almost no changes, and converted to any other language with just a little effort as well. XNA and C# can do these things particularly easily due to their access to the .NET framework, but several of these techniques were inspired by tools I’ve used on previous projects that didn’t use .NET and didn’t always run on Windows. As if that’s not enough, I’d go further – there’s no reason games projects should be the only ones to benefit from this stuff. Any non-trivial software development effort would be made easier using techniques and tools like these.
I’ve entitled this mini-series “Efficient Development” to give a flavour of what I’m trying to achieve with this; I’d have used “Agile Development” but that has a very specific, well-defined meaning (even if no-one seems to agree on what that meaning is). Nevertheless, this is all very much in the spirit of Agile Development in the abstract – ways to work on software with minimal time wasted in recompiling, restructuring, and generally wrestling with the code. Having used techniques very similar to some of these ideas before – and thought “wouldn’t it be great if” for others – I knew before I wrote a single line of XNA that getting this stuff together would be mega handy, because it would make my coding life easier and save me a bunch of headaches later. When you might only get ten hours a week (or fewer!) to work on your game, you want to spend as little of it as possible faffing around.
Below you can see a screenshot from a tool I’ve developed for viewing models, imaginatively called the Modelviewer. XNA supports a wide range of model formats and it’s easy enough to write converters for your own custom types. With the Modelviewer, I can download models from the internet, or build my own, and very easily examine them (either using the Modelviewer as a standalone tool or a mode in another game). As my code develops, I will add features to it such as animations, particles, sound editing etc.
It’s pretty handy to be able to check out models in this way. But that’s not the focus of this article (useful though it is). Instead – let’s imagine I’ve downloaded this model and I want to use it in my game. But, maybe, I want to get a better idea of exactly how many polygons are involved. (The XNA Model class can give me a number, but suppose I want to use my intuition). Or perhaps I can see a defect in the model and want to work out what’s going wrong. The obvious answer is to view the model as a wireframe.
XNA is pretty good at making it straightforward to do things like this. All you have to do is ask the Graphics Device to render in wireframe:
GraphicsDevice.RenderState.FillMode = FillMode.WireFrame;
Easy! Except… I had to change code to do that, which meant I had to recompile. Suppose I’ve got a whole batch of models I want to view at once, and want to be able to switch between wireframe and normal rendering. Changing this code every time I want to do that is going to be laborious. I could comment it out, or wrap it in “#if false… #endif”, but that makes the code look ugly and is hard to maintain. If we look to the future, when I might want to do this at any arbitrary time while a game level is running to see what is being rendered on the other side of a wall, changing the code every time is clearly out of the question. I could assign a key shortcut to it – but I’ll soon run out of shortcuts, or forget them, and how would that work if I tried to run it on Xbox 360?
Clearly a better solution is needed.
That better solution comes in the form of a set of toggleable options, which can be freely switched at runtime. The dialog box (a separate form, by the way, not a child – I’d usually keep it out of the way of the game window) that you can see in the screenshot shows how easy it is to change things on the fly. In this example, I’ve set the flag “Draw.Wireframe” to off, and replaced the previous black background with a more axiomatic “Draw.CornflowerBlue” option. It’s worth noting, by the way, that the dialog box is not the only way these options can be controlled (were you about to say, “well you can’t get Windows Forms on Xbox 360!”?) but I’ll talk more about that in a future post. The key thing is that the runtime behaviour of the game can be rapidly changed during development by means of a simple set of options – you’ll see just how simple in a moment.
Behind the scenes it’s all very straightforward. The static class Kensei.Dev.Options maintains a Dictionary of strings (the name of the option) and bools (the current state). It wraps this up behind a bunch of public functions that control and check the status of these options. That’s the core of this tip, really – a single centralised location where any arbitrary flag can be set to allow rapid changing of game state during development. It’s not intended for player-controlled options – but it will allow you to change things on the fly without recompiling your code.
The dialog box itself, by the way, is a standard .NET Windows Form, though I suppose if you’re not using C# you could use MFC if you’re still living in the Dark Ages. It adds all the Dev Options as checkboxes and maintains a live update of each option’s state with the game (so whether the option is changed in the dialog box, or in code, or by some other method, it will always remain in sync). You can see that the main form contains a tab control – there can be as many tabs as you like, with each containing as many checkboxes as you like. The form even automatically resizes itself as more options are added.
So what code is involved in this, you ask? Well, the whole Options.cs file is less than 500 lines in size, writing which was a one-off cost on my part that will save me (and you, if you decide to use it when I make it available for download) lots and lots of time in the future. The game simply needs to add one function call in its over-ridden Initialize() method (this Manager initialises all the stuff I’ll be talking about in this mini-series):
Kensei.Dev.Manager.Initialise( Content, GraphicsDevice );
…and perhaps another to make the dialog box appear automatically at startup – or it can be summoned later (here I have limited it to Debug configurations):
From this point on, it only takes a single line of code to add an option. Options default to off, but that can be controlled with an overloaded function call, or they can be added separately to explicitly state whether they should start on or off. You can even add a delegate that gets called when the option changes, which is useful in a number of scenarios. My wireframe option simply looks like this:
if ( Kensei.Dev.Options.GetOption( “Draw.Wireframe” ) )
GraphicsDevice.RenderState.FillMode = FillMode.WireFrame;
There are millions of things this can be useful for during development. Testing a difficult part of the game and need to get past it? Turn on Cheats.Invincible. Noticing your frame rate drop? Switch on Profile.ShowFPS and see how bad the damage is. Need to know what your bad guys are thinking to work out why they’re running away from the player instead of kicking his ass? AI.ShowInfluences should do the trick. Absolutely anything you can think of that you might need to change on the fly at runtime during development can be controlled using Dev Options, and it only takes one line of code to implement.
This kind of thing is what I mean by Efficient Development. It saves time, it saves effort, it keeps the code clean and maintainable. I hope you’ll have seen the benefits – firstly of having a centralised development option store, and secondly of making them easy to change via a standard Windows control. Of course you’ll already have noticed some limitations, too. It only controls booleans, for example, and from all you’ve seen so far it’s Windows only. In part two of this mini-series, I’ll show you another Kensei.Dev feature, that will go even further to making your development efficient and fast.
“Controlling complexity is the essence of computer programming.” – Brian Kernigan
PS. I can heartily recommend the Copy Source As Html add-in for Visual Studio, without which writing this blog would be much more painful.
PPS. Please, please do leave comments. Was this useful to you? Too long? Too short? Too obvious? Very clever? Questions, or suggestions?