Skip to main content
GameDev.net gamedev.net
🔒 Locked

OOP game data structures

Started by squidlarkin Mar 17, 2009 at 7:58 PM 7 replies 2k views
Original Post
squidlarkin
squidlarkin
I've been working on a sort of 3D top-down shooter using Python and Ogre, but I still haven't completely wrapped my head around OOP. Things were going fine as long as I defined each instance of a game object individually, but now that I want to spawn objects dynamically I'm running into problems. Right now I've got all my physics calculations in a separate module which maintains a master list of all the objects in the game, but it doesn't seem to make sense to store references to the objects' SceneNodes in the physics code, so how can I step through the list to draw the objects?
Captain P
Captain P
Not every object that must be drawn needs collision checks, and not every object that needs collision checks needs to be drawn. I'd probably go for a composition approach: game objects contain either a SceneNode (for rendering), or a PhysicsObject (or whatever you use for your physics), or both. The rendering code only needs to know about the SceneNodes, the physics code only needs to deal with the PhysicsObjects. And the game just updates all game objects.

Perhaps this gives you some inspiration? :)
WhatsUnderThere
WhatsUnderThere
Correct me if Im wrong, but doesnt Ogre take care of drawing the list of objects with root.renderOneFrame()? If youre iterating through a list of objects on your own and drawing them, it's probably not unnecessary.
squidlarkin
squidlarkin
Yes, but I still need to worry about updating their locations and anything else about their appearance that changes based on game logic. Also there's the task of creating the meshes and sceneNodes as objects are spawned. The best solution I can come up with is to have the physics module maintain its list of physics objects while elsewhere there's a separate list of renderable objects, but that opens up the potential for nasty situations where the lists get desynced.
squidlarkin
squidlarkin
Specifically, situations like this one: my physics code tests to see if a bullet has hit a wall, and if it has, the bullet object gets deleted. But since the physics code doesn't know about the list of SceneNodes, it has no way of telling the rest of the program that it's time to delete that object.

I suspect the solution has something to do with having the objects' constructors and destructors take care of adding and removing the objects to the lists automatically, but I'm still running into snags there. Even if we forget about the graphics for now... say I want the PhysOb constructor to call world.registerObject(self). Since my physics module only has the class definitions, it has no way of knowing the name of the actual instance of the World class. What am I missing here?
AbandonedAccount
AbandonedAccount
If I understand you correctly, you can use a variety of methods to handle keeping your data in sync. Your physics code that deletes objects can use a callback to report which object was deleted, or you could just return information from the physics code that is then acted upon by the main code. You can also just use the same list of objects for both, and enhance the object to contain all required information for both rendering and physics.

For getting the instance of World, if there is only ever one World at a time you'd use a singleton and just Get() it.
Captain P
Captain P
Quote:
Original post by squidlarkin
Specifically, situations like this one: my physics code tests to see if a bullet has hit a wall, and if it has, the bullet object gets deleted. But since the physics code doesn't know about the list of SceneNodes, it has no way of telling the rest of the program that it's time to delete that object.

The physics code just informs the bullet that it's colliding. The bullet, or perhaps the code that manages the bullet, takes care of removing the bullet. Since the bullet is composed of a physics and a rendering (scenenode) object, it knows how to remove them.

Quote:
I suspect the solution has something to do with having the objects' constructors and destructors take care of adding and removing the objects to the lists automatically, but I'm still running into snags there.

Whether you do it at construction/destruction time or not, doesn't exactly determine how to do it. But yes, using the constructor/destructor (don't forget the copy constructor and assignment operator!) will likely make things easier to automate.

Quote:
Even if we forget about the graphics for now... say I want the PhysOb constructor to call world.registerObject(self). Since my physics module only has the class definitions, it has no way of knowing the name of the actual instance of the World class. What am I missing here?

What exactly is this World class responsible for? Why does PhysOb, or the physics module, need to know about the world (I can imagine it needs to know about the physical aspects of the world, but the world itself?)? Either way, if it needs to know about something, can't you just tell it about it (by sending it a reference to that world instance)?


Quote:
Original post by richardurich
For getting the instance of World, if there is only ever one World at a time you'd use a singleton and just Get() it.

No need for that. If you insist on such kind of dependencies, a globally accessible instance will be sufficient. However, that makes your physics system depending on that singleton or global instance. Not very flexible. If the physics system needs to know about something, just pass the information along.
Zahlman
Zahlman
Ok, ok.

You don't have a list of SceneNodes or of PhysicsObjects. You just have a list of game objects. Possibly several, depending on your organizational requirements (i.e., what can collide with which, and so on). A GameObject contains an Appearance (if it is visible), a PhysicsObject (if it is substantial), and a dead flag.

You iterate over GameObjects, calling update() on each. update() does nothing if the GameObject in question has no PhysicsObject. If it has one, it asks the PhysicsObject to do its thing. The PhysicsObject updates its internal state, and returns a boolean value to indicate if the object died. The GameObject updates the dead flag.

You filter the list(s) of GameObjects, removing everything that's dead.

You iterate over GameObjects, calling render() on each. render() does nothing if the GameObject in question has no Appearance. Otherwise, it asks the Appearance to do its thing (typically, fit itself into a graph of SceneNodes or a render queue or something somehow. Maybe Appearance == SceneNode is good enough for your purposes; maybe it makes sense to add room for some kind of translation work in there). Then you render the scene.
squidlarkin
squidlarkin
Aha! Solved it by having the physics module create the world instance itself, then creating a reference to it in the game sourcefile. Which seems somehow sloppy to me, but it works, so I'm happy.

Zahlman: The way I've got it set up is to have the World object take care of the updating for all the objects in a big nested loop, which seems to me to have some advantages; when two objects interact, I can change both their states at once, and also I only have to test each pair of objects once instead of twice. Is there a real downside to this approach, other than it perhaps not fitting the OO paradigm as well?

[Edited by - squidlarkin on March 24, 2009 8:12:47 PM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.