Sign in to follow this  

OO Engine Design Issues

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

So I've got Game Objects which are either render-able or affect the game play in some way (part of the Scene Graph). And I also have certain services, such as a Texture Manager, Model Manager, which handle the loading and such of different resources. Game Objects need to know about certain Services (or managers) but not all of them all the time. There is a main "Engine" class which is the container for everything. I've looked into using the Factory pattern for creating GameObjects, but there is still the problem of, how does code that doesn't care about service X, pass service X to a GameObject which does need it. I was passing a pointer to the Engine object to each object, then they could use that to get the different service's they needed. But that necessitates a class knowing about it's container which is dirty. So there is that problem, objects shouldn't know about their container, but then how do they know about other objects inside the container which they need. Also, these Managers, I don't want them to be singletons, I mean they are pretty much just library functions, but still state full. Like the Texture manager actually holds the memory the textures are allocated into, and store lists of who is using them, so manages freeing them when they are unused and such. At the moment they are not singletons, they are just regular classes which could be instantiated twice, just never would be. So how do you guys handle things like this?

Share this post


Link to post
Share on other sites
You should extend your definition of "cares about X" to also include cases of "creating objects that care about X". That is, your Foo-factory does not merely create Foo objects, because Foo objects can't exist in a vacuum. Instead, your Foo-factory creates Foo objects that live in a specific Bar—you then decide whether a given Foo-factory should always create its Foo objects in a given Bar (provided when it's created), or if the user should provide the Foo-factory with an individual Bar for every Foo upon creation of that Foo.

Share this post


Link to post
Share on other sites
Quote:

So how do you guys handle things like this?


By not breaking rule #1.

Game objects are independent of their presentation.

