Could people show me their game class layouts?

Started by
22 comments, last by johnnyBravo 18 years, 5 months ago
Hi, I'm trying to decide on how to layout my game classes for the 100th time. And I was wondering if people could post their header files or give a brief description on how the classes are layed out. I want to see what other people are doing, because I've got a few ideas, but they seem not to work very well as my games get larger and more complex. I've been recently looking at Directed Acyclic Graph classes (DAG) which seems like a good idea, which basically is a layout where there are no loops in the class connections. eg it can't have connections like: class A depends on class B class B depends on class C class C depends on class A My problem with this is how to represent it at a code level. Should I have all the classes global? or in each class actually put pointers to the other classes where the connections exist (which doesn't seem very flexible if i am to want to remove or make new connections to existing classes). Thanks.
Advertisement
The thing is, "depends" isn't very descriptive.

Some places you might need B to inherit from A, other places you'll need C to have instances of B and/or A.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
You may create a pure virtual class which has one function such as ProcessMessage (Message) and all other classes are derived from it. When one object wants to connect to the other objects, it calls their ProcessMessage () functions with the appropriate message along.

It seems to be more object-oriented I think, while objects tell each other what to do or ask them for infos. But I use it sparingly as it is more complex than the original method.

It may help solving your problem though, give it a try.
Hth
V@T
--> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--
I use DAG's for mine. It's fast and easy.

Basically all my game objects inherit from a single base abstract class: GameObject.

It has a Notify method that takes a GameEvent object. Each GameEvent has a Type (BROADCAST, COM, MOVE, CUSTOM, etc) Using the event object, each GameObject checks to see if it has any EventResponse's registered for that type of event. If so, it returns them and they get put in a list. Then Notify gets called on each child, appending their EventResponse's to the list.

After all this, the EventResponse's are sorted by their priority field and then sent off to the scripting engine to be executed.
Crazy ideas - never thought about it.

Mine is more simple, because I have only made simple games.

I'll have a class similar to gameObject for example.


Inside it will have 3 functions

input();
think();
draw();


input will call think
think will call draw
draw will call input
AfroFire | Brin"The only thing that interferes with my learning is my education."-Albert Einstein

  • Everything is separated into local, global and avatar categories.

  • Local objects and avatars are stored and manipulated on the client, and do not exist on the server. Global objects exist only on the server, but are available as read-only proxies to the clients. Local controllers can be used to send orders to global objects from a client.

  • There is no such thing as an "update step" to most of the system. Also, except for avatars, no part of the system is aware of "frames" (since only avatars may be rendered).

  • The biggest unit of organization is the World. Each world has an unique global space-time. Space (physics, collisions) is managed by a physics module while time is managed by a scheduling module. Each world also has a local rendering space in which the avatars for that world are rendered on the client.

  • Everything is expressed in terms of initial state, start time and evolution. Current information is never used, which makes server/client communications much easier. Server-to-client latency is solved without backtracking simply by changing the above data.

  • Client-to-server latency is solved by having the client issue commands into the future, delaying commands that were meant to happen before they were received (and allowing batches of commands, so such batches are always executed in the same order), and also giving the server enough liberty to actually backtrack to a previous state to see what the result of a command would be, and accept it if it does not interfere with other commands.

  • Scheduling means providing a function that will be called after a certain time has elapsed. Scheduling can be global (and occurs exclusively through local controllers) or local (at which point it can only affect local objects or avatars). Nanosecond-level precision is ensured as far as global and local objects are concerned. Avatars only have a 60Hz guaranteed precision, but the precision error that occurs below that treshold will usually be unnoticed.

  • Each object has access to the world it appears in (and also to all modules owned by this world, such as collision detection, rendering, client-side resources or scheduling). Scheduling is performed in an idiomatic way. Aside from this, there should never be such things as singletons. Each object can only manipulate objects which it created, which were given to it in any way.

  • Where are objects stored? Usually on the heap, with an appropriate allocator. There are no "list of all objects" managers, although modules may keep internal lists (such as an event queue, a tree of avatars in a scene graph or a synchronization module). Most objects are not owner or pointed to by anyone, except maybe a garbage collection system and one or more scheduled operations that will be applied to them.
Quote:Original post by Endar
The thing is, "depends" isn't very descriptive.

Some places you might need B to inherit from A, other places you'll need C to have instances of B and/or A.


Yes I am beginning to see that.

I've been trying to decide on whether the rendering of each object, the sky, particles, and the menu should all reside in the render class, where the render class can see all the entities that it should render,

or should each entity have a pointer an adjacent Drawble class that is stored in some arrays sitting inside the render class which tell the render class the position to draw, use what textures etc.

Or should I have seperate classes each to render all the objects, the sky, all the particles?

Quote:Original post by Skeleton_V@T
You may create a pure virtual class which has one function such as ProcessMessage (Message) and all other classes are derived from it. When one object wants to connect to the other objects, it calls their ProcessMessage () functions with the appropriate message along.

It seems to be more object-oriented I think, while objects tell each other what to do or ask them for infos. But I use it sparingly as it is more complex than the original method.

I don't know if I want to go into using messages right now, although they look quite good if used properly, but I'm sure theres going to be some unforeseen design problems that I haven't thought about.
Also theres the problem with too tightly coupling the classes where I am unable to modify something without causing problems elsewhere.

Quote:Original post by AfroFire
Crazy ideas - never thought about it.

Mine is more simple, because I have only made simple games.

I'll have a class similar to gameObject for example.


Inside it will have 3 functions

input();
think();
draw();


input will call think
think will call draw
draw will call input

Hmm seems kinda funny ;)

