# Game Engine Design Questions

This topic is 4319 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

##### Share on other sites
To be honest, if you're interested mainly about designing a game engine sucessfully, rather than getting a fast game engine, I wloud suggest C#. It has the flexiblity of C++ (to a degree, but when you need the advanced features, you could always drop back into C++). C# is nice for designing engines and systems imo, because all the framework is down for you.

You mentioned that you want extensibility in your engine. In this case I can recmmomend some design books, especially "Head start design patterns." Have you seen the Enginuity series of articles? At the moment, these are generally the best for engine design.

##### Share on other sites
acid2,

I have looked at C# but I really would prefer to stick to C++ right now. My ultimate goal is to design and program a stable 2D game engine using DirectX. Of course, I probably won't accomplish that the first time around but that is okay. I do believe, however, that if I design it on paper and get a clear understanding of how it will work then I will have a much better (and easier) chance at programming it successfully.

I have read the Enginuity series, as well as other articles here and elsewhere, and have somewhat of an understanding on how it works. However, the same thing happens with every article I read: I kind of understand the end product but I don't see the design process. IE, what went on in the guy's head when he designed the Enginuity engine? This is why I want to design my own and need help getting started. I want to fully understand exactly how and why everything in my engine works all while avoiding simply copying someones code.

P.S. It wasn't my intention to sound rude if indeed I did.

Thank you,

Jerry Smith
Iota Beta chapter of Sigma Kappa Delta

##### Share on other sites
So here is what I have so far (in general terms, still not "designed" in my opinion):

I will have a kernel that will handle tasks (this idea is based off of the Enginuity series). It will allow me to add a new task, remove a task, pause a task, resume a task, kill all of the tasks, and execute the application loop.

Timer, Input, Audio, and Video will be tasks. Any other tasks will most likely be game specific.

Any suggestions on the specific components and how they fit together? I have a sheet of paper out and i'm trying to draw this on a flow chart and it just isn't clicking. Can anyone point me to another engine's flow chart? Or give me tips on how each component flows into the next?

Thanks,

Jerry Smith
Iota Beta chapter of Sigma Kappa Delta

##### Share on other sites
The interaction between game engine components is mostly the only real difficulty in designing an engine. Each individual component is quite simple if it is isolated.

The Task/Kernel approach by superpig works real well for me. I just made a post describing how my engine works at the thread Design Issues: Making systems know about eachother. Bare in mind that I have a "small scale" engine, i.e. this is not top of the line, but as hobbyist game framework, it is very functional.

##### Share on other sites
I've been working on a 2D "engine" with OpenGL/SDL for about a year and a half now. You will probably find that certain setups work well for some things and not others. Like my setup was originally designed for an action-styled game. I'm now adding a lot of GUI over the top of it for a strategy game which changes the basic way i deal with the system.

