Pandemonium

July 28, 2008

Efficient Development – part two

Filed under: Games Development — bittermanandy @ 7:26 pm

In part one of the Efficient Development mini-series, I talked about the importance of providing a simple set of boolean switches that can be set up and used with an absolute minimum of effort, to gain the absolute best possible use of your development time. I also showed how my Kensei.Dev library reduces the effort involved in setting such options up, to basically one line of code.

I mentioned in the closing comments of that article that Kensei.Dev.Options has some limitations. For a start, it only allows you to turn options on and off (or, set up a delegate that is called whenever the on/off state is changed). It’s not hard to imagine that you might encounter a situation where you need much more power and flexibility than that.

Let’s look at a slightly more concrete example. Let us suppose that we are getting into the closing stages of development on our game, and are starting to encounter frame rate issues. We’ve read through what Shawn Hargreaves has to say about profiling XNA games, and working on a combination of his advice and what we’ve already learned about Efficient Development, we’ve set up a couple of Kensei.Dev.Options we can use to help us determine whether we are CPU or GPU bound:

    protected override void Update( GameTime gameTime )

    {

#if PROFILE

        if ( Kensei.Dev.Options.GetOption( “Profile.Sleep1msOnUpdate” ) )

        {

            // If enabling this option does NOT reduce frame rate,

            // we must be GPU bound

            System.Threading.Thread.Sleep( 1 );

        }

 

        if ( Kensei.Dev.Options.GetOption( “Profile.SkipUpdate” ) )

        {

            // If we are not GPU bound, if enabling this option improves frame rate,

            // we must be CPU bound (else balanced).

            Kensei.Dev.Manager.Update();

            base.Update( gameTime );

            return;

        }

#endif

        // … rest of Update method

After determining that we are GPU bound, we continue to read through Shawn’s brilliant performance articles and notice the following advice:

Try running your game in a tiny resolution, say 100×50. … If reducing the resolution speeds things up, you must be limited by one of the pixel processing stages.

Good tip. It’d be great if we could do this whenever we wanted instead of hard coding it, so obviously we need to add another Kensei.Dev.Option that will set the resolution to 100×50.

Wait right there! Doesn’t it strike you that 100×50 is a bit, well, fixed? Undoubtedly running in a very low resolution will be handy for profiling. Still – wouldn’t running in a very high resolution be handy for showing the game off to our friends? How about changing aspect ratios to check how our user interface behaves? In fact, shouldn’t we be able to run the game in absolutely any resolution we want?

This is clearly a situation where Kensei.Dev.Options is insufficient. Luckily, at this point Kensei.Dev.Command steps up to the mark.

The idea is a very simple one, and not new (though I think the way I’ve implemented it is pretty clever). It’s something you can and should add to any of your games, even if you choose not to use my implementation. Basically it involves adding support for a command line interface to the game – and making it trivially easy to add new commands, and for the player/developer to issue such commands. You’ve undoubtedly have seen this before – most likely in the Quake series and Half-Life 2, which ship with these command interfaces even in their distributable builds.

In Kensei.Dev.Command, registering a new command is very easy:

    Kensei.Dev.Command.AddCommand( “SetResolution”, SetResolutionDelegate,

        “Sets the display resolution.” );

This simply registers the command string with the delegate in a Dictionary. When the command is issued, the delegate is called with an array of strings representing the full command line. This is exactly analogous to the way command line arguments are passed to an executable, so you can use the same well-known techniques to parse these arguments. Providing the parameters in this way separates Kensei.Dev.Command completely from the way any particular command behaves.

    private void SetResolutionDelegate( string[] parameters )

    {

        switch ( parameters.Length )

        {

            case 1:

            default:

                Kensei.Dev.Command.Print( “Sets display resolution.

                    Usage: SetResolution <width> <height>” );

                break;

 

            case 3:

                try

                {

                    int width = int.Parse( parameters[1] );

                    int height = int.Parse( parameters[2] );

                    m_graphics.PreferredBackBufferWidth = width;

                    m_graphics.PreferredBackBufferHeight = height;

                    m_graphics.ApplyChanges();

                }

                catch ( System.Exception )

                {

                    Kensei.Dev.Command.Print( “Invalid resolution.” );

                }

                break;               

        }

    }

That’s it – that really is all there is to it. Not very much code for a very useful, flexible and powerful feature.  Not the way you’d want to present the choice of resolution to a player of the final version of your game, but it gives us the flexibility to change resolution at will completely arbitrarily. At runtime, we use a Windows Form (much like the one used by Kensei.Dev.Options) to allow the developer to enter their commands. The command line has full support for typical Doskey features (for example, using the up and down cursors to scroll through previously issued commands) and there are some common commands that every game is likely to need.

An example Dev Command

An example Dev Command

I think the separate form for input is the most elegant way of achieving this, but obviously that won’t work on Xbox 360, so I’ve also supported the more Quake-like technique of drawing the command line interface over the top of the game itself. You can plug any USB keyboard into your Xbox 360 (you can pick up a cheap one for maybe £5-£10), and instantly have access to the full range of dev commands, exactly the same as you have on Windows, shown here. (You can see listed the full range of commands currently available to my Modelviewer tool. Note in particular “setoption” and “getoption” - this is how it’s possible to use the Kensei.Dev.Options stuff on 360, where there are no Windows Forms).

Using the in-game Dev Command interface

Using the in-game Dev Command interface

I hope it’s obvious how useful Kensei.Dev.Command (or your own similar implementation, if you prefer) can be, and how little extra code it involves. I use it to take screenshots; to save, load, and change levels; and to interrogate the game database as to the current state of an object; among many other things. If your game uses a scripting language (and as we’re talking about Efficient Development, that is something I would strongly recommend for any complex game) it is trivial to use this command line interface to issue commands in that language, allowing you to make changes to the fundamental behaviour of your game on the fly, without recompiling, and dramatically speeding up your development iterations. You could even allow whole scripts to be created and run via the command line, removing the tedium of repeatedly entering the same commands.

So this was another straightforward tip but a very powerful and flexible one. Combined with the easily-switchable options discussed in the previous article, this will really help make your development sessions faster and more efficient. In the next part of this mini-series, we’ll look at some more techniques to help you do just that.

“Make everything as simple as possible; but no simpler.” – Albert Einstein

About these ads

3 Comments »

  1. Wow, I loved this article. This was definitely one of those moments where you slap yourself on the forehead and think, “Duh! How didn’t I think of that sooner?!” Really good advice so far. I’ve always been a fan of simple and elegant solutions to problems, especially when the solutions are extensible for other developers to tailor to their own needs. Again, great article and advice, looking forward to reading more!

    Comment by Kolo Rahl — July 29, 2008 @ 6:14 am | Reply

  2. Very helpful. In a future post could you please elaborate on scripting? I’m curious as to why you recommend it, and how to implement it. Thanks for a great blog

    Comment by Venatu — December 6, 2008 @ 7:53 pm | Reply

  3. I’m probably unlikely to write a whole article on scripting in the near future as I’ve not worked that closely with it, not enough to know what I’m talking about in any detail anyway (I’ve worked on plenty of projects that did use it, I simply had other responsibilities). Maybe one day, when I get to implementing scripting in my own games.

    Basically though, the advantage of scripting is that it makes your game far more data-driven. This is most beneficial to full-team games, because it allows your designers to control the gameplay themselves, instead of relying on programmers to make changes for them; but even for individuals, scripting allows you to change things on the fly, without recompiling your entire game. A good scripting system will let you play a part of the game, change the script, play it again, change the script, etc. – and you can go through four or five iterations in the time it would take you to recompile the game just once. This kind of rapid turnover allows you to fine-tune your game much more quickly and makes for a better game in the end.

    It might not be obvious, but XACT is one form of scripting; it’s just a script with a visual interface rather than script “code”. Instead of the programmer having to write C# code that says, “randomly select one of these ten .WAV files and play it, at this volume and for this long”, the programmer (or even better – another script, removing the programmer entirely!) just says “play this cue”. The audio designer can then control how many variations there are, how long they are played, how many instances to limit it to, etc. XACT has been specifically designed for rapid iteration – that’s why you can connect the XACT GUI to your game for auditioning, so if you’re developing your game and realise the gunshot sounds are too quiet, you can just increase the volume while the game is running and hear the difference instantly, reducing it again if you went too far, etc. Scripting is a general purpose extension of exactly the same thing.

    Comment by bittermanandy — December 6, 2008 @ 10:13 pm | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The Rubric Theme. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: