Game Engine Design

Overview
To code your own gameengine can be hard at first. There is many things to think about. I will show you the basic idea of a gameengine, both as theory and code. However, if you are writing a large engine there will be many more things I won't show here. Also, I am an OpenGL coder and the examples I show uses OpenGL but the structure is the same. So what does a gameengine need? The first thing we might think about is graphics. So a graphicsmanager is needed. There is a lot of managers that we might use, but here I present some common ones:


 * Kernel : The central part of engine
 * Graphics : Takes care of rendering
 * Input : Handles mouse and keyboard events (during gameplay)
 * Camera : Speaks for itself
 * Console : Handles events when the console is active

Many people use a texturemanager too, which is good for DirectX but isn't needed with OpenGL (not at least the way I will show). The power of using managers like this is that every manager man talk to each other and tell them what to do without to much trouble.

Kernel
The kernel is instanced by the mainfunction and its constructor can be used to instance the other managers or we could use a init function, either way, the kernel is the central part of the engine and needs to be created first. We will use global pointers to all managers so a typical mainfunction would be something like this:

//Include all suitable headers
 * 1) include "include/config.h"

CGraphics *graphics; CKernel *kernel; CInput *input; CCamera *camera; CConsole *console;

int main(int argc,char* argv[]){ kernel = new CKernel;

kernel->run;

delete kernel; return 0; }

As you can see we have 5 pointers to different managers but we only instance the kernel as that is going to instance the others. Lets take a look at the prototype for CKernel:

class CKernel { public: CKernel; ~CKernel;

void quit; void run; private: bool running; };

We call the run-function which is a simple gameloop, but remember to instance the other managers first! In every .cpp file, not .h, you include extern CGraphics* graphics; if you need the graphics manager.

void CKernel::run{ while( running ){ input->handleInput; graphics->render; } }

Graphics
The graphics manager has a function to rendera a scene. It gets a list of objects from the kernel (not shown above) and renders them. If some cullingalgorithm is used it applies that before it renders. I suggest that the kernel holds three lists, for solid objects, transparent objects and lights. The managers culls all lists and sorts at least the transparent object list back-to-front and renders then renders them. A more advanced method is to apply culling and sort all objects into one list by something like this:


 * Solid objects
 * Shader
 * Texture
 * Transparent objects
 * Shader
 * Texture

By doing this we minimise objects rendered and statechanges. Switching a shader is an expensive change. An example of render: void Graphics::render{ std::sort( 		kernel->transparentObjects->list.begin,		kernel->transparentObjects->list.end,		BackToFront(kernel->transparentObjects->list) );

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW); glLoadIdentity; camera->use;

for ITERATE(kernel->lights){ (*(kernel->lights->it))->use; }

glPushMatrix;

for ITERATE(kernel->solidObjects){ (*(kernel->solidObjects->it))->render; }	for ITERATE(kernel->transparentObjects){ (*(kernel->transparentObjects->it))->render; }

glPopMatrix; SDL_GL_SwapBuffers; }

kernel->transparentObjects returns a pointer to a LIST-struct, which contains a STL-vector and its iterator, in this case the list of transparent objects. ITERATOR is a macro which is defined to iterate through a vector. camera->use applies the camera transformation to the current matrix and likewise *(kernel->lights->it))->use applies lightsources to the scene.

As OpenGL has to do with graphics this manager shoud initiate it.

Singleton
A singleton is a design pattern, see Singleton Pattern on wikipedia. A singleton is a class which should only have one instance. This is typiclly good for managers of different kinds since we only want one of them each. To simplify creation of managers each manager will inherit from a singletonclass. A typical solution to a singleton class:

template class Singleton { public: static T& Instance { static T theSingleInstance; //assumes T has a default constructor return theSingleInstance; 		} };

Every class that should be a singleton should inherit as this: class Kernel : public Singleton { //Rest of the prototypes here };