• Advertisement

Archived

This topic is now archived and is closed to further replies.

Very quick engine design question

This topic is 5039 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

I am planning an engine right now, and i am trying to go for a very organized engine. What would be wrong with the following line of code? Would it be slow? Engine->SubSystems->TextureObject->CreateTexture(&WaterTex); That looks very organized but it also looks very slow. I guess i would only be calling those type of functions at the initalize phase, because in runtime, i would just do WaterTex.UseTexture(); What do you guys think, please give me advice. Thanks "What we do in life, echos in eternity" -- Gladiator

Share this post


Link to post
Share on other sites
Advertisement
It seems convoluted. I dont think speed would be an issue. You would have nightmares tracking down all of the memory access errors your going to encounter by exposing all those pointers.

Here are a few design philosophies i adhere to:

- Isolate everything
- Keep interfaces simple
- Be consistent (especially with naming)
- Automate simple tasks (they are easier to program and easier to reuse)

In this case, you want to keep your texture creation code interface simple - the separation by modules should keep things fairly organised. Its much easier for example to do this:


#include "texture.h"

void use_texture(void)
{
tex_img_typ image, sepia_img;
tex_typ texture, sepia_tex;

image = tex_load("c:/img.bmp");
texture = tex_create(image);

//convert the original texture to sepia

sepia_img = tex_sepia(image);
sepia_tex = tex_create(image);

//release images from memory

tex_free(image);
tex_free(sepia_img);
}


Using simple commands, the user of your engine can do many complex tasks easier because the interfaces are so simple.

This doesnt mean that all the functions in your engine are going to be simple. They can be as complex as you want; the tex_load function for example can at first only support bitmaps if your pressed for time. Then later on, you can easily add support for jpegs, tga, ect because the interface to that function is fairly universal to use and doesnt have to be changed.

Another good design technique is to provide only references to objects in memory stored somewhere else by the engine. This is how opengl manages textures. The idea is that you can potentially add support for extra chanels (like an alpha channel) without changing code already written.



[edited by - llvllatrix on May 6, 2004 9:05:28 PM]

Share this post


Link to post
Share on other sites
Speed wouldn''t be an issue if your only doing all those dereferences during initialization.

However...ever heard of over-engineering a problem? IMHO you''d be better off using namespaces instead of separate objects for your Engine and SubSystems:

Engine::SubSystem::Object->Function(...)

Where Engine is whatever your engine name is and SubSystem is the name of a subsystem, for example:

MyEngine::Display::TextureObject->CreateTexture(&WaterTex);

Even then, unless your dealing with a fairly large engine I think that you could suffice with not bothering with the SubSystem namespaces. Another point, what''s wrong with using

WaterTex = new MyEngine::TextureObject;

There are reasons that the approach your using may be a Good Thing(tm) for an engine design, but is it necessary for YOUR design?

Share this post


Link to post
Share on other sites
Thanks for the replys.

My C++ is a bit fuzzy on this kind of thing:
MyEngine::Display::TextureObject->CreateTexture(&WaterTex);
WaterTex = new MyEngine::TextureObject;

Would doing MyEngine::Display::TextureObject, that would return the default instance of TextureObject right?
Like for example, If i dont have a instance of MyEngine declared, you could still do MyEngine::Varible = 5; right?

Am sorry, i am really fuzzy on those :: operators. I have only ever used them for static varibles in a private section of a class though.

Please can someone give me quick run through of them, i really dont want to read an entire tutorial when i can probley deduce what it does from a little base knowledge.

So if anyone could clear that up.

Also on llvllatrix reply, that code that he did, if i did it that way, wouldnt that get rid of the whole OOP programming? Can you explain that to me?

Also on the :: operator. Just a short quick thing would do me wonders. Thanks alot

"What we do in life, echos in eternity" -- Gladiator

Share this post


Link to post
Share on other sites
quote:

Also on llvllatrix reply, that code that he did, if i did it that way, wouldnt that get rid of the whole OOP programming? Can you explain that to me?



Yep You dont always have to use classes to do something in c++. Why do you think most games are written in c? Use what you need to get the job done easiest; that way you can spend the time where you need it: debugging your code

Share this post


Link to post
Share on other sites


I think it would be more like this.



class cGame
{
public:

struct sConfig
{
char data[256];
char name[20];
};

cGame();
bool SetConfig(sConfig *config);

};


void dosomething()
{
cGame::sConfig *newconfig = loadconfig("file");

cout<<"Config?: "<SetConfig(newconfig)<}


Actualy I think I''m probably wrong. I''d like to be clarified also please.

}

Share this post


