Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
68 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

Contents
 Organizing Projects
 Creating Libraries
 Runtime Log Files
 Protecting
 Image Data

 Introduction
 to Scripting

 The String Table

 Printable version
 Discuss this article
 in the forums



The Series
 Beginning Windows
 Programming

 Using Resources
 in Win32 Programs

 Tracking Your
 Window/Using GDI

 Introduction
 to DirectX

 Palettes and Pixels
 in DirectDraw

 Bitmapped Graphics
 in DirectDraw

 Developing the
 Game Structure

 Basic Tile Engines
 Adding Characters
 Tips and Tricks

Introduction

Here we are, with nine articles behind us, and only one left to go. It's unfortunate that I won't have time to take this any further, since there a lot more things I could go over, but we've gotten off to a good start in Windows game programming, and there are any number of places you can go from here: input devices, sound effects and music, scripting, the DirectX Graphics API, etc. There are lots of articles covering things like this to be found at GameDev.Net, or there's always the DirectX documentation.

In any case, to close the series out, I'm going to show you a few little things you can use while developing your games. A lot of these, like organizing large programs logically into multiple source files, are going to be necessities when you start building up a full game. For most of today's article you won't actually need knowledge of DirectX to follow along, so don't worry if you've missed previous articles in the series. All set? Let's start with the topic I just referred to: organizing programs.

Organizing Projects

All of the demo programs I've shown you along the way in this series have been relatively short. The source file for the most recent one, on adding characters to your game, was about a thousand lines long, but that includes comments and whitespace, and I use both quite a bit. Even so, when you start putting a full game together, you'll quickly find that putting all your code in a single source file just won't work. It's not very organized that way. Sure, you can use Visual C++ to search for functions pretty quickly, but it's still much better to have your program logically broken up so you can find things when you need them. Also, it's nice to be able to jump from one function to another just by switching documents, or to compare code from two documents side by side.

Organizing a program in C++ is easy: if each class has its own source and header files, you'll always be able to find what you're looking for. For C programs it's not so well-defined, so you should just do your best to group functions which serve similar purposes together. To give you an example, I'll show you what my source files for Terran look like. There are quite a few, but it makes it easy for me to know where everything is.

audio.cppThis file contains all functions needed for loading and playing sound effects and music.
battle.cppThese functions handle the details of the battle system, including the code that makes battle decisions for enemies.
chars.cppThis contains everything pertaining to character handling, such as movement and animation, keeping NPCs sorted, and locating characters on the map.
directx.cppAll the code that actually makes changes to DirectX interfaces is here, mostly for initialization and shutdown, but also for things like restoring and reloading lost surfaces.
game.cppThe very general framework for each major game state is contained here.
graphics.cppAny function which renders graphics to a surface, be it fading or fireballs, maps or text boxes, is found here.
input.cppThis file detects and reads input devices, and combines the relevant information into a small input structure used by the rest of the game.
items.cppItem functions such as buying, selling, using, transferring, or discarding items are here, along with anything else needed to manage character inventories.
magic.cppSpells are managed from here, both the learning and the casting of them. Graphical output is done in graphics.cpp, but this file is responsible for setting up those effects.
maps.cppThis wraps up anything map-related: loading maps and collision data, performing collision detection, and launching scripts linked to the map.
menus.cppThis file allows the user to navigate through any menu in the game, and sends commands to the rest of the game as necessary.
scripts.cppHere is where the scripting language extensions are set up, and specialized script functions are located. The general script loader and parser are in a library I wrote; I'll get to that later.
stats.cppThese functions manage character statistics: computing those that are constantly changing, updating main stats at level increases, and so on.
stdafx.cppThis is the precompiled header Visual C++ sets up for you when you create a simple project.
terran.cppProbably the simplest one, this one just has variable declarations, WinMain() and WindowProc(), plus some functions for loading game data which are called only once, at startup.
terranrs.rcTerran's resource script, it contains a few icons, several audio files, and an enormous string table.
text.cppAnything text-related, such as generating lists or loading dialogue, is done here.

So hopefully that will give you an idea how to keep source files organized. I also have a large header file called stdafx.h, which contains declarations for a bunch of structure types, function prototypes, extern statements for global variables, and about five hundred million #define statements. If you haven't seen it before, the extern keyword allows other source files to access a global variable that's been declared in a different source file. It's just a qualifier that goes on the front of a variable declaration, like this:

extern int bImageLock;
extern STATE sGameState;

By including these extern statements in a header file, you can just include the header file at the top of every source file, and you'll have access to all your globals. The other thing to make sure you do with header files is to avoid including things like type declarations multiple times. For this, you use the #if and #endif directives. The way it's usually done is to check if a certain constant has been defined. If not, define it, then include all the stuff you need. That way, the next time that block of code is encountered, the constant has already been defined, so your declarations are only included once. For example:

#if !defined(_GAME_HEADER_001_INCLUDED)
#define _GAME_HEADER_001_INCLUDED

// ... constant declarations and such go here...

#endif

There are a lot of blocks like this inside the main Windows headers, which is why using #define WIN32_LEAN_AND_MEAN can keep a lot of unnecessary code out of your project builds. Most things you'll put in header files should only be included once, and so should be inside a #if block. But including external variables with extern should be included in every source file, so be sure to keep those statements outside of your #if block.

One last thing on this: if you're using Visual C++, you can also use a single line of code that reads #pragma once to accomplish the same thing. This line specifies that the header in which it is located should only be included one time in a build. Most #pragma directives are compiler-specific, though, so you'll need to use #if..#endif if you're not using Visual C++, or if you may work with your code on a different compiler one day.





Next : Creating Libraries