You then end up with a few factories. Ones that create resources (presentation only) and one that is application specific (which can know about the game and the presentation since it's at the application level) that creates a presentation given a game object and a context.

Share this post


Link to post
Share on other sites
I'm reading that article and will probably come back w\ some more questions, but here is how I have things set up.

My Game objects are fairly agnostic of both what their presentation data is and how it is being presented.

All presentation data is requested by a Game Object from a Resource Manager (such as a texture or model manager). If the resource has not been loaded before, then it is loaded and registered with the manager and given a resource ID. That resource ID is returned to the Game Object. If it had already been loaded then it is found and it's ID is simply returned.

Then, the Game Object registers it's self with the Scene Manager (Scene Graph wrapper) where a Scene Graph Node is created for that specific object. Then when ever the renderer hits that Scene Graph node it finds the resource ID (which was given to the node by the Game Object) and renders the data specified by the ID stored in the specific resource manager.

This way the Game Object takes care of the logic ( Control ), the Scene Graph + Renderer take care of the presentation ( View ), and the Resource Mangers take care of the data ( Model... ish. )

This seems like a reasonable way of handling things to me, what do you guys think?

Share this post


Link to post
Share on other sites
Quote:

This seems like a reasonable way of handling things to me, what do you guys think?


Exactly what I thought before.

BAD

Model <====> View



GOOD

Model <====> Controller <====> View


Game objects do not care about presentation. They do not care about scene graphs or textures or models. A dedicated server uses game objects but has no presentation. An AI uses game objects but has no presentation. A pathfinding thread uses game objects but has no presentation...

Your Scene Graph doesn't care what game it's being used in. It doesn't know or care about SpaceShip or NastyOrc.

Your Application knows about the game objects, and it knows which rendering api you're using. It acts as the intermediary to get the two parts that don't care about each other working in concert.

Share this post


Link to post
Share on other sites
That's interesting, Telastyn. Most MVC architectures that I've seen generally allow for communication between the view and model. Are you suggesting that a better design is to route all communication through a controller class? I sort of see where that might be useful, but it also seems needlessly complex. The view certainly needs to know about state changes in the model.

Edit-

A slightly more concrete question: we're talking about using a MVC arrangement for every object in the game world, so say we have a SceneNode (view), Entity (model), and EntityController (hurr). The EntityController might handle player input, network messages, AI logic, or nothing at all, depending on what type of entity we're talking about. Obviously the SceneNode renders itself and the Entity stores/manages state, but how would you synchronize them?

When the EntityController decides to do something new it has to inform the Entity, but it can't directly inform the SceneNode since it doesn't have the "authority" to change state on itself. Would you say it's better to then have the Entity pass its new state information back to the EntityController, which then passes it along to the SceneNode, or would it make more sense to have the Entity itself inform the SceneNode of its new state?

Share this post


Link to post
Share on other sites
Enh, sorry I just did it that way since the triangle ascii art never seems to work right...

And MVC is also perhaps not the best use of what I was trying to describe.

On one side you have your game. The game needs to exist and work without any presentation.

On the other side you have your UI/rendering. The UI/rendering needs to exist and work for any number of games.

So something needs to know about both of them. To me, that something is the Application. It takes the game code and the UI/rendering and makes them work together. Sometimes that's extending some code, sometimes that's setting up event handlers...

Regardless, that's how the 'knowledge' structure goes, in a tree.


A
B C


B and C need to be independent of each other, but also need to work together. Thus you need A to make them work together. B and C can then be used elsewhere without dependencies.

Quote:

When the EntityController decides to do something new it has to inform the Entity, but it can't directly inform the SceneNode since it doesn't have the "authority" to change state on itself. Would you say it's better to then have the Entity pass its new state information back to the EntityController, which then passes it along to the SceneNode, or would it make more sense to have the Entity itself inform the SceneNode of its new state?


Two options, depending on the scenario.

1. Simple event. The Application (which knows of both the Renderables and the Game Object) has an event handler which understands the state change and can update the Renderable. Message passing does the same sort of thing.

2. Concrete Implementation. Part of the Application is a sub-class of the Game Object (likely registered into a factory known by the Game Objects) that does the extra work (unbeknown to the Game code itself). Similarly, the Renderable could be subclassed to 'peek' in at the Game Object and update itself as necessary.


The key though is that the Application is the code that is not reusable. It exists specifically to make this Game work with this Rendering. As such, the design motivation is to make it as small and simple as possible. Ideally not much more than making some objects and tying some events to some handlers.

Share this post


Link to post
Share on other sites
Quote:
Original post by Jools
That's interesting, Telastyn. Most MVC architectures that I've seen generally allow for communication between the view and model.


If you divide your app into model, view, and controller classes, but allow each of the 3 categories to communicate with the other 2, then how is that conceptually different from just having a single category? What benefit has it brought you, except perhaps a small degree of mental clarification?

Surely the only way to make maximal use of such a division, is to allow the controller to enforce the separation, so that the view doesn't break when the model changes, and vice versa.

Share this post


Link to post
Share on other sites
Quote:
Original post by Jools
When the EntityController decides to do something new it has to inform the Entity, but it can't directly inform the SceneNode since it doesn't have the "authority" to change state on itself. Would you say it's better to then have the Entity pass its new state information back to the EntityController, which then passes it along to the SceneNode, or would it make more sense to have the Entity itself inform the SceneNode of its new state?


It would make more sense to me to let the Entity inform their own EntityView(SceneNode), because the EntityController does only handle the interaction with the Entity the Entity will handle the logic of the overal object. If you want something different rendered you will send a message from the Entity to the EntityView. The EntityView will only care about rendering.

Like in the article if you want to have for example a particle effect rendered for an Entity you will fill in a structure and send that structure via a one way messagehandler to the EntityView which will process the message to render the particle effect.

If you want to process a function like fire() then the controller will let the entity now the player wants to fire and so the Entity will decrease the ammo or something like that and sends a message to the EntityView to process a particle effect. The EntityView will then render the particle based on the message it recieved from the Entity.

Personnaly i love this system it works very nice to seperate specific logic/rendering

Edit:
Also please note the Entity isnt the 2d/3d-Model its just a GameObject. The View will handle the 2d/3d-Model based on the Entity instructions

[Edited by - rvdwerf on November 22, 2007 7:38:24 AM]

Share this post


Link to post
Share on other sites
Man this is a great thread, and that article is awesome too.

I'm gonna re-read all of this stuff a few times and analyze how to redesign my architecture, then maybe I'll post back on here to see what you guys think.

Thanks again so much for the clarification guys!

Share this post


Link to post
Share on other sites
An interesting question to put here...

@Telastyn,

You said:

"BAD

Object <===> Presentation"

What about?

Object ===> Presentation

Now, this assumes that Presentation is only modified by Object, and not the other way around, but is that bad?

In fact, should a game object be worrying about messages from its presentation? If it is a true "presentation," why would it even communicate with it?

In the current system I program with, the Top->Down style is the only way things work, except for messages. All game objects tell their presentations what to do, and the presentations are in turn rendered, played, calculated, etc...

However, there are some systems that need to provide information to the game objects, and that info is put into a message class, and then sent to a high-level game message machine. That machine decides where to send the message based on a given database, which the game objects can register in to receive certain messages. This allows for the scripting language I use to control the program more.

My primary question in this is: What is the advantage to having a 2 way street of communication, when really, the street is 1 way? By separating the main input and output streams, you may create a bit of overhead, but isn't it much more appropriate to the situation?

Share this post


Link to post
Share on other sites
The main concern comes to this:

If you can't run your game without a presentation, something is wrong.
If you can't use your presentation framework without this specific game, something is wrong.

Personally, I find game objects need presentation info/events/messages. Why? Because (imo) user input is presentation dependent, mostly due to mouse clicks requiring context to determine the trigger, but also because keybindings and localization concerns best fit into that area of the code.

Share this post


Link to post
Share on other sites
Quote:
Original post by Telastyn
Personally, I find game objects need presentation info/events/messages. Why? Because (imo) user input is presentation dependent, mostly due to mouse clicks requiring context to determine the trigger, but also because keybindings and localization concerns best fit into that area of the code.


I find personnaly that the user input isn't presentation depended. because with input you need to change the state of a gameobject(s) and in no way the presentation(s). The presentation(s) doesn't even know about the current GameStates only thing it can do is render based on the instructions of the GameObject(s)

Share this post


Link to post
Share on other sites
Quote:
Original post by rvdwerf
Quote:
Original post by Telastyn
Personally, I find game objects need presentation info/events/messages. Why? Because (imo) user input is presentation dependent, mostly due to mouse clicks requiring context to determine the trigger, but also because keybindings and localization concerns best fit into that area of the code.


I find personnaly that the user input isn't presentation depended. because with input you need to change the state of a gameobject(s) and in no way the presentation(s). The presentation(s) doesn't even know about the current GameStates only thing it can do is render based on the instructions of the GameObject(s)


That assumes you use GameStates...

So, how do you handle the translation of mouse clicks in screen coords to GameObject events?

Share this post


Link to post
Share on other sites
Somethings got to decipher what's being clicked, right?

I don't know what rvd does, but as for me...

When a mouse click happens, the coordinates and button are transmitted in a message. The high level message center will hash the message and pass it off to the registered function. This function is specified by the scripter, or coder, but it would in turn tell the game object that it's been selected, clicked, etc...

Share this post


Link to post
Share on other sites
Quote:
Original post by Kylotan
Surely the only way to make maximal use of such a division, is to allow the controller to enforce the separation, so that the view doesn't break when the model changes, and vice versa.


The problem with this is that you create an unnecessarily large dependency between the model and the controller and the view and the controller. I wasn't suggesting unrestricted communication between all three components, but rather controlled communication that's only dependent on interfaces. In the case of a "mini" MVC setup for each entity, I would personally have the model produce some sort of state change (EntityMoved or whatever) event that's consumed by the appropriate presentation object. The presentation object would then call a getTransform method (or getPos or similar) on the model to update itself. You'd almost certainly need to do some more complicated state querying for animation purposes as well.

You end up coupling your presentation to your model somewhat, but I think that's a necessary evil in any situation where you're presenting something more complex than some static geometry. If you're dealing with animations and special effects you need some way to sync those up with the current state of the actual object. Even if you do this entirely by passing events and never have the presentation aware of its model you still end up with some implicit coupling since you're relying on events that are probably specific to your current game. In my opinion it's not a big deal to have bits of game-specific code in your presentation as long as they're well encapsulated and easy to pull out when/if you decide to reuse the code on another project. Attempting to make your presentation completely generic is, in my opinion anyway, a pretty big waste of time.

Share this post


Link to post
Share on other sites
Quote:
Original post by Jools
That's interesting, Telastyn. Most MVC architectures that I've seen generally allow for communication between the view and model. Are you suggesting that a better design is to route all communication through a controller class? I sort of see where that might be useful, but it also seems needlessly complex. The view certainly needs to know about state changes in the model.


Something like this is more like the "Model, View, Presenter" pattern. Its particularly nice if you want to unit test as much as possible of the display logic.

here is info on it

I'v built a sales system as part of a course in agile software development that used it heavily and it worked really well.

Share this post


Link to post
Share on other sites
Quote:
Original post by Telastyn
Quote:
Original post by rvdwerf
Quote:
Original post by Telastyn
Personally, I find game objects need presentation info/events/messages. Why? Because (imo) user input is presentation dependent, mostly due to mouse clicks requiring context to determine the trigger, but also because keybindings and localization concerns best fit into that area of the code.


I find personnaly that the user input isn't presentation depended. because with input you need to change the state of a gameobject(s) and in no way the presentation(s). The presentation(s) doesn't even know about the current GameStates only thing it can do is render based on the instructions of the GameObject(s)


That assumes you use GameStates...

So, how do you handle the translation of mouse clicks in screen coords to GameObject events?


If you mean for the GUI ;)
The GUI has also a GuiEntity and GuiController so the GuiEntity will poll the GuiController for mousclicks and will notify(if you specify the GuiEntity for it) the other Entities.

