# Game engine architecture

This topic is 4591 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
Instead of letting the the topical classes interact with each other, have a game class which act as an supervisor. Something like this:
// Inside the Game-classwhile( true ){    _player.update( delta_time );        // Player is derived from PhysicalObject    _physics.applyPhysics( _player ); // the _physics-object takes care of checking                                      // and compensating for collisions    if( _input.keyPress() == key_up )        _player.setState( accelerate );}

This solution has worked for me so far. It may not be the best, but it is easy to follow and it doens't require complex relations between classes.

##### Share on other sites

First, I believe that you should make your modules (physics, terrain, input etc.) as generic as possible, not aiming at a specific game but enabling as much capabilities as possible. This way you would have generic modules at your disposal.

The next thing to do is to really treat these as black boxes and NEVER rely on one another. The input module will never know about the physics, and the physics module will never know about the terrain. How do you do it? You have another module - your ENGINE module. This one interacts with all the modules but keeps them from interacting between themselves. The interaction takes place based on familiar data structures. For example, you should have a structure, defined in a common level (like the engine for example), that will describe an input event. You will also have a structure that will define a physics outcome of some sort, etc. This will behave like a contract between the engine and its modules.

This way you can do the following:

1. As long as the contracts remain intact, you can change the engine and the modules as much as you like, and nobody gets hurt.
2. If you do need to change a contract, you will know that you have at most caused a change in a link between the engine and N modules. These changes can sum up to N links - but they will never be N^2 links (which might be the case when "everybody is talking to everybody").

I believe this is a fair way to go about doing things. Naturally it has its own flaws, like centralism, and having data defined by the engine instead of the client modules. However, as I believe that the main client here is the engine and the modules are just its pawns, I think this might be a good way to go.

Waiting to hear other ideas :-)

##### Share on other sites
Hmm, I actually hadn't considered simply removing a level from the hierarchy. That's not a bad solution actually, but what bothers me about it is that there is no categorisation. It feels correct to have certain aspects of the engine dealt with entirely separately.

I suppose the topical nature of some classes is the cause of the problem they try to resolve as they add an unnecessary level of abstraction which I had never really considered removing before. I would worry a little however with this method, that too much work is being taken on by the game supervisor class.

Well, certainly the best answer I've seen to this question so far, but I'd appreciate anyone else confirming that this is how they deal with things or pointing out any negative implications to this method, not that I want to pick fault, but I want to make sure I'm doing things as well as I can :)

Thanks,

Steve

*EDIT* DadleFish, thanks for your reply also! That suonds just like the kind of interface method I was thinking of myself. I think I've certainly got some thinking to do now, it's been great to see both opinions so quickly :)

##### Share on other sites
Hey,

I've been having similar problems, hopefully if i explain how my engine works it may help.

Until recently i've been structuring my classes so that they can interact with each other, this was bad for 2 reasons:

1. The code gets messy quickly
2. Code could not be easily reused

So when I decided to give an engine another go I did some research, the most useful articles I found were the Enginuity series by Superpig. They describe a number of complex techniques, of which I selected a few. I used his Singleton class, and the Task Based approach to the engine. This means that Input / Sound / Video etc. are all tasks which have Start/Update/Stop method. They can be suspended and resumed, and are controled by a kernel class.

So now in my engine, anything that I only need a single instance of is derived from the Singleton class. This includes: the game log, the main game timer, the texture manager, the physics environment, the kernel, and the application class.

Anything that needs regular updating in the game loop is derived from the task class; the physics, video, sound, input etc.

Although my engine is still in its early stages, everything is tidy, bugs are easier to find and most importantly everything is modular and can be dropped into another project.

Another tip is: Do not be afraid of static functions and classes. Use them wisely but remember they are there.

Hopefully that might give you some ideas,

Luke.

##### Share on other sites
What you can do is, first declare a mother class, let's say the "game" class and then have child classes underneath it and all messages go through the mother class, which makes it understandable.

Sorry for the vague description... but if you need more info, please feel free to mail me: thedatabandit@hotmail.com

Cheers,
-Zubair_

##### Share on other sites
Quote:
 Original post by databanditSorry for the vague description... but if you need more info, please feel free to mail me: thedatabandit@hotmail.comCheers,-Zubair_

...or we can use this forum!