Like some kind of function loop?

Quote:Original post by ToohrVyk--

I'll remember that the next time I create a mmorpg :), i think some of this is way above my head. The hard part for me is trying to make every come to together seemlessly.

Thanks guys, all this game class design is pretty complicated..
Some form of message queue will solve a ton of interdependency issues.
Quote:Original post by LordShade
Some form of message queue will solve a ton of interdependency issues.


True, but there is a fair amount of coupling assumed in using messages in that form.

My class layout is as follows, and it does use messages for input.

There is a system class which knows about all of the subsystems such as: InputManager, RenderManager, PhysicsManager, GuiManager, GameManager, ResourceManager, SoundManager, ScriptManager, etc.

Most of these managers maintain lists of objects which inherit specific interfaces. InputManager registers InputListeners. RenderManager registers Renderables, PhysicsManager registers WorldEntities, GuiManager registers Screens, and so on.

InputManager queries DirectInput each frame and dispatches input to the InputListeners. GameManager and GuiManager inherit InputListener. They receive input every frame. They process the input and perform actions based upon the InputMessage received.

Screens and GameEntities inherit Renderable. RenderManager renders them each frame.

GameEntities also inherit WorldEntity so they are acted upon by the PhysicsManager each frame, but before they are rendered.

System is responsible for creating each of these managers and passing to them the specific data that they need to initialize. It then enters the main game loop which does the usual:

Input - Dispatch all input
Process - Update states and physics
Render - Render the frame

Most of the Managers need to know about specific Managers such as the ResourceManager so each of them will have a pointer to the instance of ResourceManager which should be creating their resources. No singletons here, instead, that pointer is added to the SubSystem interface as is a pointer to any other manager that will be needed my most SubSystems.

That's my layout in a nutshell. I have not completed a full game yet, so take this all with a grain of salt.
It doesn't have any member method / properties descriptions, but here's my overall design:

http://www.mike-n.com/stuff/go.png

Where classes above the line are 'system' classes, below that are actual game object types

The basic underlying idea is that an Object can receive actions; only Actors can perform actions.

This topic is closed to new replies.

Advertisement