Share this post


Link to post
Share on other sites
HHhhmmmm.... this is all fairly close to what I have already in fact.



So here, lets say you have a class: Monster
which is a sub class of Game Object.

It is instantiated when some new "Game State" is instantiated which needs a monster. It is instantiated by that "Game State" (That is a very simplistic example, just go with it).

Monster tells the Resource manager it wants "monster.mdl" and "monster.png" for its geometry and texture.

They are loaded into memory and a "Resource Id" is returned.

Then our Monster class registers it's self with the Scene Manager, the Scene Manager created a Scene Graph node for our Monster object and registers it's self as a subscriber of events for our Monster Object (lets call him Gorge).

So our Game State interprets some input which turns out to mean that Gorge need to move some amount of distance. The Game state calls gorge.move( 2, 0, 0 ); to move him forward. The Monster class contains the controller code, the game logic, for how the monster actually moves. Gorge complies, and after updating his internal state sends a message about his new position to anyone listening.


The Scene Manager is listening and updates the Scene Graph if need be (it's a BSP tree, so it might have to move Gorge to a new Leaf).

Now our update is done, time to render. Our render is passed to the root of the scene graph, and traverses the Scene Graph using the visitor pattern.

When it encounters Gorge's Scene Graph node, the node has a reference to Gorge which it uses to grab the Resource Ids returned by the resource managers. Then, using those Ids, it gets the actual bits and bytes from the managers, and renders them. It also gets information such as rotation and position from the gorge object.

The nodes are general, such as;
class Model3DNode : public SceneGraphNode;

The renderer expects to be able to get a Model ResourceId from what ever game object the node has a reference to.

This is all implemented via interfaces and base classes.


Now I posted this because I KNOW it is flawed, and I WANT you guys to rip and tear! But before you do, I bet you are going to say that many of these things (such as position and rotation) should be in the Scene Graph node it's self. But it just seems to be that the Scene Graph and it's nodes should not care about what objects they are representing, and if they were to store this info, they would have to care. Some Objects need resource Ids for models, some for textures, some need rotation, some dont. You would need a Scene Graph Node sub class for every type of Game Object almost it would seem. Please correct me if I'm work (I probably am) but that doesn't seem like a great idea.

Share this post


Link to post
Share on other sites
Warning: Opinion follows.

Quote:
Original post by Wavesonics
HHhhmmmm.... this is all fairly close to what I have already in fact.


Yup, it seems so.

Quote:

So here, lets say you have a class: Monster
which is a sub class of Game Object.


Fair enough, though there's often little difference between monsters and players and npcs.

Quote:

Monster tells the Resource manager it wants "monster.mdl" and "monster.png" for its geometry and texture.


Why does a GameObject care what geometry and texture it has? Why does it care what its Presentation is at all? Since you're using events for other things, I suggest a "Hey, I'm a new Monster!" event [edit: actually within the Game State, so it'd be more like "I'm making a new Monster" event]. The Application can then tie that to an Application level factory that says "Oh Monster X gets such and such Model and Texture."

Quote:

Then our Monster class registers it's self with the Scene Manager, the Scene Manager created a Scene Graph node for our Monster object and registers it's self as a subscriber of events for our Monster Object (lets call him Gorge).


Again, Presentation cares about the GameObject and its events. The Application factory would do this as part of the "New Monster" event handler.

Quote:

So our Game State interprets some input which turns out to mean that Gorge need to move some amount of distance. The Game state calls gorge.move( 2, 0, 0 ); to move him forward. The Monster class contains the controller code, the game logic, for how the monster actually moves. Gorge complies, and after updating his internal state sends a message about his new position to anyone listening.


Good!

Quote:

The Scene Manager is listening and updates the Scene Graph if need be (it's a BSP tree, so it might have to move Gorge to a new Leaf).

Now our update is done, time to render. Our render is passed to the root of the scene graph, and traverses the Scene Graph using the visitor pattern.


Fair enough.

Quote:

When it encounters Gorge's Scene Graph node, the node has a reference to Gorge which it uses to grab the Resource Ids returned by the resource managers. Then, using those Ids, it gets the actual bits and bytes from the managers, and renders them. It also gets information such as rotation and position from the gorge object.


Why? If the Monster tosses events on movement and rotation, why does it need to double check every frame? Why does it need the reference to the Monster?

Quote:

The renderer expects to be able to get a Model ResourceId from what ever game object the node has a reference to.


Why isn't that ResourceID in the Node?

Quote:

Now I posted this because I KNOW it is flawed, and I WANT you guys to rip and tear! But before you do, I bet you are going to say that many of these things (such as position and rotation) should be in the Scene Graph node it's self. But it just seems to be that the Scene Graph and it's nodes should not care about what objects they are representing, and if they were to store this info, they would have to care.


Why? It's the position and rotation of the Node, which due to resolution/effects will often be different from the position and rotation of the GameObject. Sure, they're going to be synchronized, but you're probably going to need to store position info for your Nodes. What of UI objects that need a position, but don't represent a GameObject? What of Games that don't have their position directly in 3D space (ex. chess)?

It might be a little inefficient for Games that do have their playfields directly mapped to the screen, but the design is most flexible when the two parts handle their own position/rotation.

Quote:

Some Objects need resource Ids for models, some for textures, some need rotation, some dont. You would need a Scene Graph Node sub class for every type of Game Object almost it would seem. Please correct me if I'm work (I probably am) but that doesn't seem like a great idea.


There's a number of articles about Scene Graphs that could help. I've seen a few where "Rotation" is a node in the graph by itself, automatically turning any of its children. You then get some composition, eliminating the need for so much subclassing. Personally, I only see 3 major subclasses needed: Model, Image, and Text. If you don't want rotation, specify 0 rotation (or go with the default; 0 rotation).

Share this post


Link to post
Share on other sites
Quote:
Original post by Jools
The problem with this is that you create an unnecessarily large dependency between the model and the controller and the view and the controller.


I really don't see why that should be the case.

Quote:
The presentation object would then call a getTransform method (or getPos or similar) on the model to update itself. You'd almost certainly need to do some more complicated state querying for animation purposes as well.


I would much prefer to have the controller telling the presentation object where it's supposed to be. Generally I think presentation instructions should be pushed down by the game rather than pulled down by the renderer. Generally this is because it means there's less temptation to change the model to accommodate changes in the view.

Quote:
Even if you do this entirely by passing events and never have the presentation aware of its model you still end up with some implicit coupling since you're relying on events that are probably specific to your current game.


I just think that these things are trivial to do via the controller, and that the benefits are significant. Anything which helps you vary the model and the presentation independently is a good thing in my experience.

I appreciate that often, there seems little reason to have an extra middleman between the view and the model, but since you have one and use it for many other purposes anyway, I find it beneficial to extend that to be a layer of abstraction between the two.

Share this post


Link to post
Share on other sites
Quote:
Original post by Vincent de Perrot
Since everybody is talking about dependencies and code reusability, what part of the code would never change between two completely different games?


Let's see... in my current game (VS solution) I have a number of projects (not actual names):

ActiveStatusGroups
ThreadingUtils
BaseManager
BaseRendering
BaseSound
Interpreter
D3DRendering
FMODSound
GameClient
Game
Network
Logging
Timing
ValueSet (for in-game piles of stuff)
Input

Game and GameClient are the only projects with stuff specific to the game and no other project depends on them.

Quote:

Other question: how can entities interact with elements that are not game entities, such as a terrain, static geometry or whatever?


I've not worked really with games that have such needs, but my gut instinct is that they don't. You make a GameObject that represents the terrain or other geometry. This I'd imagine would often be in the form of whatever physics or collision detection code you're using.

Share this post


Link to post
Share on other sites

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