Warning, more rambling.
Let me see if I can put this in perspective and in a linear fashion.
One of the first things I did when I began my program was to instantiate my objects at the global level. This is a preferrence of mine because to do otherwise obligates me to create some functions at some of the higher call levels where I have to pass objects to the functions. To me that forces me to take more of a procedural than an object oriented approach. That does, of course, depend on how complex your code needs to get. I believe in letting the objects do most of the work, mostly for keeping code ncapsulated and reuseable rather than having odd functions running around my code in an assortment of files.
I'll use a bitmap class as my example but it still extends to sprite and image classes and other classes as yet unwritten.
My bitmap class encapsulates a static integer called nextBitmapNumber that's set to '1' when initialized. When a bitmap object is instantiated I assign nextBitmapNumber to the bitmapNumber member of my class and increment nextBitmapNumber for use with the next bitmap I may instantiate. The natural inclination is to follow the assignment with a call to dbCreateBitmap () to have the GDK create one in it's system. But if I do this with an object that's declared globally it generates an exception because the DarkGDK () function hasn't initialized the GDK yet. Even worse, with the workarounds I've had to use, I found
that I can't declare a global GDK object with a dbDelete*() call in the destructor without exiting with an abend.
So my bitmap class is filled with lots of tests to make sure that it exists in GDK before using it. Otherwise it creates one. To me this is something of a waste. And with the intertwining of sprites and images it gets more complex when the sprite needs to know if the image object is valid or just assumes it is. I was having to declare the objects globally and then making calls to make sure that GDK had created its counterpart. If I fail to make that call then the image number that a sprite may expect to be valid may not be.
That said, I've worked out the following approach. My main.cpp looks something like this (give or take)
// Dark GDK - The Game Creators - www.thegamecreators.com
// the wizard has created a very simple 2D project that uses Dark GDK
// it can be used as a starting point in making your own 2D games
// whenever using Dark GDK you must ensure you include the header file
#include "DarkGDK.h"
#include "DarkGame.h"
void DarkGDK ( void )
{
DarkGame theGame;
theGame.Run();
return;
}
I then write the DarkGame class. The objects that I otherwise would have declared as global are now member objects of that class. This makes them available to all the methods that are part of the DarkGame class, essentially giving them a global presence and eliminting the need to pass them down to higher level functions. Since the object is declared inside the DarkGDK () function all the GDK functionality is established before the member objects are instantiated. The constructor for the class also takes care of all the other things that are otherwise set, like display settings, sync and a few other things indiginous to the game. Invoking the Run() function is like running main() in a regular program. I wish I knew how to create a template of this arrangement.
So if I declare a bitmap, sprite or image object under this approach I can afford to call dbCreateBitmap () (or dbSprite(), etc.) against the number I've assigned to it without having to anticipate an error. This pretty much eliminates the need to check for the validity unless I provide an avenue to delete it other than the destructor.
Okay, now on to the bitmap w/ sprite thingy. The current phase of my development involves laying out some roadway and I found hand editing was not only tedious but also rife with errors. I also discovered that some of my concepts required rethinking so early work at hand editing required a lot of reworking. So I've developed a program for creating the level layouts visually. I believe in letting the object do the grunt work. It helps cut down on the procedural code, breaks the code down into functional units and keeps the code available for reuse without having to keep track of a bunch of functions scattered about my development environment.
My map editor involves a grid on which I click start and end points for a road segment. To do this I created a Grid class that I derived from my Bitmap class. It includes the functionality to draw a grassy background, a grid with clickable intersections, drawing the road segments, deleting road segments, saving the layout to a binary file and loading a saved file. I thought I was finished but realized that I really needed to include the starting point for the vehicles, their startup delay and relative speed. For this I figure on doing a drag and drop. So I need sprites for the players vehicle and the other vehicles declared as objects in the Grid class along with matching images. I might also add some buildings, trees, some road blocks and the powerups. AAR, for each sprite I would need to specify the image and would need to rely on the image being valid. Under my old programming model I would have had some complications but under the new one I think I've eliminated some of the concerns I had.
I also had considered making a sprite class with an embedded image or even trying a special class that inherited from a sprite and an image class. But I dislike multiple inheritance.
Lilith, Night Butterfly