Link to post
Share on other sites
lol, you would make a game a class? Are you expecting to have one or more instances of a game? jk (...yes i know about singletons...)

Whenever you approach a design issue, especially in the real world, you evaluate the advantages and disadvantages of implementing a design a certain way.

Classes work great when you need multiple instances of the class; they were originally designed as a tool that associates functions and data into one object. The constructor and destructor also lend themselves to doing some nifty things. This doesnt mean that you should use classes because they are avaliable, and in fact there are many cases where using classes can hurt your program.

This also doesn''t mean that you abandon procedural based programming because its old; it is in fact still very powerful. I typically use a synergy of both procedural (typically for interface) and class based programming methods (for the complex implementation of the interface).

A bit on game design:

Games are wierd programs to write because you are trying to mix a whole bunch of different elements into one. This makes them one of the hardest type of programs to write. Classes (specifically the way they are used in MFC) do not lend themselves to typical game design because the whole inheritance "this is a type of that" does not apply. One big reason using classes can hurt you here is because inheritance limits code reuse; to reuse one segment, you have to inherit the entire tree.

Instead you have to start from the ground up; you need to build a whole bunch of different subsystems that do a basic job. For example one will do sound, another graphics. You keep building higher level systems that continue to integrate these subsystems into one until you arrive at the game. Procedural based programming lends itself easily to this.

For example lets say we used opengl to produce the example of the texture loading system i had above. If we wanted to make a model that used the texturing engine, all we have to do is include and use the appropriate functions. The if we want to create a character management system, all we have to do is include the model system as a subsystem of the new one and bingo.

Share this post


Link to post
Share on other sites
Not sure if I understood that earlier post SkinnyM ... so maybe this doesn't answer anything.
It sounds a little as if false pride prevents you from taking a look at the basics again

The :: operator is called the scope operator.

I think this part of the cplusplus.com language tutorial might be interesting.
Section 4.1 - Classes