##### Share on other sites
Forgive me if I'm being dense, but the Enginuity articles, while being very good, and something I'd certainly like to implement, actually do not help with allowing easy communication between classes? Perhaps that wasn't the intention, but I still ask, as if it does have relevance to my query, it would certainly help if I understood exactly how it is relevant!

So far, I think the engine interface style class seems the best solution... that way, we still have to go through the process of building the links... but all the code for the links is in a common place. This means that if we do have to add in new modules to an engine and remove old ones, we simply slot them in, add any new links in the engine interface class and the newly added classes, and we needn't touch a line of code in that which has already been created unless it needs to interact in a different way with the new component. If it does need to interact with the new component, all rewritten code will revolve around the engine interface class only.

Take our previous example, say we wish to add in floor-plate switches to our moving around a map situation. We create a new class to represent interactive map elements. With the suggested system, we simply pass a EngineInterface pointer to the interactive objects class containing the floor-plate switch object. Now the switch needs to query the physics module to determine if anything is pressing on it. We implement in our EngineInterface class a function such as IsAnythingPressingOnSwitch(). We then let the EngineInterface worry about obtaining that data via querying the character engine for all characters within a given radius to determine if they are on top of the switch or not, and the switch never even has to know how the character class works.

If we then in future include a class representing objects that can be pushed onto the switches, we simply alter the EngineInterface IsAnythingPressingOnSwitch() to also check with the ObjectManager class for objects within radius. We never need ever touch the switch class in any way to let it know how to deal with the existence of the new class.

So anyhoo, I guess I'm simply restating what was said previously by DadleFish, by way of a more solid example, but it seems to make sense to me :P

Cheers,

Steve

*EDIT* please ignore the fact that switches and boxes are both interactive elements that should be in the same class (little mistake of mine!)... I think the point is still made ;)

##### Share on other sites
As others mention, pretty much any time you have a behavior that needs two [or more] other behaviors to work, it belongs in a class/object "above" those two other behaviors.

To the example:

Quote:
 Take our previous example, say we wish to add in floor-plate switches to our moving around a map situation

Okie dokie.

Quote:
 We create a new class to represent interactive map elements.

I'm not certain that you can abstract all the different interactive map parts this way, and I'd start by making a base interface class, not a full fledged class; but that's an implimentation detail.

Quote:
 With the suggested system, we simply pass a EngineInterface pointer to the interactive objects class containing the floor-plate switch object.

No, bad. What you do is have the EngineInterface pointer 'create' the interactive object and put it into a list, or have a mediator [which is a level above the engine] create the interactive object and attach it to the upper level part. [or better, see below] Remember, ownership flows down hill.

You might still need a 'parent' or 'owned_by' pointer in the lower class, but the idea is to make the 'lower' classes handle less and less problems so that the lowest can handle a simple problem easily. The 'higher' classes combine these until a really big problem, like a game, becomes managable code.

Quote:
 Now the switch needs to query the physics module to determine if anything is pressing on it.

And then you've dependancy again.

Personally, I would try something like this:
engine contains map.engine creates floor plate, adds to map.engine creates image/model representing floor plate,  engine links image data to floor plate data [boost::weak_ptr, reference, bald ptr], adds to lower rendering module, forgets it.engine creates physics representing floor plate, engine links physics object callback/trigger to something it owns...  (likely a member function of the engine floor plate)[boost::function, boost::weak_ptr] adds to lower physics module, forgets it.

Then the rendering part can focus on rendering the model, and only knows/cares about the model. The physics can focus on 'triggering' the plate, and ignore how it's rendered. The engine knows about both, but can safely ignore how the rendering and triggering is done. Those are problems solved by 'lower' parts.

##### Share on other sites
So essentially, what you're saying is that we should create seperate models of everything, i.e. the physics part of the engine should deal with physics and physics only.... the AI engine AI only such that if the AI needs to access terrain data, the terrain data should be included in the AI model as a fundementally separate entity from the actual terrain data.

I can see the benefits of such a method, but surely this causes just as many problems? Okay, so the engine knows that there are 3 versions of the terrain, 1 in the AI class, 1 in the physics class and 1 in the rendering class, but we now have to ensure that 3 separate models of the terrain are kept synchronised with one another and 3 times the memory consumption. I suppose to solve the synchronisation issue every change must be made in the base engine on a base object, which would then look after updating the other representations of its data.

The more I think about it, the more appealing this method is, but I'm still not 100% convinced yet... some more food for thought though.

Thanks!

Steve

• 10
• 16
• 14
• 18
• 15