But long story short, start with a basic method to update/draw everything. You can hang everything else off of that. You will probably find that your update and draw routines are the ones that get used the most (if you profile your code, you'll see what i mean), so spend the time to make them work cleanly and fast before expanding the rest of your system.

Resource management and drawing are also things that i think should be nicely encapsulated. With a decent resource manager, you can put all of your image, sound, font loading and dumping in one place and ideally not deal with it anymore.

Drawing should be encapsulated so you don't have to worry about [insert API] calls. Ideally, you want it to be this simple:

image.Blit(x,y);

That helped my system a great deal.

Audio is pretty much it's own thing and usually runs in it's own thread, so you don't have to worry too much about how to integrate that.

If you plan an action game, collision detection is going to be one of the biggest hurdles for you. It's almost always ugly and can be done in a bewildering number of ugly ways ;-) Give it a lot of thought before you code it.

##### Share on other sites
A good design will always try to solve the requirements. Nothing more, nothing less.

Creating the utopian design is just that.

Before starting, define the requirements, limitations and features of your game.

For example:
Requirements:
- level based aproach
- tile based
- discrete unit positioning
- small world (maximum map has 500x500 tiles)
- interpolated unit movement
- asynchronous user input
- cut-scenes
- persistent user settings
- multi-player support
- 30 fps on Radeon 9xxx series
- Positional stereo sound
- Event driven sound score

Limitations:
- directx 9.0c or higher
- written in C++
- maximum of 200Mb of ram, 128Mb of video ram (or as implied by Radeon 9xxx requirement)
- distributable over internet (you can only afford hosting 5000 Mb per month)
- Supports mouse and keyboard (not necessarily joystick, gamepads, etc.)

Features (these can be scaped at any time if you run out of time/money/resources):
- Particle effects
- Optimized LAN support
- Support for player created units

After you do this, simply develop the design that fits these requirements, while considering the limitations, and adding as many features as you can.

I intentionally put "support for player created units" under features. While modability "could" be put under requirements, it adds a lots of upfront work for little immediate benefit.

Do not, ever, put everything under requirements. The less you have there, the better chances of success you have. If you're doing this for the first time, each feature in itself will take a huge ammount of time, and will prove to be completely mis-designed by the time you complete several requirements. But this will allow you to keep a close check on what you're trying to acomplish, how far you are, and where to focus next.

##### Share on other sites
To Enselic,

Each task will be it's own class derived from the abstract interface iTask.

cKernel's execute method will begin a loop. It will run all of the tasks in the list in order of priority and then remove any dead tasks from the list. The next iteration of the loop will then begin. Each iteration of the loop will be one frame.

So it is established that a task will be considered any process that needs to be run every frame. For example, video updates, sound, input, and timer functions.

so far what I have looks kind of like this (I am not that good with flow charts, so if my flowchart doesn't match the text i have in this reply please help me correct it):

http://img154.imageshack.us/img154/9974/flowchart0oz.jpg

To everyone,

Thanks so far for your help.

Thanks,

Jerry Smith
Iota Beta chapter of Sigma Kappa Delta

##### Share on other sites
Quote:
 Original post by dean1012My questions are as follows:1) Where to start?

Logging. You're writing code that likely will not work, having a reliable logging interface [and other in-engine debugging tools] will help greatly.

##### Share on other sites
To Antheus,

Thanks for your advice. I never thought about it that way. I suppose I have a small list of requirements then:

Requirements:

tile based maps
movable/animated character (most likely needs to be timed)
audio capabilities
keyboard and mouse input capabilities

Limitations:

DirectX
C++

Features:

scripting capability (Lua)
3D EAX Audio

Thanks,

Jerry Smith
Iota Beta chapter of Sigma Kappa Delta

##### Share on other sites
To leiavoia,

This is my ultimate goal (to have it as simple as image.blit(x, y)).

To Telastyn,

Ahh yes, thanks for reminding me about logging.

To Everyone,

So far, i have what is including in my last large reply (with the flowchart) that covers tasks and the kernel. Separate from that, I have cLog that will handle logging and some sort of resource manager (cResourceManager perhaps). The kernel and logging class will be singleton objects.

Just a couple of questions:

1. Am I understanding the Kernel/Task process correctly? (Through my last text and the accompaning flow chart)

2. Should I make the engine multithreaded? If so, how do I incorporate that into my design and which parts of the engine should and should not be in their own thread (i'm new to threads, done very little work in them)

3. In regards to the resource manager, should I have just one single class (cResourceManager) that handles the loading, unloading, and managing of every type of resource (images, audio, etc...) or should I have multiple classes (cImageFile, cAudioFile, etc...) that handles the loading of their specific resource type and have a resource manager class (cResourceManager) that brings them all together and manages them?

Using the first method, i'd have one huge class. Using the second method, i'd have a bunch of specialized classes used just for loading and unloading specific resources and have a central class that allows the user to add/remove/access resources. Any suggestions on designing the resource manager?

4. How do the other classes of the engine relate to the kernel and its tasks? For example, as seen by the flowchart, the kernel and its tasks are closely related. However, the logging, resource managing, memory managing, etc... are important parts of the engine too. How can I draw them onto the flow chart?

I am heading to class now until 4:00 P.M. CST. I will be back then to check up on replys and post some more myself.

Thanks,

Jerry Smith
Iota Beta chapter of Sigma Kappa Delta

##### Share on other sites
Quote:
 Requirements:tile based mapsmovable/animated character (most likely needs to be timed)audio capabilitieskeyboard and mouse input capabilities

Will the maps be fixed size or flexible?
Can you keep them all in memory, or will you need to load them from disk due to memory constraints? How much memory do you have at your disposal?
Will they be flat or will you support layering (multi-level buildings)?

What kind of audio will you use? Sound effects, static sound tracks? Interface effects? What kind of format will you need for the quality/size you want to provide? mp3 format? wav? wma?

Animation will need to provide time-frame independant animation. Which most likely means different timer than the one used for sound playback (most lilely not a separate timer, but part of rendering loop). It will also be different from world timers. Each of these would most likely fall into different type completely.

How will animations be stored? Will you be using 3D models, 2D rendered 3D sprites, hand-drawn sprites, what kind of perspective will you support?

Quote:
 Limitations:DirectXC++

Which directX? From which version on. This is extremly important question.
Which C++? Which compiler. Difference between MVS 6 and 2005 is huge. Standard compliant C++? Policy on use of C code? External libraries?

Quote:
 Features:scripting capability (Lua)3D EAX Audio

This is good.

You do not need to over-specify, and even adding many features or requirements is not bad. The more you cover upfront, the easier and intuitive the design will become.

##### Share on other sites
Quote:
 Original post by dean1012To Enselic,I am currently reading your post now. So let's see here.[...]

Yep, it sounds and looks as you've got the hang of it. I do recommend though that you experiment a bit with this. I've been tweaking the engine for a year on and off. It takes a while to get a good balance of what things Tasks should do and what things that should not be tasks.

Incorporating a Game State Manager helped me get rid of a lot of tasks. Now game specific code are encapsulated in GameStates, so basicly one single task is updating all game states, intsead of one task per game objects which was my first solution.

Quote:
 2. Should I make the engine multithreaded?

I'd say no. Definitly no. Especially if this is your first engine. Multithreading is so much more than just executing things at the same time.

This subject is considered quite hardcore, and I think it will be for quite some time.

Quote:
 3. In regards to the resource manager, should I have just one single class (cResourceManager) that handles the loading, unloading, and managing of every type of resource (images, audio, etc...) or should I have multiple classes (cImageFile, cAudioFile, etc...) that handles the loading of their specific resource type and have a resource manager class (cResourceManager) that brings them all together and manages them?

I definitly think you should have different interfaces so to speak for audio and images etc. However, I have not good advice wether you should let all of these resources derive from a single base Resource object. One main reason I guess would be to have a unified memroy handling process, but since I use C# I don't have to deal with that. I know superpig implemented some kind of garbage collector in his series, but as I said, I didn't have to implement one.

I think your engine will be useful no matter which way you choose to tackle this. I mean the only thing audio and textures etc have in common, is that they take up memory, so keeping them totally separated would not be a big problem I think.

Quote:
 4. How do the other classes of the engine relate to the kernel and its tasks? For example, as seen by the flowchart, the kernel and its tasks are closely related. However, the logging, resource managing, memory managing, etc... are important parts of the engine too. How can I draw them onto the flow chart?

I don't have valuble advices here [sad]. Since C# with MS tools offers great debugging features and garbage collection, I havn't implemented these things myself.

##### Share on other sites
Enselic,

Thanks for the advice and encouraging comment. I will avoid multithreading, as per your advice and as for the resource manager I think i'm going to follow something along these lines:

cAudioFile

cImageFile

cResourceManager
-will provide higher level methods to handle all resources
-ideally the user of an engine will only need to use cResourceManager
-singleton

I am still not sure how it would work though

cResourceManager would have to have some interface to the load and unload method of the appropriate class but that seems kind of redundant. but again I suppose not.

cAudioFile::Load() for example would have the detailed code to load the file
cResourceManager::Load() would simply need to know the type of file and to call the appropriate method

after a file is loaded its reference would be added to a list that can be played later.

example:

I could then do cResourceManager::GetSingleton().PlayAudio("test.mp3");
or something to that effect.

Any ideas for a better solution anyone? or does this sound good?

Finally, as far as the game state system goes,

I have a fairly good idea of making game state machines (i have one now that i created as a prototype). however, i'm not sure how to integrate it with the kernel/task design. I will list my thought process and maybe someone here can help me get rid of that "mental block"

2) the input task runs gathering the current input (say the right arrow key), it would then invoke the character's move method, moving the character to the right by so many pixels so long as collision doesn't happen

4) the video task runs updating the screen thus physically moving the character (the right key in step #2 just changed the characters position)

that leaves a few tasks still for the game states or tasks: AI, Quests, etc...

But if I chose to incorporate a game state system where would I stick it? IE, when would it get run? I can only think of one solution:

Make a game task that runs between the audio and video task and will call the game states in the appropriate order. Why is this better than creating tasks rather than states? Is it faster?

Thanks,

Jerry Smith
Iota Beta chapter of Sigma Kappa Delta

##### Share on other sites
Antheus,

Thanks for the attention to detail. Let me retry this:

Requirements:

tile maps (dynamically allocated/flexible)
all maps will be loaded in memory at once
128 MB RAM
mp3 format audio
2D character sprites using sprite sheets
2D top down

Limitations:

DirectX February 2006
C++ (MSVC 2005 Pro)

Features:

Lua Scripting
3D EAX Audio

As for the timer, I am still very confused on what exactly i'm going to do for the timer. Does anyone have a tip on how to create the timer class? IE, how do I make a timer? Should I make it so that I can create multiple timers?

For example I could have:

cTimer which is the actual timer

then I can have cTimerManager that would keep a list of cTimer

I am really just confused on three things:

1) how to keep time

