Developing game software is a complex, intricate, math-intensive and
error-prone business. So it should be no surprise that virtually every
professional game team builds a suite of tools for themselves, in order to make
the game development process easier and less error-prone. In this chapter,
we’ll take a look at the development and debugging tools most often found in
professional-grade game engines.
9.1 Logging and Tracing
Remember when you wrote your first program in BASIC or Pascal? (OK, maybe you don’t. If you’re significantly younger than me—and there’s a pretty
good chance of that—you probably wrote your first program in Java, or maybe
Python or Lua.) In any case, you probably remember how you debugged your
programs back then. You know, back when you thought a debugger was one of
those glowing blue insect zapper things? You probably used print statements
to dump out the internal state of your program. C/C++ programmers call this
printf debugging (after the standard C library function, printf()).
It turns out that printf debugging is still a perfectly valid thing to do—
even if you know that a debugger isn’t a device for frying hapless insects
411
412 9. Tools for Debugging and Development
at night. Especially in real-time programming, it can be difficult to trace certain kinds of bugs using breakpoints and watch windows. Some bugs are
timing-dependent: they only happen when the program is running at full
speed. Other bugs are caused by a complex sequence of events too long and
intricate to trace manually one-by-one. In these situations, the most powerful
debugging tool is often a sequence of print statements.
Every game platform has some kind of console or teletype (TTY) output
device. Here are some examples:
• In a console application written in C/C++, running under Linux or
Win32, you can produce output in the console by printing to stdout
or stderr via printf(), fprintf() or STL’s iostream interface.
• Unfortunately, printf() and iostream don’t work if your game is
built as a windowed application under Win32, because there’s no console in which to display the output. However, if you’re running under
the Visual Studio debugger, it provides a debug console to which you
can print via the Win32 function OutputDebugString().
• On the PlayStation 3 and PlayStation 4, an application known as the Target Manager (or PlayStation Neighborhood on the PS4) runs on your PC
and allows you to launch programs on the console. The Target Manager
includes a set of TTY output windows to which messages can be printed
by the game engine.
So printing out information for debugging purposes is almost always as
easy as adding calls to printf() throughout your code. However, most
game engines go a bit farther than this. In the following sections, we’ll investigate the kinds of printing facilities most game engines provide.
9.1.1 Formatted Output with OutputDebugString()
The Windows SDK function OutputDebugString() is great for printing debugging information to Visual Studio’s Debug Output window. However, unlike printf(), OutputDebugString() does not support formatted output—
it can only print raw strings in the form of arrays. For this reason, most Windows game engines wrap it in a custom function, like this:
#include
// for va_list et al
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include // for OutputDebugString()
9.1. Logging and Tracing 413
int VDebugPrintF(const char* format, va_list argList)
{
const U32 MAX_CHARS = 1024;
static char s_buffer[MAX_CHARS];
int charsWritten
= vsnprintf(s_buffer, MAX_CHARS, format, argList);
// Now that we have a formatted string, call the
// Win32 API.
OutputDebugString(s_buffer);
return charsWritten;
}
int DebugPrintF(const char* format, ...)
{
va_list argList;
va_start(argList, format);
int charsWritten = VDebugPrintF(format, argList);
va_end(argList);
return charsWritten;
}
Notice that two functions are implemented: DebugPrintF() takes a
variable-length argument list (specified via the ellipsis, . . . ), while VDebugPrintF() takes a va_list argument. This is done so that programmers can
build additional printing functions in terms of VDebugPrintF(). (It’s impossible to pass ellipses from one function to another, but it is possible to pass
va_lists around.)
0 Comments
Please Comment for any further query :