|
There are some basic concepts and ideologies behind the way this library was
created that you should learn before moving on to the actual nuts and bolts of
it.
File Structure
The following is a view of all the header files in the library and how they
are logically grouped from the bottom up. As you can see, your application need
simply include <gs_lib.h> to access the functionality of the library.
gs_common
|
gs_debug
______________|___________________________________________
| | | | |
gs_directdraw gs_directinput gs_directmusic gs_winstandard gs_timer
gs_surface gs_keyboard gs_directsound | |
gs_font | | | |
gs_deviceenumerator | | | |
|______________|_______________|________________|__________|
|
gs_helper
|
gs_lib
|
your application
Singletons
The way the library is designed is based for the most part on the idea of "singletons". As the name
implies, there can only be one instance of a singleton object in an entire application. Typical
examples of singletons are the keyboard or mouse on a system, or a file manager in an operating system.
In this library, the singleton objects are the following:
DirectDrawObject
PrimarySurfaceObject
DirectInputObject
KeyboardObject
DirectSoundObject
DirectMusicObject
MouseObject
So what does this all mean? How does this change the way I use these objects? Simple:
the constructors
for these objects are not public, so you cannot do this:
DirectDrawObject DDrawObject;
The compiler will not allow this because it cannot construct this object. So how do you get access to
this object? Simple, you use a special member function called "Instance()" to retrieve the single
instance of this object as follows:
DirectDrawObject *pDDrawObject = DirectDrawObject::Instance();
This may seem more complicated, but there are many advantages to using singletons:
 | There is no way you can have more than one instance of a singleton object. |
 | You don't need to keep global variables nor pass a singleton to functions because you can
always use the "Instance()" function anywhere to retrieve it. |
The only disadvantage to using singletons is that their destructors are not automatically called, so
to properly destroy them, you should call the "DestroyInstance()" member function. Of course, even
if you don't, the OS will clean up the unallocated memory, so this isn't a huge problem.
So now you know what singletons are and how to use them. The sample code shows how to
use them in more detail. After a while, you will become very comfortable with singletons so don't
worry about it if it seems complicated.
Object Creation
Nearly all objects in the library must be created through their
"Create()" member function. Some may argue that such creation should
be accomplished by the constructors of the objects; however, I opted for this
method because it allows you to have objects in the library exist as data
members of a class. If constructor parameters were required, then you could not
do this because C++ does not allow you to initialize data members directly (they
must be initialized in the constructor).
Debugging
A special debugging mechanism exists in the library in order to catch any
errors produced by the program or common mistakes that are made by programmers
using the library. This debugging mechanism is only available when the project
is compiled in Debug mode; in Release mode, I have made every effort to make the
program run as fast as possible by removing extra error-checking and debugging.
Thus, it is highly recommended that you compile in Debug mode during development
and only compile the release version in Release mode (naturally).
The debugging mechanism provides the following:
 | Every object created is given a unique identifier (ID) starting with '1',
unless the object is a singleton, in which case it's ID is simply
"--". |
 | When an error occurs, the application is killed and a message box appears
explaining the error and providing the object ID as well as the member
function in which the error occured. |
 | Certain events as well as generated errors are logged in a file called
"debug.txt" which can be found in the root directory of the
application. Although you can view this file with any text editor, it is
often easier to read it using the "GS Debug Viewer" available in
the \bin directory of the library. |
To log your own special events, you should place the following in your code:
#ifdef GS_DEBUG
DebugMsg(0, "Function", "Message");
#endif
|