2) how to handle more than one timer (a timer for movement/animation, timer for the frames, timer for audio - which you mentioned but I don't quite understand yet, etc...)

3) how to organize the timer (as mentioned above, should I have one class, a class and a manager class, etc...)

I'd appreciate any more help!

Thanks,

Jerry Smith
Iota Beta chapter of Sigma Kappa Delta

##### Share on other sites
Quote:
 1) how to keep time

This depends on circumstances.
Animation timer will most likely be part of rendering loop. Each time you render the scene, you will calculate the time passed, and use difference from last screen to calculate the movement. While not a timer in that sense, it does keep track of time.
Logical timers might apply to game elements. Power-up expires after 5 seconds. No need to mess with render loop, just define it as 5000ms.
Sound timers might be used (depending on your sound API) to fill sound buffers with new data.

Quote:
 2) how to handle more than one timer (a timer for movement/animation, timer for the frames, timer for audio - which you mentioned but I don't quite understand yet, etc...)

Core timers for movement and animation will probably be part of main game loop as described above.

You will usually not need a timer for frames, since that will be hardcoded in the main render loop, and there is very little reason not to do so. Usually you render as fast as possible, and maybe limit FPS to screen refresh rate or half that. This will be handled by DirectX or enforced by your main game loop.

For other timers, you could use a thread.

I once used a semi-accurate timing method using priority queue. Each entry in the queue would represent an event (object, ID, token, ...) and a timestamp, when the event should occur. Priority queue was ordered by timestamp, so first event dequeued would be the one to trigger soonest.
The main loop, which had sufficiently high granularity (several ms for each pass) would check the priority queue, and dequeue all events that have expired (their timestamp was in the past compared to current time). While this was not perfectly accurate, it served the purpose well with little to no overhead.

For some tasks, such as the sound buffer I mentioned (if applicable), you could use a separate thread. This should prevent buffer starvation in cases of slow computers/fps drop and keep sound from stuttering.

Quote:
 3) how to organize the timer (as mentioned above, should I have one class, a class and a manager class, etc...)

