Acorn Heroes

Tag: idevblogaday

Tuning Your Game Made Easy

by on Jul.09, 2010, under Coding, Game Design

Some days it’s hard to think of something to write about, and other days something just falls in your lap. Happily this week it was the latter. It all started with Miguel (as these things often do) – a.k.a. @mysterycoconut on Twitter – posting this article about connecting to an iDevice via telnet while running your App. Using this technique it becomes possible to rapidly tweak parameters on the fly or in fact do all sorts of crazy stuff.

Needless to say I jumped on this idea to aid in tuning my current game prototype. I’ve just reached the stage where rapid tweaking of variables is going to help focus and refine the game play. Miguel suggests hooking a Lua scripting engine into your code, but I thought it would be fun to create my own, plus most of my code is C++ (rather than Objective-C) and I’ve found binding Lua to C++ to be a fiddly process in the past.

The corresponding code for this article can be found here. Note that the DebugServer code comes from Miguel’s article, and the AsyncSocket code comes from here.   I’ve added a minimal amount to Miguel’s code to pass received commands on to the DebugUtils functions found in Debug.[h|mm]. I haven’t had time to create a complete sample project, but the code provided should drop into any existing code base with minimal fuss. If the coding style looks a little strange, you may want to also read this and this.

So, let’s start at the end and work backwards, which I often find to be an effective technique. When tuning a game we spend a lot of time tweaking variables and constants – maximum speed, rate of fire, gravity, item prices, animation durations etc. Wouldn’t it be nice to open up a telnet session to your App and enter a command like “gravity = -8”? Alternatively, maybe there’s a set pattern of enemies that causes a rare bug. Wouldn’t it be nice to enter a “SetupWeirdEnemyPattern” command for easy testing?

So, we have two common scenarios – tweaking a variable and executing a function that alters the game state in a slightly more involved way. The code below allows us to do this. Variables and functions can be “registered” and given a name, which we can then use to adjust values or execute functions via our telnet connection. To make it simple to pass in parameters to these functions, we pass in a set of text parameters using argc and argv, just like the main() function of a C++ program.

Let’s have a look at the public interface to this code:


typedef bool (*DebugCommandFunc)(int argc, char *argv[]);

namespace DebugUtils
{
    void Initialise();

    bool ProcessCommand(const char *command);

    bool RegisterCommand(const char *commandName, DebugCommandFunc commandFunc);

    bool RegisterVariable(const char *variableName, bool *var);
    bool RegisterVariable(const char *variableName, int *var);
    bool RegisterVariable(const char *variableName, float *var);
}

Not much there, is there? The guts of it is in the ProcessCommand() function, where we pass in a string, and magic happens. Or, to provide an example:


bool ResetGameCommand(int argc, char *argv[])
{
// Do stuff here to reset the game state
}

DebugUtils::RegisterCommand(“ResetGame”, ResetGameCommand);

And later, through a telnet connection, we enter “ResetGame”, which in turn calls:


DebugUtils::ProcessCommand(“ResetGame”);

And, just like magic, we reset the game state.

Or as another example, we could register a game variable, say…


DebugUtils::RegisterVariable(“gold”, &gameState.pileOfDubloons);

And then, through the telnet connection, we can tweak this value mid-game, by entering:

“gold = 10000”, or “gold *= 2.0”

I’ve intentionally kept this system as simple as possible, but there’s a lot of power here. It’s very simple to register variables or add short pieces of code that can be run as needed. Just a few examples – turning on debug drawing to see bounding boxes of physics objects, changing the value of gravity or a jump pack’s thrust, loading an arbitrary level, turning off collision detection – the sky’s the limit.

The key thing here is to let you spend as much time as possible refining and tuning your game, because as Jesse Schell describes in his excellent book The Art of Game Design: A book of lenses:

The Rule of the Loop: The more times you test and improve your design, the better your game will be.

In other words, by removing the code-compile-run stage from tuning our game, we can create a better game in less time. Hopefully this code, combined with Miguel’s will provide a simple way to help you refine and debug your game.  Happy tuning!

P.S. I was planning to include a description of how I used TDD (Test Driven Development), but figured this post was long enough. If it’s something you’re interested in though, leave a comment or drop me a note on Twitter (@GeorgeSealy) and I’ll put together an article.

P.P.S. Yes, there’s a few things that could be added to this code to make it even more useful. At the moment it’s not possible to pass a parameter that’s a string with spaces or new lines in it. To do this, you just extend the tokenizing code to respect quoted parameters like “This is a string”.

P.P.S. I’ve resisted the temptation to allow more complex calculations such as “percentComplete = 100 * itemsFound / totalItems”. Most of the time all you want to do is tweak values. If you need this much power, hook in Lua as Miguel suggests, don’t roll your own as it becomes increasingly difficult to maintain as a project matures.

