World Manager

Started by
16 comments, last by JWalsh 18 years, 10 months ago
Greetings, I am looking for a good approach to making a WorldManager class for handling all the entities running around the gameworld. At its most basic level, I expect it would look something sort of like this (it's a rough sketch, ignore the lack of error checking, public:, etc):
class WorldManager
{
	void Add(GameObject* gameObject)
	{
		m_gameObjects.push_back(gameObject);
	}

	void Remove(/*what sort of identifier should be used?*/);

	void Render()
	{
		for(iterator i = m_gameObjects.begin(); i != m_gameObjects.end(); ++i)
			i->Draw();
	}

	list<GameObject*> m_gameObjects;

}

Questions: 1. How would I go about extracting specific objects from the WorldManager? Say, if in a CheckKeyboardInput() function it's detected that the left arrow key is being held down so the one specific Player object needs to be located and moved left? What about specific types of objects? They'll all be GameObjects but what if I wanted to get a list of all the Bullet objects for collision detection? I would guess I need some sort of complex ID system? 2. Off the top of my head there ought to be Add(), Remove(), and Render() functions, what else would be useful/necessary? 3. Should stuff like the main Graphics, Input, and Sound objects also be stored in the WorldManager? Or maybe making them global would be better? I don't think I've ever put so many question marks in one post. Any ideas or suggestions would be appreciated.
Advertisement
load_bitmap_file,

This is going to be kind of a longish answer, primarily because I think its important for you to understand the principle I'm trying to pass along.

Principle: "Code by necessity"
Translation: Never add a single line of code until you need it. Every line of code you add should be added as a way to solve an existing problem you are trying to address. Programmers are inherintly problem solvers, and game programmers in specific. As such, we need to remember that solving problems are the main focus of our jobs.

1. You ask, "How would I extract objects from the WorldManager?," My response - why are you adding objects to the world manager to begin with? What problem are you trying to address that adding a WorldManager will solve?

2. You ask, "What interface does the WorldManager need? - add, remove, render, etc...," I ask, what interface do you need to solve the problem you're focusing on in question 1? If you're just creating a list to store all objects in the game, then you only need add, remove, and clear. If you're trying to make a render queue, then you need draw. Does it make sense to have a single manager be both an object list and a render queue - that depends on the problem you're trying to solve.

3. You ask, "Should stuff like the main Graphics, Input, and Sound objects also be stored in the WorldManager?," I ask, do you already have renderables, input objects, sound objects, etc...? And if so, where have you been storing them up to this point, and why is their current location no longer serving its purpose?

As you can see, I've not answered any of your questions directly, because there is no correct answer. The answer depends solely upon what problem you're trying to solve. More importantly, however, is that although I CAN answer this question for you in a generic fashion, it will not teach you to analyze a problem and come up with an acceptable solution.

So although the questions above may seem rhetorical, I can assure you they are not. If you post back the answers to those questions it will force you to think about them, help you understand them, and help me better understand the problem you are attempting to solve. It may be that you dont need a world manager at all...

Its important for you, if you're going to be a successful game programmer, to establish a strong problem-solving ability, and learn to only "code by necessity."

Cheers! - Look forward to hearing back from you!
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints
Quote:Original post by jwalsh
load_bitmap_file,

This is going to be kind of a longish answer, primarily because I think its important for you to understand the principle I'm trying to pass along.

Principle: "Code by necessity"
Translation: Never add a single line of code until you need it. Every line of code you add should be added as a way to solve an existing problem you are trying to address. Programmers are inherintly problem solvers, and game programmers in specific. As such, we need to remember that solving problems are the main focus of our jobs.

1. You ask, "How would I extract objects from the WorldManager?," My response - why are you adding objects to the world manager to begin with? What problem are you trying to address that adding a WorldManager will solve?


Well, the point of the WorldManager is to enable keeping track of all the game objects without resorting to making them all global. I posted about it a while ago, but to summarize: I am currently working on a 2d engine, not an actual game itself yet, but once the time comes, I thought about what the main game loop would look like. I figured it would be something like this:

InitializeAllTheGameObjects();while(it isn't gameover yet){	ProcessKeyboardAndMouseMessages();	UpdateEachGameObjectPositionAndStateAndWhatever();	RenderEveryGameObject();}CleanUpAllTheGameObjects();


<walloftext>So, basically I'm separating different tasks into different functions for organization, clarity, and whatnot. The problem here is in how do you pass around the data of all the GameObjects to each function? Each function here needs access to all the GameObjects data so being functions, they only "know" about variables inside their function scope, passed parameters, and variables in the global scope. I can't simply create everything in the local scope of the Initialize() function because everything else needs it. Having separate global variables for each and every game object would get messy very quickly ("g_player.Render(); g_dogs.Render(); g_buildings.Render(); g_...etc). So from the responses in the aforementioned thread and what I gathered from my thoughts, I would need some sort of a manager to hold all the GameObjects so they could be passed around in one neat package. For example, instead of having to say for each type of GameObject "whatever.Render()" I could iterate through each element of the list<GameObject*> and call Render() then let polymorphism do its magical work. Also, now I can simply pass a central WorldManager object into each function as a single parameter which solves the problem of sharing data across each of the functions.</wall of text>

Quote:2. You ask, "What interface does the WorldManager need? - add, remove, render, etc...," I ask, what interface do you need to solve the problem you're focusing on in question 1? If you're just creating a list to store all objects in the game, then you only need add, remove, and clear. If you're trying to make a render queue, then you need draw. Does it make sense to have a single manager be both an object list and a render queue - that depends on the problem you're trying to solve.


I guess my idea of a WorldManager would be a class with more than one responsibility, but as is my engine is not complex enough to require a separate RenderManger class. The only thing it would do is loop through each element of the GameObject list and call Render() for each. This list would have to be obtained from the WorldManager class, and there doesn't seem to be much of a point to do this.

Quote:3. You ask, "Should stuff like the main Graphics, Input, and Sound objects also be stored in the WorldManager?," I ask, do you already have renderables, input objects, sound objects, etc...? And if so, where have you been storing them up to this point, and why is their current location no longer serving its purpose?

As you can see, I've not answered any of your questions directly, because there is no correct answer. The answer depends solely upon what problem you're trying to solve. More importantly, however, is that although I CAN answer this question for you in a generic fashion, it will not teach you to analyze a problem and come up with an acceptable solution.


I have been working on a 2d engine, so I am merely defining the Graphics/Input/Sound classes at the moment. I created instances of these classes in my WinMain() to test them, but I merely declared/defined them inside the WinMain() because I did not need to pass them to any functions anywhere, because there isn't much reason to organize anything since I am just testing my classes/functions. Any halfway complex program, like a game needs to organize itself into functions and subfunctions and whatnot, but since the testing program is extremely simple, it does not need to worry about passing around data at the moment.

However, unlike making every game object global, making single global variables like: g_graphics, g_sound, and g_input would be no problem since there will only be one instance of those classes that I'll need. This is more of an opinion question I guess, since although making the Graphics/Sound/Input variables in a game seems perfectly feasible to me, I thought I might get some opinions on it.

Actually, now that I think about it a little more, I think having g_graphics, g_sound, and g_input variables would be a better solution than sticking them in the WorldManager for needless additional complexity.

Quote:So although the questions above may seem rhetorical, I can assure you they are not. If you post back the answers to those questions it will force you to think about them, help you understand them, and help me better understand the problem you are attempting to solve. It may be that you dont need a world manager at all...

Its important for you, if you're going to be a successful game programmer, to establish a strong problem-solving ability, and learn to only "code by necessity."

Cheers! - Look forward to hearing back from you!


If I understand correctly, I think that you posted because you thought that I didn't really know why I wanted a WorldManager class. As detailed above, I'm pretty sure I need one to solve the issue of passing around data to the various main-game-loop-functions, so it is rather necessary. Rather than why I need one I need to know how [smile].

*Whew*, that was a long post.

EDIT: Just to clarify, I still need help :0

[Edited by - load_bitmap_file on June 17, 2005 7:17:27 PM]
first of all you will want to sub class all your different game entities (lets call their base class Entity).
Now for creating each different entity you have a factory class which 'manufactures' whichever Entity when asked.
class EntityFactory{    public:        enum EntityID        {                STILL ,                // ....        }        Entity *New(EntityID id);   // I would return a shared_ptr<Entity>};

for your entity define the methods that you want for each subclass in the base (Entity) class, and those objects where the method has no affect just make it an empty function.
class Entity{    public:        virtual void Action(...);  // ignored by some parents and not overriden};

in the storage class (I usually call this something like EntityCollection, although thats a matter of taste) store the entities in a perl style hash map which maps each Entity to a name which is used as a handle.
        std::map<std::string , Entity*> entities;

Then in your code/scripting language you can now access your game objects by name.
        perform_some_engine_action("aeris" , 10 , 99 , 87)


This is fairly basic, but I hope it gives you some ideas on which to expand upon.
Well, instead of a list, as in the idea of an array, you could use a linked list to connect all of your objects. You can also look for resources on a scene graph, which is pretty much what you want, and (potentially) a lot more. As someone has mentioned, what you add to it depends on what you need. You seem to be searching for more of a "good way" to implement this, as opposed to what might it do, and what interfaces it might have. For this question, I do not have an answer as I am not experienced in this, except a little bit of research I have done myself recently (which I havent implemented yet).

It's kind of like the guy in I, Robot who says "My responses are limited, you must ask the right questions." Sometimes asking the right questions, or looking at things from a different angle, under a different light, will lead you to the best solution.
Quote:Original post by Genjix
first of all you will want to sub class all your different game entities (lets call their base class Entity).
Now for creating each different entity you have a factory class which 'manufactures' whichever Entity when asked.
*** Source Snippet Removed ***
for your entity define the methods that you want for each subclass in the base (Entity) class, and those objects where the method has no affect just make it an empty function.
*** Source Snippet Removed ***
in the storage class (I usually call this something like EntityCollection, although thats a matter of taste) store the entities in a perl style hash map which maps each Entity to a name which is used as a handle.
*** Source Snippet Removed ***
Then in your code/scripting language you can now access your game objects by name.
*** Source Snippet Removed ***

This is fairly basic, but I hope it gives you some ideas on which to expand upon.


I have a main base class called "GameObject" instead of "Entity" but it serves the same function. The EntityFactory, I don't have. Admittedly I only have a vague idea of what the Factory design pattern is supposed to do *looks at unopened copy of Design Patterns on desk* but I have not encountered any problems not using a Factory up to now.

Simply using a std::map to match up the identifier sounds like a good idea! I'll probably change it a bit to std::map<std::string, std::list<GameObject*> > though, so I can do something like this in the WorldManager constructor:
mapOfGameObjects[identifier].push_back(theNewGameObject)

I think this is a nice, simple solution. Thanks Genjix.

Quote:Original post by Bonehed316
Well, instead of a list, as in the idea of an array, you could use a linked list to connect all of your objects. You can also look for resources on a scene graph, which is pretty much what you want, and (potentially) a lot more. As someone has mentioned, what you add to it depends on what you need. You seem to be searching for more of a "good way" to implement this, as opposed to what might it do, and what interfaces it might have. For this question, I do not have an answer as I am not experienced in this, except a little bit of research I have done myself recently (which I havent implemented yet).

It's kind of like the guy in I, Robot who says "My responses are limited, you must ask the right questions." Sometimes asking the right questions, or looking at things from a different angle, under a different light, will lead you to the best solution.


By list I did mean a linked list. If I meant array I would say array [razz]. Also, from the wikipedia article on scene graphs, it doesn't really have anything to do with this. I suppose you could take away everything else except the utmost basic part of it, but then it wouldn't be a scenegraph anymore. The rest of what you said seems to be saying something similar to what jwalsh suggested. I gave a response to his post which explained what the point of it was.

Next, I don't know why you're quoting from "I, Robot" (the movie, not the book). The movie was horrible. Again, as I explained in my response to jwalsh's post I believe I am already "asking the right questions". "Looking at things from a different angle, under a different light" is very generic advice that could be applied to virtually any problem and doesn't exactly help much.
Actually scene-graph would be just what you need.
I have already posted on scenegraphs today already so you should be able to find that post quite easily.

What you seem to be trying to do is simply create a system to manage gameobjects, but your suggested design is really too simple. You should seriously think about scene-graphs, this means each game object can logically belong to another.

Splitting up the different kinds of operations (update and render etc) is definately a good idea. Using scene-graphs you could have a node baseclass (GameObject) with pure virtual functions Render, Update, Collide etc and simply fill in the functionality for different kinds of gameobjects. Each node would store pointers to its children (std::vector<*GameObject>) rather than having one huge list.

You can then use a scene-manager (WorldManager) which is the root of the scene-graph with different methods for rendering and updating and methods to add and remove from the scene and allow you to attach objects to other objects.
The scene-manager would also store the camera(if 3D) or just view-position(if 2D).

Creating an AppDevice class which stores all your different mangers (WorldManager, SoundManager, InputManager, GraphicsManager, NetworkManager) is one solution because then each pure virtual function of the GameObject base class would take a parameter to take a reference of the AppDevice which stores all the different managers. This means each node is responsible for using the adequate managers to render or update itself.

Of course iterating is a litte more complicated for scene-graphs I suggest you look at the visitor pattern and you can make the whole system more flexible using function pointers, double dispatch and such.
Bitmap,

Sorry I haven't been able to post, I'm at my folks for the weekend visiting for father's day, etc...I'll be back in town tomorrow night and post a more productive response. (I'm on dial-up right now)

As a basic statement, I want to post a response to both of you. Primarily, you're attempting to write a game engine having not written a game to go along with. So you're violating the basic rule of "Code by necessity."

As for your needing a scene graph, you dont need a scene graph, you dont need any of the "managers" because you have nothing to manage yet. Add your sounds and graphics objects, then add the managers as you need them.

And anyone who says "your solution is too simple, you need something more complicated," is frankly lying to you, and likely has never finished a project of their own, due to over-complicating the issues.

Always simplify the problem, never complicate it.

I'll post more tomorrow....I do hope I can pass along to you the importance of coding only by necessity.

Cheers for now, enjoy your weekend!
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints
Quote:Original post by dmatter
Actually scene-graph would be just what you need.
I have already posted on scenegraphs today already so you should be able to find that post quite easily.

What you seem to be trying to do is simply create a system to manage gameobjects, but your suggested design is really too simple. You should seriously think about scene-graphs, this means each game object can logically belong to another.

Splitting up the different kinds of operations (update and render etc) is definately a good idea. Using scene-graphs you could have a node baseclass (GameObject) with pure virtual functions Render, Update, Collide etc and simply fill in the functionality for different kinds of gameobjects. Each node would store pointers to its children (std::vector<*GameObject>) rather than having one huge list.

You can then use a scene-manager (WorldManager) which is the root of the scene-graph with different methods for rendering and updating and methods to add and remove from the scene and allow you to attach objects to other objects.
The scene-manager would also store the camera(if 3D) or just view-position(if 2D).

Creating an AppDevice class which stores all your different mangers (WorldManager, SoundManager, InputManager, GraphicsManager, NetworkManager) is one solution because then each pure virtual function of the GameObject base class would take a parameter to take a reference of the AppDevice which stores all the different managers. This means each node is responsible for using the adequate managers to render or update itself.

Of course iterating is a litte more complicated for scene-graphs I suggest you look at the visitor pattern and you can make the whole system more flexible using function pointers, double dispatch and such.


I'm still unconvinced. A scene graph simply isn't needed. I don't need a system of logically related objects or to add a camera to this thing. I'm going to have to agree with jwalsh here in that this seems to be adding needless complexity.

The AppDevice class on the otherhand sounds fine. It seems like a perfectly viable solution but I think the graphic/sound/input objects would be well suited for global since they'll be accessed a lot everywhere and there's only one of them, but that's just my opinion.

(Now in response to jwalsh)

Quote:Original post by jwalsh
Bitmap,

Sorry I haven't been able to post, I'm at my folks for the weekend visiting for father's day, etc...I'll be back in town tomorrow night and post a more productive response. (I'm on dial-up right now)

As a basic statement, I want to post a response to both of you. Primarily, you're attempting to write a game engine having not written a game to go along with. So you're violating the basic rule of "Code by necessity."

As for your needing a scene graph, you dont need a scene graph, you dont need any of the "managers" because you have nothing to manage yet. Add your sounds and graphics objects, then add the managers as you need them.

And anyone who says "your solution is too simple, you need something more complicated," is frankly lying to you, and likely has never finished a project of their own, due to over-complicating the issues.

Always simplify the problem, never complicate it.

I'll post more tomorrow....I do hope I can pass along to you the importance of coding only by necessity.

Cheers for now, enjoy your weekend!


If I understand you correctly, "Code by necessity" means to not program stuff you only think you need, but rather only the stuff you know you need, so if it turns out that what you thought you needed isn't actually necessary, you won't have wasted your time on code you'll never use.

However, I pretty much know that I will be needing a manager of some sort to pass around all the game object data. Another good rule of thumb is to design before hand isn't it? Projects where everything is done on the fly are going to get messy quickly. If the programmer(s) realize halfway into making their program that requirement X must be fulfilled and that in order to fulfill requirement X, a ton of code has to be changed in order to accomodate that, it isn't very good! By planning ahead, I hope to avoid a lot of headaches that otherwise would have popped up.

Next, you wrote that I shouldn't be writing a game engine without having a game to go along with it first. Companies write game engines and then the game all the time. Once a game engine is written, writing the game itself becomes a lot easier. I'm using DirectX 9, I've seen how much code it takes to do seemingly simple things. Why would it be bad to make a function like say DrawRect() and call that with a single line rather than jump through two dozen lines of DirectX manually? Complicating things right now by writing such a function will actually simplify things later on.

I look forward to the follow-up post you mentioned, jwalsh [smile]. (I would also be interested to see what other people think of this coding philosophy.)
Quote:mapOfGameObjects[identifier].push_back(theNewGameObject)


Would "identifier" every be significantly dynamic? As in, you'd make up your mind to create a new kind of identifier, and put that into some data file that lists entities, and then the entity gets created and inserted into a new kind of identifier, without re-compiling?

If that's the idea, then how are you going to know what you want to do with these separate identifiers? I'd assume that your C++ engine wants identifiers of specific kinds, because it knows what to do with them -- you wouldn't typically have a need to add entities to identifiers of kinds different than the ones supported.

If that's the case, then you might as well have a listOfGameObjectsOfTypeA.push_back(theNewGameObject), and a listOfGameObjectsOfTypeB.push_back(theNewGameObject). Using the compiler/linker to sort out your different identifiers is significantly faster than using a std::map.


Regarding "code by necessity," that's another way of putting "YAGNI" -- You Ain't Gonna Need It. That's a tried-and-true principle.

However, what YAGNI wont't solve, is the problem when you're developing an SDK to potentially be used by other (unknown) programmers, for solving multiple, varying problems. If YAGNI was always used, nobody would have created the UNIX API, and we wouldn't have had Linux. Win32 wouldn't have been created, and we wouldn't have had Windows XP. Heck, OpenGL wouldn't have been created, nor DirectX -- they all are chock full of functions that some designed thought a user might find useful at some point, but which nobody had use for right as the API/SDK/library was created.


So, perhaps a better question to ask is this: Is your end goal to release an SDK for others to develop 2D games with (and if so, what makes yours better than the others out there)? Or is your end goal to build an actual game (and if so, what's the actual story/characters/gameplay)?
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement