Sign in to follow this  

Game engine classes question

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Rather than having long convoluted source files I am trying to organize my engine a little better. This is my first attempt at a from scratch class based engine. Currently my code looks something like this. However I wanted to use a resource manager and an entity system. I also had questions on how data would get between the logic and other systems. I suppose I could have a game state class. Currently I am using no inheritance. Any one have any suggestions or links to good articles on engine structuring. Thanks.

Share this post


Link to post
Share on other sites
And WHY aren't you using any inheritance? Seems just dumb to me (not saying I'm a pro, but it does save me a lot of time, in a lot of things). And a Game state class is what I've used for this sort of thing, makes it easy to test for a good deal of things.

Share this post


Link to post
Share on other sites
I should have said "I'm not using any inheritance yet" meaning none of the classes in the diagram derive from each other at this time. Still trying to figure out the organization.

Share this post


Link to post
Share on other sites
1. Use inheritence only if needed.
2. Use singletons for Config, Console and other subsystems that don't need to have more than one instance.
3. Usually game logic is on top of the engine (uses an instance of the engine) and not a property of the engine itself.

Share this post


Link to post
Share on other sites
Quote:
Original post by Dekasa
And WHY aren't you using any inheritance? Seems just dumb to me.

That's a bit harsh isn't it? You're saying it's dumb for him to not use it, but don't explain why he should. As Rimio said, inheritance is just a tool - you don't use a screwdriver to hit nails.

Quote:
Original post by Rimio
2. Use singletons for Config, Console and other subsystems that don't need to have more than one instance.

There's been a lot of arguments on here about singletons.
If something doesn't need more than one instance, but no harm will come from having more than one, then don't use a singleton. Only use singletons when there is a requirement that limits you to only allowing one instance.


An idea for your entities: make some interfaces for things that entities can do (such as be drawn), and then make a base entity class that implements these interfaces along with any functionality that would be common to all entities (such as position/rotation perhaps)...

Then your renderer class can have a list of pointers to "Renderables" and your logic class can have a list of pointers to "Updateables" etc...

This also lets you render things that arent entities, because your renderer just deals with any class that implements the Renderable interface.

class Renderable
{
virtual void Render( const Renderer* )=0;
}
class Updateable
{
virtual void Update( float time )=0;
}
class Entity : public virtual Renderable, public virtual Updatable
{
...
}
class MyEntity : public Entity
{
...
private:
Texture myTexture;
Polygons myPolies;
}




It would be a good idea to use some kind of smart pointer for these entities though (because the renderer, logic and manager classes will likely all have their own pointers to shared objects.

Share this post


Link to post
Share on other sites
I think a good question related to this topic is how do you establish the lines of communication from game object to engine parts. For example, a game object (or entity, actor, etc...) needs some particular resource, say a texture. How should the object say "Hey! I need a pointer to GoblinTexture" ?

Do you pass it a reference to the particular resource manager in its constructor? Do you give it a central point of access to the subsystems somehow? This is something I have struggled with. I can break down and do it the "easy" way, but I am always trying to find a "better" way to establish this communication.

Share this post


Link to post
Share on other sites
class Entity
{
public:
void setTexture (Texture * tex);
void setModel (Model * mdl);

/* alternatively */
void init (Texture * t, Model * m);

private:
Texture * m_Tex;
Model * m_Model;
}


You should also think about using materials and such, and having textures assigned to them.

Then have Models that have the material assigned. Then all you need is setModel (modelManager->getModel ("animals.monkey")); or whatever.

ModelManager::createModel (Mesh * mesh, Material * mat);

Just some ideas.

Share this post


Link to post
Share on other sites
If you are going to be making a reasonably decent game, you will need to use inheritance. If you don't, you will be programming the same lines of code over and over for very similar tasks.

The structure you propose looks good. What you will also need is a structure for lights (point, spot, directional inherit theses :) and also for objects in your game. ie Base object -> player, enemy, vehical etc. Lots to inherit here.

When designing the physics, your structure will play a big role.

Share this post


Link to post
Share on other sites
Quote:

If you are going to be making a reasonably decent game, you will need to use inheritance. If you don't, you will be programming the same lines of code over and over for very similar tasks.

Inheritance is not the only way of solving the code-reuse problem, and it is certainly possible to make excellent games without using inheritance. You should not use it just because you think you have, you should only use it when it makes sense.

In the initial class diagram posted by the OP, there is nothing there that really needs to involve an inheritance hierarchy at all.

Share this post


Link to post
Share on other sites
Do not go overboard with inheritance either. It's a fine line I say. Our engine/game actually uses very little of it. Just where needed. Hodgman has a pretty good use of inheritance in his code example of an entity.

Also like thre3dee said, don't think of textures, think of materials. Materials are made up of texture(s).

Personal note, drop the CGame thing. We now have intellisense, it will tell you it's a class ;-)

Honestly, write a game, not an engine. You'll get something completed (engines are boring, boring, boring) and learn more about how to build an engine when its actually time.

Share this post


Link to post
Share on other sites
Quote:
Original post by Mike2343
Honestly, write a game, not an engine. You'll get something completed (engines are boring, boring, boring) and learn more about how to build an engine when its actually time.


But in order to write a game, you will need classes/managers like a resource manager, an entity system and so on, so I don't see the difference to developing the engine with the game.
Would you care to clarify that for me? It has always been a question that sat in my mind how you would develope a game without some sort of decent backend.

Share this post


Link to post
Share on other sites
Quote:
But in order to write a game, you will need classes/managers like a resource manager, an entity system and so on, so I don't see the difference to developing the engine with the game.
Would you care to clarify that for me? It has always been a question that sat in my mind how you would develope a game without some sort of decent backend.


I think this provides a pretty good explanation.

Share this post


Link to post
Share on other sites
Quote:
Original post by Julian90
I think this provides a pretty good explanation.


I dont necessarily agree with this article. It does have some good points but totally disregards the knowledge gained from writing ones own engine. Going out on a limb I suggest that a developer who writes his own backend technology/engine is going to be a more efficient game coder in the long term than a game coder who hacks and slashes together basic engine-like classes without thinking them through.

[Edited by - lubby on June 24, 2007 8:47:18 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by lubby
Quote:
Original post by Julian90
I think this provides a pretty good explanation.


I dont necessarily agree with this article. It does have some good points but totally disregards the knowledge gained from writing ones own engine. Going out on a limb I suggest that a developer who writes his own backend technology/engine is going to be a more efficient game coder in the long term than a game coder who hacks and slashes together basic engine-like classes without thinking them though.


Yes, but do we want to make a game or a mess? More often than not people who try make an engine and then make a game from it realise too late that they have horribly distorted the engines requirements and end up making a mess.

For most people starting out results are important to keep them confident and productive, and a game gives more immediate results than an engine.

Yes, there is much knowledge to be gained from making an engine. However, the inexperienced game engine developer is not likely to make a usable engine, that is the point of the article. If the ultimate goal is to make a game, then one should pursue that immediately and drop the notion of making an engine.

I would propose you finish a game and try "refactor" the engine out of the game, rather than try to hammer a game onto an engine you have made. I have had good success with this approach, I have a bunch of classes which I have copy/pasted into new projects with the minimum of pain after some substantial refactoring of the original game source.

In my opinion, of course [smile]

Share this post


Link to post
Share on other sites
@switch: actually, not using inheritance is a Good Thing™. Try studying software design patterns and you will see that they all prefer composition to inheritance.

Quote:
Original post by lubby
Quote:
Original post by Julian90
I think this provides a pretty good explanation.


I dont necessarily agree with this article. It does have some good points but totally disregards the knowledge gained from writing ones own engine. Going out on a limb I suggest that a developer who writes his own backend technology/engine is going to be a more efficient game coder in the long term than a game coder who hacks and slashes together basic engine-like classes without thinking them through.


Just tell me how you can be efficient when you keep reinventing the wheel. Of course one has to know what is going on in the backend but writing an engine for each game you develop is like re-implementing the standard library every time you boot up your C++ compiler; it's a complete waste of your time.

Writing an engine is also not a good thing for beginners; although the might actually learn from it, they will end up with one horrible and unmaintainable piece of software that nobody ever wants to use, is far from reusable and will just give you a headache.

When creating a game it is often better (and cheaper) to buy a prefab engine and modify that to your specific needs, re-implementing the whole thing is a long and tedious project that will demotivate the team and only cause delays because your using unproven technology that might still be bug ridden.

The only reason one might want to build an engine is when the ultimate goal is to create the engine technology, not the game.

Share this post


Link to post
Share on other sites
Quote:

It does have some good points but totally disregards the knowledge gained from writing ones own engine.

What "knowledge?" The "knowledge" you gain by writing and engine and the "knowledge" you gain by writing a game (and perhaps later factoring out parts of an engine) are largely the same thing. After all, ultimately the end product is basically the same, is it not?

There are dangers inherit in trying to write an engine before you've written a game. First and foremost is the assumption that you know what you're doing when you don't have practical experience doing it -- and since you're working alone, without somebody more experienced to provide feedback, you run the risk of learning things incorrectly (remember, just because something works doesn't mean its a good way of doing something) that can stick with you for a long time.

Share this post


Link to post
Share on other sites
Quote:
Original post by jpetrie
Quote:

It does have some good points but totally disregards the knowledge gained from writing ones own engine.

What "knowledge?" The "knowledge" you gain by writing and engine and the "knowledge" you gain by writing a game (and perhaps later factoring out parts of an engine) are largely the same thing. After all, ultimately the end product is basically the same, is it not?

There are dangers inherit in trying to write an engine before you've written a game. First and foremost is the assumption that you know what you're doing when you don't have practical experience doing it -- and since you're working alone, without somebody more experienced to provide feedback, you run the risk of learning things incorrectly (remember, just because something works doesn't mean its a good way of doing something) that can stick with you for a long time.


You can get into "wrong" habits no matter which method you take. The only way around that is to read, google, and ask questions to ensure that you understand what it is that you are doing.

The true question here, is what is the person's experience level with programming in general? If they understand the language they are using and how to apply advance concepts to it, then working from the ground up can be a very productive learning experience.

Perhaps an even better way to go would be to try and reverse engineer some open source code. That will give you a much deeper understanding for how things work than just placing your code on top of someone else's mysterious black box.

You will not see results as quickly, but if you test as you develop, then you will be able to see your work progress. For some people this is all the motivation they need. The ability to see that a method works and to understand why is a great accomplishment.

Furthermore, the quick turnaround to pretty graphics isn't the only way to go. Sometimes the greater lessons in life take time to acquire.
Quote:
Original post by jpetrie
What "knowledge?" The "knowledge" you gain by writing and engine and the "knowledge" you gain by writing a game (and perhaps later factoring out parts of an engine) are largely the same thing.

Writing the engine teaches you which dependencies are truly required and which ones are unnecessarily injected. Writing the game on top of someone else's engine just teaches you how someone else solved it, but it will not explain why. Unfortunately, sometimes the "why" was to save development time, or to use some other preexisting library/code. Shortcuts are generally not very good lessons to learn.

Furthermore, the possibility that your first engine will not be usable isn't that bad. Especially given the fact that any begginer project is going to subpar in one way or another. Regardless, the knowledge and understanding gained from the project is likely to be far more valuable than the results of the project itself.

Share this post


Link to post
Share on other sites
Quote:
Original post by switch
However I wanted to use a resource manager

Please avoid the manager "concept" it is a cheap shortcut. Although if you want your project to work now, and plan on learning the details later, then that approach can help.

Regardless, you will often find much greater (and very useful) flexibility by defining I/O methods separately from the objects that need I/O. You also should not group unrelated classes together simply because they all need I/O. Here is an example of the pattern I am working into my engine.

Stream stream.open("some file");
Object obj;
Loader load(stream,obj);
// use object
Saver save(stream,obj);



Depending on how much flexibility you need you can change that pattern. If you will only ever use one type of stream, and you are guaranteed to load everything by file name, then you can sacrifice that flexibility for a simpler design such as:

Obj obj;
Loader load(obj,"some file");
// use object
Saver save(obj,"some file");



You could also combine Loader and Saver into the same object, but that will not reduce the amount of code that you have to write and it will only reduce flexibility.

*A note on streams: You may or may not have a need for it, but treating a buffer in RAM or a unique file system as stream can be very useful.*

Regardless, the lesson here is that most design choices are about trade offs of flexibility, maintainability, development time, and performance. Although when it comes to performance, it is very important not to prematurely optimize, and do not assume that your way is faster if you have not profiled it. Performance should be one of the lower priorities on your scale.

Also, I would suggest a similar pattern for rendering as well, as there tends to be a lot of data unrelated to render able objects that are needed for rendering. Because of that, I would strongly suggest separating the complexities of rendering from the renderable objects as much as possible. Here is one example solution:

Renderer renderer;
// set up rendering specific parameters in renderer
Mesh mesh; // just an example of a renderable object
// perform any mesh specific routines, maybe animation routines
renderer.Render(mesh); // render the mesh using the Renderer



Of course this too employs trade offs, however it does preserve a good degree of orthogonality. Also, note how this solves the issue of mesh to renderer communication. The renderer directly accesses the mesh, allowing it to get all the data it needs.

That is the key to flexible code that will not have to be refactored/rewritten a million times.

An orthogonal design is one where things that are unrelated to each other are free to vary independently of each other. For example, the color of a sheet of paper should not determine which kinds of paper airplanes it can be folded into. Just as the way in which a mesh animates it vertices, should not affect the ways in which it may be loaded into memory.

Share this post


Link to post
Share on other sites
I think in this case Resource Manager is the correct term to use. It manages resources. I do agree people use "managers" far too often in engines though. But in this case the name fits. Even if you make a templated manager for each different resource you'll use, or like us a central one it works. We don't have a AudioManager/SoundManager class, we have an AudioSystem class. Gets people thinking the right way. The naming of classes is quite important, least for us as we prefer self documenting code.

Here is something, off topic in a way, that I found helped a lot. We removed all Get/Set functions. For example:

void SetX();
float GetX() const;

We just changed it to:
void X();
float X() const;

The compilers smart, it figures it out. We just found it more intuitive. But of course do what feels best for you as you learn.

Share this post


Link to post
Share on other sites
Quote:
Original post by Mike2343
I think in this case Resource Manager is the correct term to use.

If you are unnecessarily injecting dependencies and breaking orthogonality then you are likely subscribing to an inferior design.

In general (99.9% of the time), details that vary independently should be independently defined where ever this is possible.

Share this post


Link to post
Share on other sites
Quote:
Original post by switch
However I wanted to use a resource manager and an entity system.

What does "manager" means? [smile]
I mean, I smile, but that's still a dead serious question.

Share this post


Link to post
Share on other sites
Quote:
Original post by Emmanuel Deloget
Quote:
Original post by switch
However I wanted to use a resource manager and an entity system.

What does "manager" means? [smile]
I mean, I smile, but that's still a dead serious question.


Thank you. Apparently someone understands. Of course someone just had to down rate me for disagreeing with them. SMH.

Share this post


Link to post
Share on other sites
Quote:
Original post by T1Oracle
Writing the game on top of someone else's engine just teaches you how someone else solved it, but it will not explain why.
The suggestion being made is not the use of someone else's engine, but rather adjusting the goal of the project to "make a game" instead of "make an engine". The components of a typical engine are still being made but it is approached from a different perspective with generally more well defined requirements.

Share this post


Link to post
Share on other sites
Quote:
Original post by PaulRTC
Quote:
Original post by T1Oracle
Writing the game on top of someone else's engine just teaches you how someone else solved it, but it will not explain why.
The suggestion being made is not the use of someone else's engine, but rather adjusting the goal of the project to "make a game" instead of "make an engine". The components of a typical engine are still being made but it is approached from a different perspective with generally more well defined requirements.

Where does the OP state any of that? Do you speak for him??

The original posts asks about an engine, no where does it mention a game. Wanting to make an engine is just as worthy a goal for a noob as wanting to make a game. I personally have more respect for someone who wants to make an engine, because that shows (IMHO) they have more interested in working and learning, than playing around.

Share this post


Link to post
Share on other sites
Quote:
Original post by T1Oracle
Where does the OP state any of that? Do you speak for him??
Certainly not, he doesn't say that.

I was talking about the suggestion made by jpetrie in both the linked article (which he wrote) and the comment to which you were responding in the text I previously quoted. The article certainly does not suggest the use of someone else's engine. That's why I pointed it out, because you were responding to him as if that were his suggestion. Jasper was however talking about the use of another engine, so yeah, it got kind of muddled.

Share this post


Link to post
Share on other sites

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

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this