Sol's Graphics for Beginners


(prebuilt win32 exe)

21 - Housekeeping

Before continuing on with the game building, we have to face the fact that the project has grown too large to be kept in a single source file - there's over 800 lines of code there! Thus, in this chapter we will split the game into several files before adding anything new to it.

This would also be a good time to refactor the whole codebase into classes, but we'll keep things simple, even though some of the things we're doing would make more sense as classes.

Start by making a copy of the game so far (16 - Level Data from File). Rename the copy to chapter 21.

The main.cpp currently consists of approximately 820 lines of code. Starting from the top, we have:

  • includes
  • some SDL objects
  • macros
  • the collectible structure definition
  • bunch of globals
  • level data enumeration
  • some global arrays
  • blending functions
  • primitives (circle, rectangle, tile)
  • printing functions (drawcharacter, drawstring)
  • collectible collision function
  • reset, init, deinit, render, and main.

Roughly speaking, we have definitions, data, graphics functions, game logic and the application framework.

First, add a couple of new files to the project, called graphics.cpp and game.cpp. Add the following lines to the beginning of both of the files:

#include <stdlib.h>
#include <string.h>
#include <math.h>
#ifdef _MSC_VER
#include "SDL.h"
#include "SDL/SDL.h"
#include "gp.h"

Add the new gp.h include line near the top main.cpp as well. We'll create the gp.h file in a bit.

Cut the following functions from main.cpp into the new graphics.cpp file:

  • blend_avg
  • blend_mul
  • blend_add
  • drawcircle
  • drawrect
  • drawtile
  • drawcharacter
  • drawstring

After this first move, our main.cpp has shrunk to about 600 lines. The biggest function we have in main.cpp is the 'render' function, as most of our game logic happens in that function.

Cut the following functions from main.cpp into game.cpp:

  • collectiblecollision
  • reset
  • render

Rename render() to rendergame().

Back in main.cpp, add a simple render() function which calls rendergame(). We'll come back to this function to add rendering calls to the menus, etc, later on.

Now the main.cpp is at about 300 lines, which is much more manageable.

Trying to compile at this point will only give you errors about the missing gp.h file. That will be our next task. Add the gp.h file to the project.

Start the gp.h by moving all of the macros - that is, #define lines - from main.cpp to the gp.h file. Under the macros, move the leveldataenum enumeration, and under that, the collectible structure.

To make things a bit tidier, you may wish to create dividers in the header file, such as:

// Structures

Now we've moved all "intangible" definitions to the header file, and our main.cpp is down to around 230 lines. If you try to compile now, you'll be greeted by a flood of error messages related to functions not finding their data or other functions.

First, let's make the global data accessible to all of our source files. Copy (don't move) all of the globals from main.cpp to the end of the gp.h file. Next, prefix all of the line with 'extern', like so:

extern int gLastTick;

Four of the global variables will require special attention. First, remove the "= NULL;" from the gJoystick variable. Then, remove the dimensions from gLevel, gFontOfs and gFontWidth, like so:

// Level data
extern unsigned char gLevel[];

// Offset of character data per character
extern int gFontOfs[];
// Width of character data per character
extern int gFontWidth[];

Now we're down to relatively few errors when compiling. What's left is to declare our functions extern, as well.

Paste the following lines at the end of the gp.h file:

extern void collectiblecollision();
extern void reset();
extern void rendergame();
extern unsigned int blend_avg(unsigned int source, unsigned int target);
extern unsigned int blend_mul(unsigned int source, unsigned int target);
extern unsigned int blend_add(unsigned int source, unsigned int target);
extern void drawcircle(int x, int y, int r, int c);
extern void drawrect(int x, int y, int width, int height, int c);
extern void drawtile(int x, int y, int tile);
extern void drawcharacter(int x, int y, int character, int blend);
extern void drawstring(int x, int y, char *s);

After this, the code should compile and link correctly. If not, make sure you've saved all files, and try again.

Next we'll see a tremendous improvement to the gameplay as we're 22 - Adding the Dots on the Ball..

Having problems? Improvement ideas? Just want to discuss this tutorial? Try the forums!

Any comments etc. can be emailed to me.