Debugging and Deploying Mobile Games (part 1) - Game Debugging Strategies

10/23/2012 3:07:17 AM

Game Debugging Basics

Before getting into a serious discussion regarding mobile game debugging, let’s take a moment to define exactly what a bug is. A bug is simply a coding error that results in some unwanted action taking place in your game. This unwanted action can vary from a score not being updated correctly to the user’s phone going down in flames. Although the latter case is admittedly a little exaggerated, you should take bugs very seriously because they speak volumes about the quality (or lack of quality) of your games.

The concept of bugs has been an accepted part of programming for a long time now. Although all programmers strive for perfection, few are ever able to attain it. Even those that do reach that nerd nirvana typically encounter significant numbers of bugs along the way. The difference is that these programmers anticipate bugs rather than imagine that their code is immune to bugs. Therefore, the first rule in regard to debugging is to assume that bugs are in your code and that it is your responsibility to hunt them down and fix them to the best of your ability.

The issue of finding and fixing bugs is especially important in games, because game players are often very fickle. If a game does something screwy like trashing a player’s score, the player will probably get frustrated and toss your game. This makes it all the more important to be vigilant in finding bugs before you release your game. Sure, you can always distribute a patch to fix a bug in a release version, but it typically leaves game players with a less than high opinion of your development ethic.

Before getting into specific debugging strategies, let’s go over a few debugging basics. If you are already familiar with debugging in Java or in another language, feel free to jump to the next section. The following are three fundamental debugging techniques that you will find indispensable when finding and fixing bugs in your mobile games:

  • Single-stepping code

  • Watching variables

  • Using breakpoints

The next few sections explore these debugging techniques in a little more detail.

Single-Stepping Code

A very common debugger feature is the capability of single-stepping through code. Single-stepping is the process of executing your code one line at a time (in single steps). The significance of single-stepping as a debugging technique is that it provides you with a way to see exactly what code is being executed, as well as trace the flow of execution through your program. Typically, single-stepping in itself isn’t entirely useful; you usually combine it with another technique known as watching to see what happens to variables as you step through code.

Watching Variables

Watching is a technique that involves specifying certain variables in your code as watch variables. A watch variable is a variable whose contents you can see while code is executing in a debugger. Of course, in the context of a program running at normal speed, watch variables don’t help much. But if you watch variables as you single-step through code, you can gain lots of insight into what is happening. Very often, you will find that the values of variables are changing unexpectedly or being set to values that don’t make sense in the context of what you thought the code was doing. This type of insight into the inner workings of your code can lead you directly to bugs. Single-stepping combined with watch variables provides a standard approach to finding bugs with a debugger.

Using Breakpoints

Another fundamental debugging technique is that of using breakpoints. A breakpoint is a line of code that halts a program’s execution. To understand the usefulness of breakpoints, imagine that you are interested in a line of code in the middle of a program. To get to that line of code in the debugger, you would have to single-step for hours. Or you could set a breakpoint on that line and let the debugger run the program like normal. The program then runs in the debugger until it hits the breakpoint, in which case the program halts and leaves you sitting on the specified line of code. At this point, you can watch variables and even single-step through the code if you want. You also have the option of setting multiple breakpoints at key locations in your code, which is very useful when dealing with complex execution flow problems.

Game Debugging Strategies

Although debugging tools have come a long way since the early days of programming, the ultimate responsibility of eliminating bugs still rests squarely on your shoulders. Think of debuggers and standard debugging techniques simply as a means of helping you find bugs, but not as your sole line of bug defense. It takes a diversified arsenal of knowledge, programming practices, debugging tools, and even some luck to truly rid your mobile games of bugs.

Debugging can almost be likened to a hunt: You know there is something out there, and you must go find it. For this reason, you need to approach debugging with a very definite strategy. Debugging strategies can be broken into two fundamental groupings: bug prevention and bug detection. Let’s take a look at both and see how they can be used together to help make your games bug free.

Bug Prevention

Bug prevention is the process of eliminating the occurrence of bugs before they have a chance to surface. Bug prevention might sound completely logical, and that’s because it is. However, surprising numbers of programmers don’t employ enough bug prevention strategies in their code, and they end up paying for it in the end. Keep in mind the simple fact that bug detection is a far more time-consuming and brain-aching task than bug prevention. I’m all for bug prevention as a primary way to eliminate bugs.

Think of bug prevention versus bug detection as roughly parallel to getting an immunization shot versus treating a disease after you’ve contracted it. Certainly the short-term pain of getting the shot is much easier to deal with than the long-term treatment associated with a full-blown disease. This metaphor is dangerously on the money when it comes to debugging, because bugs can often act like code diseases; just when you think you’ve got a bug whipped, it rears its ugly head in a new way that you never anticipated.

Getting Explicit with Parentheses and Precedence

One area prone to bugs is that of operator precedence. I’ve been busted plenty of times myself for thinking that I remembered the precedence of operators correctly when I didn’t. Take a look at the following code:

int a = 37, b = 26;
int n = a % 3 + b / 7 ^ 8;

If you are a whiz at remembering things and you can immediately say without a shadow of a doubt what this expression is equal to, then good for you. For the rest of us, this is a pretty risky piece of code because it can yield a variety of different results depending on the precedence of the operators. Actually, it only yields one result, based on the correct order of operator precedence set forth by the Java language. But it’s easy for programmers to mix up the precedence and write code that they think is doing one thing when it is doing something else.

What’s the solution? The solution is to use parentheses even when you don’t technically need them, just to be safe about the precedence. The following is the same code with extra parentheses added to make the precedence more clear:

