Adding Configuration and Logging
In the last tutorial we setup the main application core that we can use as a primitive kernel
to run our games with the help of the DirectX sample framework. In this tutorial we’ll go through
adding some important pieces to your application, even if they might be “unsexy”; reading .ini config files,
and logging.
Reading INI Configuration
An important ability for your application, is to be somewhat data driven in nature. In other words, your
application loads in certain data during runtime of your game, to make decisions. While it’s dangerous
to go “hog wild” and make your codebase completely data driven, we can certainly benefit from a small
use of it.
For faster testing and to shorten development time, a bit of a data driven approach can offload some work
onto your game designer crew and/or testers instead of forcing you to re-compile any desired changes.
A good use of data driven design is reading any location-specific language data. Suppose your game has several
dialogs of text which describe a certain scene to the player. If you hardcode this text into your game,
then it means needing to re-compile the entire thing for any minor text change. It is also more difficult
to add in support for other languages, because you would need to re-compile those additions as well.
While we can get fancy and load XML configuration information, let’s stick to something easier such
as using .INI files to contain our data. INI files have existed since the days of Windows 3.11 as they
were the main configuration base that Windows used before the Registry existed, and we can in turn
leverage the API that was built into the Win32 system codebase. A common use for configuration files
is to set a default resolution and/or window size for your game, such as the following:
[Application] WindowWidth=640 WindowHeight=480 WindowDepth=32 Windowed=TRUE
GetPrivateProfileString
and GetPrivateProfileInt
can be used to quickly scan our configuration information from the .ini file we pass into the engine.
With the attached code, I wrapped this ability into the IniConfigReader object in order
to give you quick access to any configuration information you want to put into the .ini file.
DWORD IniConfigReader::getString(const string strSection,
const string strKey,
const string strDefault,
string& strReturn)
{
DWORD dwResult = 0;
TCHAR strTemp[MAX_PATH];
ZeroMemory( &strTemp, sizeof( strTemp ) );
dwResult = GetPrivateProfileString(strSection.c_str(),
strKey.c_str(),
strDefault.c_str(),
strTemp,
MAX_PATH,
m_strFileName.c_str());
strReturn = strTemp;
return dwResult;
}
UINT IniConfigReader::getInt(const string strSectionName,
const string strKeyName,
int iDefault)
{
UINT iResult;
iResult = GetPrivateProfileInt(strSectionName.c_str(),
strKeyName.c_str(),
iDefault,
m_strFileName.c_str());
return iResult;
}
While there are other ways to process .INI files, I thought this way was among the easiest and flexible.
Using Log Files
Another small but very important component of a game, besides reading in configuration information,
is recording certain events and/or messages that you need to for troubleshooting any problems with
the game. Log files are used as not only a support tool for helping your customers, but also to
bring attention to any potential problems. Under the hood of our codebase, the FileLogger Singleton class
has a file stream handle that we can use to record anything of significance. Either for debugging purposes,
or to let our player know additional troubleshooting information should they encounter an error in your game.
Note: For a more detailed look at the Singleton, check out our tutorial here.
bool FileLogger::openLogStream(const string& strName)
{
m_log_file.open( strName.c_str() );
m_strLogName = strName;
logInfo("FileLogger", "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++");
logInfo("FileLogger", "+ Event log +");
logInfo("FileLogger", "+ (http://www.wazooinc.com/) +");
logInfo("FileLogger", "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
logInfo("FileLogger", "FileLogger singleton created.");
return true;
}
In our codebase, along with our DirectX sample framework components, we now have the ability to record
events to a logfile, along with reading any configuration settings we want from an .INI file. To integrate
these 2 new objects into our codebase, I’ve made the following addition to the MyApp.h file.
class MyApp : public CD3DApplication
{
protected:
IniConfigReader* m_pConfig;
//snip!
Since the FileLogger object is a Singleton, we don’t really need to store a pointer anywhere to it in
our MyApp definition. Take a look at the OneTimeSceneInit() in the code…
HRESULT MyApp::OneTimeSceneInit()
{
new FileLogger();
if(!FileLogger::getSingletonPtr()->openLogStream("data\\application.log"))
{
return E_FAIL;
}
m_pConfig = new IniConfigReader("data\\system.ini");
return S_OK;
}
When we launch the application, you should now see the log file ‘application.log’ appear!
Logging Severity
Most of the “fancy” logging objects, such as log4j for java, use a principle of logging severity
(for lack of a better term) for helping you organize any important information that’s logged. Right
now it’s easy to find things when you only have a few lines to scan through. However, in larger
games this number might reach into the hundreds (or higher) making it more difficult to analyze.
The FileLogger object I created also includes the ability to specify which object is tripping a log
entry, and also what “severity” this should be classified with:
- INFO - Just for casual messages…in other words “FYI”
- DEBUG - Debugging information which should be stripped out of any release version of your game
- ERROR - Uh oh! We’ve got a potential problem!
- FATAL - Any object that trips the FATAL severity should immidiately precede a shutdown of the game!
The benefit of this is that you get output similar to:
19/06/2007 12:33:56: [FileLogger] | INFO | ******************************* 19/06/2007 12:33:56: [FileLogger] | INFO | [BEGIN EVENT LOG] 19/06/2007 12:33:56: [FileLogger] | INFO | ******************************* 19/06/2007 12:33:56: [FileLogger] | INFO | FileLogger singleton created. 19/06/2007 12:33:56: [GameEngineCore] | INFO | Application startup initiated. 19/06/2007 12:33:57: [GameEngineCore]| DEBUG | Using window parameters: 640 x 480 x 32 19/06/2007 12:33:57: [GameEngineCore] | INFO | Application startup complete. 19/06/2007 12:33:59: [GameEngineCore] | INFO | Application shutdown initiated. 19/06/2007 12:33:59: [FileLogger] | INFO | FileLogger singleton destroyed. 19/06/2007 12:33:59: [FileLogger] | INFO | ***************************** 19/06/2007 12:33:59: [FileLogger] | INFO | [END EVENT LOG] 19/06/2007 12:33:59: [FileLogger] | INFO | *****************************
Hope you enjoy the code as much as I enjoyed making it!
Feedback? Comments?
Either comment to this posting, or use our contact form to get in touch with us.











This is default description text on Padangan Themes, of course you can change this text via you profile administration.
January 31st, 2008 at 8:16 am
[...] That’s pretty much all we need defined for our lowest-level base class. To see this object in use, be sure to check out the other tutorials on this site. Most of them employ this Singleton object to work with objects such as our FileLogger [...]