For common timers you will usually have one class. Since timers are asynchronous by definition, using the same callback mechanism for different types of timers is usually a good choice, since the implementation is consistent.

In the example I used before, this is how the timers would be implemented. On each render pass, call Execute() on every timer whos timestamp less than current timeStamp.

class TimerTask {  TimerTask(long expirationTimeStamp);  void Execute();}class PowerUpTimer: TimerTask {  // each implementation hard-codes power-up expiration time  ....}class AudioBufferTimer : TimerTask {  // Task defaults to 500ms update  AudioBufferTask(SoundSample *ss)}class AnimationTimer : TimerTask {  // Expiration time is set to currentTime,   // so it executes on every check}AnimationTimer::Execute() {  // getCurrentTime()  // update locations of characters  // ...  // add this timer back to queue,  // so it gets executed next time}

While this works out nicely from OO design, it might not be the most efficient or accurate (neither is really a problem, but just for the sake of argument).

You could of course define two types of "timers". One that is time based, and one that triggers on every frame. Then you could have a "TimerManager", that addTimer and addPermanentTimer or something similar.

##### Share on other sites
Antheus,

I like your ideas, just let me restate it. Please let me know if I understand what you meant. I'm going to have a Timer Task that will be called once per frame. It will call every timer (animation, audio, etc...) that needs to be called.

I am just confused on two things

1. How do I actually get the current time?

2. I am confused as to how this would work. Last time I wrote a game it was in Allegro using Allegro's timers. I had to setup a timer for walking (it was my only animation) and as i pressed the arrow keys, it would use that timer to slow down the animation. I just don't see how it is working in my head, I suppose I should worry about just finding the current time first.

Thanks,

Jerry Smith
Iota Beta chapter of Sigma Kappa Delta

##### Share on other sites
Quote:
 Original post by dean1012cAudioFile-will load and unload an audio filecImageFile-will load and unload an image filecResourceManager-will provide higher level methods to handle all resources-ideally the user of an engine will only need to use cResourceManager-singleton

How come you need to store both the images and sounds(possibly meshes aswell) in a single class?

I don't see any advantages with sound, because I'd assume you would only have one SoundManager class.

For textures I can see a bit of an advantage if different rendering classes might want to share a texture, but I see that as unlikely, eg MeshesDraw and LandscapeDraw classes arn't really going to share a texture.

I guess also its easy to pop it all into a seperate thread to be loaded.

I asking because I am also designing my game(not really an engine) for the umpteenth time and trying to decide on some of the designs.

thx

##### Share on other sites
johnnyBravo,

first let me say i'm glad i'm not the only one learning from this thread.

I am working on the rough design, of course, of my engine. My understanding of things are a lot better right now than when this post was started but as you can see I still have questions that are unanswered in this thread (they will be answered in time though).

I chose to design the resource system that way simply because that's the way I think of it. I figure it this way:

when i'm writing a game, i need to access only very high level methods in the game. I shouldn't need to be bothered with the low level nitty gritty things when writing my game (that is the whole point of an engine, i believe). So I figured that in keeping with that idea, all methods that are "nitty gritty" such as loading/unloading files, directx stuff, etc... should be in their own class (cAudioFile and cImageFile in the example used). They will be accessable by the engine but preferably unknown to the game. the cResourceManager class would act as a very high level interface to those classes so the game doesn't need to use them. Does this make sense?

The only other way I can think of to do this is to remove the cAudioFile and cImageFile classes and just incorporate their methods into cResourceManager but that allows the game to access more than what it needs.

I am sure that there are many bugs (and probably major design flaws) in my resource manager design but that's why i'm posting my ideas here hoping for enlightened discussion. Currently my largest worry, however, is the timer. I still don't fully understand it.

Thanks,

Jerry Smith
Iota Beta chapter of Sigma Kappa Delta

##### Share on other sites
Quote:
 Original post by dean1012when i'm writing a game, i need to access only very high level methods in the game. I shouldn't need to be bothered with the low level nitty gritty things when writing my game (that is the whole point of an engine, i believe). So I figured that in keeping with that idea, all methods that are "nitty gritty" such as loading/unloading files, directx stuff, etc... should be in their own class (cAudioFile and cImageFile in the example used). They will be accessable by the engine but preferably unknown to the game. the cResourceManager class would act as a very high level interface to those classes so the game doesn't need to use them. Does this make sense?

I see, that makes alot of sense for an engine.

With my design i'm trying to make seperate self contained classes for each aspect of the game, eg Sky class, will load its own textures(btw I mix dx9 code with game code) and be loaded by my Main class as a Drawable.

Where as the SoundManager would be loaded just as a Component. Difference being Sky would have functions such as onLost, onReset, onDraw, and Sound would only have onUpdate.

Then I can get rid of one of these components on a whim without it affecting any of the others.
Eg instead of the Phyics class calling soundManager->playSound(), it would just add an entry to the data store from my Main class(all components and drawables plug into the Main class) which the SoundManager would read and remove it, when it was its turn to be updated.

Quote:
 Original post by dean1012however, is the timer. I still don't fully understand it.

Right now I just put the timer in my 'Main' class 'double getTime()' which returns the amount of time that has past in seconds. And I use that in my movement calculations eg

obj.positionVector += obj.velocityVector * main->getTime();

btw My main class contains:
-d3d device
-window handle
-time
-all game data stored in a std::map (eg "objects" might store another map which might contain another map with something like "missiles" which would store a std::vector of Missile class)
-components (but arn't global)

##### Share on other sites
johnnyBravo,

What is the code for getTime() though? is it a standard function or did you make it?

Thanks,

Jerry Smith
Iota Beta chapter of Sigma Kappa Delta

##### Share on other sites
//initdouble time = 0;_int64 timeFrequency;QueryPerformanceFrequency((LARGE_INTEGER*)&timeFrequency);_int64 timeCount = 0;_int64 timeLastCount = 0;QueryPerformanceCounter((LARGE_INTEGER*)&timeCount);//updatetimeLastCount = timeCount;QueryPerformanceCounter((LARGE_INTEGER*)&timeCount);time = double(timeCount-timeLastCount)/(double)timeFrequency;				if(IsIconic(hwnd)) {//minimized	time = 0;}

##### Share on other sites
johnnyBravo,

ahh, I see - so make a singleton timer class, call cTimer::GetSingleton().Init() when the program is opened, then use cTimer::GetSingleton().Update() to retrieve the elapsed time since the previous update in seconds. Am I correct in this understanding? I could then use that one timer class/function to handle movement and if needed to slow down FPS (i had to in allegro, not sure about DirectX?). If I understand all this correctly, that makes things a whole lot easier.

BTW keep in mind i'm making a 2D game engine.

I am currently working on a flowchart in Visio. When I get far enough in it i'll post it on here for review.

Thanks,

Jerry Smith
Iota Beta chapter of Sigma Kappa Delta

##### Share on other sites
A singleton is probably fine, although I don't really use them.

All my components have a pointer to the main class which keeps the time in mine.

fps, frames per second? Right now I just let them run as fast as the refresh rate allows, Although I may limit the number of frames depending on the refresh rate later, I think i heard something about not rendering as many frames as possible because it is just a waste, but im not sure.

How come you had to slow them in allegro? and whats allegro, just an api similar to sdl?

##### Share on other sites
johnnyBravo,

well I believe a singleton would be in best order since it seems that I only need one timer. It'd be equivilent to using a C style function as far as I know.

Allegro is a 2D game library. It includes rendering capability, input, timer, etc... I had to limit the FPS using a timer in allegro because if I didn't the game loop would run way too fast (every allegro tutorial you find introduces timers for that reason really early on). It caused input to work too fast and animation to look like walking spasms. I was expecting the same from DirectX but apparantly I don't need a timer for those reasons.

Thanks,

Jerry Smith
Iota Beta chapter of Sigma Kappa Delta