int a = 37, b = 26;
int n = ((a % 3) + (b / 7)) ^ 8;

Avoiding Hidden Member Variables

Another potentially tricky bug that is common in object-oriented game programming is the hidden member variable. A hidden member variable is a variable that has become “hidden” because of a derived class implementing a new variable of the same name. Take a look at Listing 1, which contains two classes: Weapon and Bazooka.

Listing 1. The Weapon and Bazooka Classes

The Weapon class defines two member variables: power and numShots. The Bazooka class is derived from Weapon and also implements a numShots member variable, which effectively hides the original numShots inherited from Weapon. The problem with this code is that when the Weapon constructor is called by Bazooka (via the call to super()), the hidden numShots variable defined in Weapon is initialized, not the one in Bazooka. Later, when the blastEm() method is called in Bazooka, the visible (derived) numShots variable is used, which has been initialized by default to zero. As you can probably imagine, more complex classes with this problem can end up causing some seriously tricky and hard-to-trace bugs, especially in game code.

The solution to the problem is to simply make sure that you never hide variables. That doesn’t mean that there aren’t a few isolated circumstances in which you might want to use variable hiding on purpose; just keep in mind the risks involved in doing so.

Making the Most of Exception Handling

One useful preventive debugging mechanism in Java is exception handling, which is a technique focused on detecting and responding to unexpected events at runtime. An exception is something (usually bad) that occurs in your program that you weren’t expecting.

To handle exceptions in your game code, you enclose potentially troublesome code within a try clause. A try clause is a special Java construct that tells the runtime system that a section of code could cause trouble. You then add another piece of code (a handler) in a corresponding catch clause that responds to errors caused by the code in the try clause. The error event itself is the exception, and the code in the catch clause is known as an exception handler.

try {
  // Do something that is capable of causing an exception
catch (Exception e) {

In this code, the exception being handled is of type Exception, which is the most general of all exceptions. In some cases you may want to take action in response to an exception, as opposed to just printing information about the exception to the standard error “device.”

Construction Cue

Java supports standard input and output devices, the latter of which can be used to display debugging information. System.err is the standard error “device,” which is handy for printing messages that are displayed in a special error window or on the command line from which the J2ME emulator is run. The System.err.println() method prints a string to the standard error device.

This discussion of exception handling really only scratches the surface of handling runtime errors (exceptions). I strongly encourage you to learn more about exception handling and how to effectively use it. Fortunately, a lot of information has been published about exception handling in Java, so you shouldn’t have much trouble finding useful references.

Bug Detection

Even if you rigorously employ bug avoidance techniques, you will still have to contend with a certain number of bugs. It’s just a fact of life that programmers make mistakes, and the sheer complexity of many mobile game programming projects often causes problems that elude us. Just embrace the notion that you’re imperfect and focus your attention on tracking down the mistakes. The point is that in addition to applying bug prevention techniques as much as possible, you must learn how to track down the inevitable bugs that will surface when you start testing your game. Let’s look at a few techniques for hunting down bugs.

Taking Advantage of Standard Output

The age-old technique for tracking down bugs is to print information to standard output. This approach probably sounds pretty archaic, and in many ways it is, but if you want a quick and dirty look into what’s going on in your game, it’s often your best bet.

Employing the standard output technique is as simple as inserting calls to System.out.println() at appropriate locations in your code. You can use standard output for anything from looking at the value of variables to determining whether a method is being called; just sprinkle those println() calls wherever you need them! The primary caveat to this approach is that you should be careful when placing the println() call in an update loop, such as the update() method, which controls the animation in MIDlet games. In this case, the println() call might slow the game to a crawl simply because of the overhead involved in printing text to the standard output device at such a rapid pace.

Construction Cue

Standard output is very similar to the standard error device. In fact, in many cases they are one and the same. However, it is generally a good idea to print error messages to the standard error device, and save standard output for general debugging information.

Tracing the Call Stack

An indispensable tool in tracking down hard-to-find bugs is the method call stack. The method call stack is a list of the methods called to arrive at the currently executing code. By examining the call stack, you can see exactly which methods were called to get to the current piece of code in question. This information often sheds light on a problem regarding a method being called inadvertently.

You can view the call stack by calling the printStackTrace() method, which is a member of the Throwable class. Because printStackTrace() is a method in Throwable, you must have a Throwable object to look at the call stack. It just so happens that all exceptions are derived from Throwable, so any time you have an exception, you can view the call stack. Check out the following code:

In this code, the array nums is indexed out of bounds in the for loop, generating an ArrayIndexOutOfBoundsException. The exception is logged to standard output in the catch clause, along with a call to printStackTrace().

Top 10
SG50 Ferrari F12berlinetta : Prancing Horse for Lion City's 50th
The latest Audi TT : New angles for TT
Era of million-dollar luxury cars
Game Review : Hearthstone - Blackrock Mountain
Game Review : Battlefield Hardline
Google Chromecast
Keyboards for Apple iPad Air 2 (part 3) - Logitech Ultrathin Keyboard Cover for iPad Air 2
Keyboards for Apple iPad Air 2 (part 2) - Zagg Slim Book for iPad Air 2
Keyboards for Apple iPad Air 2 (part 1) - Belkin Qode Ultimate Pro Keyboard Case for iPad Air 2
Michael Kors Designs Stylish Tech Products for Women
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
Popular Tags
Video Tutorail Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Exchange Server Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe Photoshop CorelDRAW X5 CorelDraw 10 windows Phone 7 windows Phone 8 Iphone