Quote:
The scope operator (: specifies the class to which the member being declared belongs, granting exactly the same scope properties as if it was directly defined within the class.
For example, in the function set_values() of the previous code, we have referred to the variables x and y, that are members of class CRectangle and that are only visible inside it and its members (since they are private).

Maybe honayboyz reply already cleared that up ... !?

---
If nothing works the way it should ... maybe you need a break!?
Get cracking and double-check the switch statements!!
Tolop|Andyart.de

[edited by - Clueless on May 6, 2004 11:43:30 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by llvllatrix
Classes work great when you need multiple instances of the class;


Hmmm there''s a situation where I like to use singleton classes: to handle subsystems that depend on each other. Say the texture manager depends on the display subsystem ; both depend on the logging utilities...

Singleton classes help creating objects in the right order without actually "writing the right order" in your code (and add a bit of ref counting and you''ll also delete everything in the right order as well...). And that adds flexibility to your code.

Note that it can impact performance as well... Using a singleton for the "logging class" is a good idea ; using one for the "class that draws a particle" is not (stupid example, but you''ll get the idea


SaM3d!, a cross-platform API for 3d based on SDL and OpenGL.
The trouble is that things never get better, they just stay the same, only more so. -- (Terry Pratchett, Eric)

Share this post


Link to post
Share on other sites
quote:
Original post by SkinnyM
Would doing MyEngine::Display::TextureObject, that would return the default instance of TextureObject right?
Like for example, If i dont have a instance of MyEngine declared, you could still do MyEngine::Varible = 5; right?

Not quite, take a look at this code:

namespace MyEngine
{
int Variable;

namespace Display
{
class TextureObject
{
// Your TextureObject class...

}
}
}

Now namespaces aren't classes and they can't be instantiated, so there will never be an instantiated object of type MyEngine or Display. Instead, they act as a way of providing separation of code. For this example, your TextureObject would be within the Display namespace which is within the MyEngine namespace. This means that someone else using your code could also have their own TextureObject so long as they place it in a different namespace. A namespace can containing anything you would be able to put globally, so you can have classes, functions, variables, etc contained within the namespace. Because I've declared Variable in the MyEngine namespace in the above code, you can go MyEngine::Variable=5;, but Variable is really a global variable that isn't part of a class that can be instantiated. To accessing 'stuff' inside a namespace you need to use the scope resolution operator, ::. Accessing your TextureObject would be done as
MyEngine::Display::TextureObject...rest as normal for a class  


quote:
Am sorry, i am really fuzzy on those :: operators. I have only ever used them for static varibles in a private section of a class though.

In this case, you use the :: again because the static variables aren't instantiated with the new objects of that class. Namespaces could in a way be considered as a class with ALL its members declared as static.

quote:
Also on llvllatrix reply, that code that he did, if i did it that way, wouldnt that get rid of the whole OOP programming? Can you explain that to me?

As has already been said... Yep
If you want to use this approach you can place all of your 'normal' functions inside of namespaces in order to help you organize your code. You then access them using the :: operator just as with my above example.


Joanus D'Mentia

[edited by - joanusdmentia on May 7, 2004 7:20:51 PM]

Share this post


Link to post
Share on other sites
man, you guys shure like to complicate stuff.

Basicly what i do is i store all textures/shaders in one shader class, the same with objects and everything else.

I automate everything and then some.
if i want to load a object full with textures and other important stuff i just call

CFdraw dm;
dm.loadObject(ENT_LOAD,0,"object.cfmd");

CFdraw is my renderlist class, it takes a list of different rendering steps and runs them.
It allso loads the stuff into static variables so once loaded i can access it from anywhere in the code.

---------------------------------
For an overdose of l33tness, flashbang.nu

Share this post


Link to post
Share on other sites
I really cant go over all the ins and outs of game/demo design; its a complicated beast. I can tell you that before I started doing large projects, I was consistently overusing classes to do jobs that a procedural based design would''ve solved and made more flexible.

If you want a bit more of this stuff check out:

http://www.gamedev.net/reference/list.asp?categoryid=45#115

It''s from a guy who worked on duke nukem forever...which sorta makes it questionable i guess...but I suggust you use your own discression and consider what he''s saying; it makes sense.

quote:

man, you guys shure like to complicate stuff.

Basicly what i do is i store all textures/shaders in one shader class, the same with objects and everything else.

I automate everything and then some.
if i want to load a object full with textures and other important stuff i just call

CFdraw dm;
dm.loadObject(ENT_LOAD,0,"object.cfmd");

CFdraw is my renderlist class, it takes a list of different rendering steps and runs them.
It allso loads the stuff into static variables so once loaded i can access it from anywhere in the code.



Of course i didnt say to completely abandon classes; Im just saying that there are cases where classes really arn''t the tool for the job.

quote:

I automate everything and then some.



From my experience it seems that more automation is inversely preportional to flexibility. This should be obvious; its the reason why opengl is so powerful to begin with.

This is a really good topic to discuss; try to keep it going.

Cheers,
- llvllatrix

Share this post


Link to post
Share on other sites
quote:

man, you guys shure like to complicate stuff.

Basicly what i do is i store all textures/shaders in one shader class, the same with objects and everything else.

If this is as it sounds you''ve just demonstrated how NOT to use OOP, and have probably made things more complicated than they need to be.

quote:

if i want to load a object full with textures and other important stuff i just call

CFdraw dm;
dm.loadObject(ENT_LOAD,0,"object.cfmd");


And how is that any less complicated? Behind that loadObject() function you still need to load and manage your textures, models, etc.

quote:

Original post by lc_overlord
It allso loads the stuff into static variables so once loaded i can access it from anywhere in the code.

This ISN''T a good thing. For small projects you can get away with it but the bigger you get the more unmanagable and bug-prone this will become.

quote:
Original post by llvllatrix
From my experience it seems that more automation is inversely preportional to flexibility. This should be obvious; its the reason why opengl is so powerful to begin with.

I think this is where OOP shines. With a well designed class hierachy I think that both can be achieved. Any desired changes to the default functionality can be achieved by deriving from the existing classes. While the same is possible without OOP by using function pointers, I find it far easier to manage using OOP.

Share this post


Link to post
Share on other sites
quote:
Original post by llvllatrix
From my experience it seems that more automation is inversely preportional to flexibility. This should be obvious; its the reason why opengl is so powerful to begin with.



that is if you want total controll of everything that happens.
Beleve me, there is no need if it's programed right.
Shure it's hard coding it from the begining, but hey, in the state my engine is now i can make a small(but still good) game/demo in under a day.

quote:
Original post by joanusdmentia
If this is as it sounds you've just demonstrated how NOT to use OOP, and have probably made things more complicated than they need to be.



Who ever said that pure oop is the best thing that ever happend.
infact if you use to much oop there is a large probobility that you are going to feed the wrong variable somewhere(because you don't know witch one your sending) and everything is going to hell.

quote:
Original post by joanusdmentia
And how is that any less complicated? Behind that loadObject() function you still need to load and manage your textures, models, etc.



Yes, but so do you, mine does it automaticly, does yours?

quote:
Original post by joanusdmentia
This ISN'T a good thing. For small projects you can get away with it but the bigger you get the more unmanagable and bug-prone this will become.



True, but that is allso true for everything else.
But my engine was designed for flexibility, it was designed so that i could just take any part of the basecode i needed and use it in a project.
It was allso designed in a way so that i could develop different parts of it in other places.
This meant that all my classes had to be selfcontained in some way, it should not depend on any parant class using it allthough it might use other classes) and it has to be global so that all parts if the code can access the information(those parts that it is alowed to access anyway), without having to pass that class around.
Statics does the job just fine.

---------------------------------
For an overdose of l33tness, flashbang.nu

[edited by - lc_overlord on May 9, 2004 8:20:39 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by lc_overlord
infact if you use to much oop there is a large probobility that you are going to feed the wrong variable somewhere(because you don't know witch one your sending) and everything is going to hell.

This has absolutely nothing to do with OOP.

quote:
Original post by lc_overlord
Yes, but so do you, mine does it automaticly, does yours?

sceneGraph.AddNode(new GameObject("filename.ext"));  

If that's what you call automatic, then yes. ANY decent design won't have you typing the same 10 lines of code every time you want to load an object. I still fail to see how you think yours is any less complicated.

quote:
Original post by lc_overlord
True, but that is allso true for everything else.

Yes, but with varying degrees. Larger projects will always be more complicated, but a good design will make this less of an issue.

quote:
Original post by lc_overlord
But my engine was designed for flexibility, it was designed so that i could just take any part of the basecode i needed and use it in a project.
It was allso designed in a way so that i could develop different parts of it in other places.
This meant that all my classes had to be selfcontained in some way, it should not depend on any parant class using it allthough it might use other classes)

This can all be achieve without using global variables (which you effectively have with publicly accessible static variables), whether the design is OO or procedural. As for dependencies between classes making a variable static makes no difference, the class will still need to know the definition of the static variable's type regardless.

quote:
Original post by lc_overlord
and it has to be global so that all parts if the code can access the information(those parts that it is alowed to access anyway), without having to pass that class around.
Statics does the job just fine.

And how do you ensure that parts that aren't allowed to access it don't?


[edited by - joanusdmentia on May 9, 2004 10:38:29 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by joanusdmentia
And how do you ensure that parts that aren't allowed to access it don't?

It's a secret. =)

I actuarly don't have any reason to restrict information that mutch, i just keep some internal stuff private cause i can (like counters and such).
But the thing is that no other code than the code in the class can freely read/write/see/everything in those statics, so any data i want programs to read i just pass along trough special functions(witch there arn't that many of), it's a neat arangement that works verry well.

quote:
Original post by joanusdmentia
If that's what you call automatic, then yes. ANY decent design won't have you typing the same 10 lines of code every time you want to load an object. I still fail to see how you think yours is any less complicated.


that specific function is perhaps not.
But i have worked hard to make it extra clear, intuiative and easy to code, that has to count for something.
But then again it's not finished, i am allready in on my third revision of the renderlist system, and im pretty shure i will have one or two more revisions.
(the first two was just an large array of numbers i passed to the render list).

the only thing i can say is that your way looks frightenly simmilar to the gamebryo basecode, and i still don't get it (nore does any of our programmers) after we have been working on it for a month or so.

---------------------------------
For an overdose of l33tness, flashbang.nu

[edited by - lc_overlord on May 10, 2004 4:05:06 AM]

Share this post


Link to post
Share on other sites
I think theres a common misconception that you encapsulate and hide everything so that some idiot programmers dont come along and screw everything up.

If you''ve ever worked on a BIG project you''ll find out soon enough that the idiot programmer that you''re trying to defend against is yourself...

Share this post


Link to post
Share on other sites
quote:
Original post by lc_overlord
It''s a secret. =)

Good answer, but I ain''t signing no NDA

quote:
But i have worked hard to make it extra clear, intuiative and easy to code, that has to count for something.
But then again it''s not finished, i am allready in on my third revision of the renderlist system, and im pretty shure i will have one or two more revisions.
(the first two was just an large array of numbers i passed to the render list).

Heheh, I''ve lost count of the number of times I''ve restarted writing my engine

I guess it comes down to personal preference as well. If your not used to a particular style then its naturally going to be more difficult to get their head around.

quote:
the only thing i can say is that your way looks frightenly simmilar to the gamebryo basecode, and i still don''t get it (nore does any of our programmers) after we have been working on it for a month or so.

Can''t say that I''d even heard of the Gamebryo engine before, although I recognized the games on the site. Not sure what skill level you and your programmers are, but keep in mind that it is a commercial engine intended for professional game developers. I''m not saying that indie developers are sub-standard, but as a general rule we don''t have the same level of experience. If a design of mine looks like that a commercial engine then I''ll take that as a compliment

Share this post


Link to post
Share on other sites

  • Advertisement