P.P.P.S. I’ve also just realised one of the more useful things I’ve left out – if you just supply the name of a variable on its own, then the variable’s value should be either returned via telnet or printed out using NSLog or similar.  There’s nothing worse than finding the perfect value for something and then being unable to see what it is!

P.P.P.P.S. The observant amongst you may have noticed that the link to Jesse Schell’s book is an Amazon Affiliate link, meaning if you follow that link and subsequently purchase something I may get a small commission. I will only ever put such links to books that I have bought myself or at least read cover to cover and would recommend.

2 Comments :, , more...

The Things I Learn From Twitter Amaze Me

by on Jul.02, 2010, under Coding

If you’re an iPhone Dev, and you’re not using Twitter, you really should be.

Whatever else Twitter may be, it is a wonderful, anarchic repository for random bits of incredibly useful information. A good habit to get into is marking useful tidbits as favourites so that you can come back to them later. (As an aside, the first person who comes up with an easy way to sync up favourites on Twitter, bookmarks from various browsers on different machines and favourites in Google’s RSS reader will do very well for themselves.)

In celebration of the randomness of twitter, here’s a few really handy iPhone-related tips I’ve picked up lately:

Managing double size graphics for the iPhone 4 (link)

With the release of the iPhone 4, developers now have the tricky problem of dealing with multiple resolutions. There seems to be a consensus amongst many iPhone devs that the best way to handle this is with 2 sets of graphics, one for each resolution. So this means you have to deal with two sets of filenames through out your code, right? Well actually no.

It turns out that when you call:

[UIImage imageNamed:@"myImage.png"]; (or contentsOfFile:)

on the iPhone 4, it will actually first attempt to load an image called myImage@2x.png first.  So simply ensure that both sets of images have the same file names (with @2x added to the iPhone 4 set), and the Sdk will take care of things for you.

Update: It turns out that the ‘@’ symbol can cause havoc with Subversion (SVN).  If you use SVN, you’d better read this before you start creating all those double resolution graphics.  Once again, I learned this from Twitter also.

Clear the colour buffer for faster rendering (link via @majicDave)

Because of the way iOS handles OpenGL rendering, it’s possible to get a speed boost by ensuring you make a call to clear the colour buffer before rendering. This is actually faster than not making the call at all, which seems counter-intuitive.  @majicDave reported a significant improvement in frame rate when he tried this.

Hot loading levels on the device (link)

If you have a chance, read @SnappyTouch’s article in Game Programming Gems 6 : Stay in the Game: Asset Hotloading for Fast Iteration. The idea is to allow assets (textures, levels, shaders, AI scripts etc) to be re-loaded in game.

By doing this, it becomes possible to rapidly tweak and refine your game without the need to recompile. One obvious benefit is that refining assets becomes far quicker without the necessary compile – and the faster you can iterate, the better your result will be. A second benefit is that it becomes possible for artists and designers to tinker with the look and game play of the App without needing to involve a programmer.

Hot loading assets on an iPhone / iPod is a little more involved, as we don’t get easy access to the device’s file system via another computer.  Miguel’s article demonstrates a good way to do this. This was also the article that kicked off the idea of #iDevBlogADay.

Getting old firmware versions (link)

So you realize that you need to test an odd bug in OS 3.13 but you’ve just upgraded your testing device to OS 4.0? This tweet give you all you need to know to revert your device to an earlier OS version. Just remember to ensure you back up everything important!

There’s HOW many sizes of icons? (link)

‘Nuff said.

Tracking your day to day sales on the App Store? (link)

Admittedly Apple emailed all developers about this one, but I heard it first via Twitter.

How to handle special characters in URLs (link)

So you’re dealing with URLs and want to get rid of all those pesky escape characters like ‘%20’ (a space)? Don’t do this by hand, it’s messy, error prone and just not needed. Apple have given us stringByReplacingPercentEscapes to take care of this for us.  This is the kind of thing that can be found in documentation if you know to look for it.  Often a quick question asked on Twitter can gain valuable insight.

Physics calculations are tricky (link)

Fortunately there’s clever people out there who can help us avoid the most common errors. By fixing the time step at which you run your simulation, many problems can be avoided. Additionally, there can be many advantages to separating the render and simulation time steps. http://gafferongames.com provides a wealth of useful information here.

I’ve been surprised by Twitter, I was worried it was just another social networking Web 2.0 buzz annoyance, but I was lucky to find a vibrant, fun group of intelligent people with a common interest.  If you’re not sure about Twitter, give it a go.  I’m @GeorgeSealy, feel free to say hi – I promise to keep my tweets to mainly iPhone Dev related topics!

9 Comments :, , more...