Let's talk architecture for a minute...

Started by
12 comments, last by lazE 17 years, 11 months ago
When you guys are designing a new game from scratch, how do you go about architecting the thing? Just to make some clarifications: I'm not really interested in answers like "well, I have my graphics manager, my input manager, my sound manager and my FooBar manager as Singletons...." I'm talking more about game object hierarchy/workflow design (and not how they interface with the hardware). So let's just say you have your favourite game loop setup:

while(!done) {
    if(it's time to update) {
        updateState();
    }
    render(); // or renderInterpolate(percentWithinState) or whatever..
}
So it's easy to visualize how stuff is setup, more or less. You have some collection of game objects, and those get displayed by render(). updateState would do all kinds of neat stuff (collision detection, reading input, updating player characters, doing the AI dance and updating NPC's, carrying forwards any animation that's under way, and so on). That's all fine and dandy, but what I'm trying to wrap my head around is a practical (read: performant and scalable) way to handle all the 'triggering' that happens in the game. Screen shifts, and all that stuff. For instance, in your kung fu fighting game, you won't just be having two characters fight. Once one character dies, a big congratulatory animation will be displayed, and then you get to ...choose your next oponent or something. Or perhaps your RPG character walks through a door and enters the next room. Next room has to load, and your character's position has to reset. Or maybe your RPG guy hits one of those random fights. All these things trigger big changes (in-game context-switches, if you will). Are there some really good design patterns meant for dealing with this stuff? What I've done in the past (and I really haven't written any very complex games) was to have a 'driver' class for each scene type. When the game starts up, I would load the 'Menu' driver, which in turn would load the background, some foreground movement, and the text menu. It would also have its own 'read input' function to handle keyboard bindings. Then, once you select a menu option, it would unload the current driver class and load the appropriate driver class for the next game state (say 'single player game', with some number of opponents or whatever). Although this was pretty nice, and prevented me from having to do that really stupid thing I see in a lot of code where there's a separate game loop hardcoded for each scene type, there are some problems with this approach. For one, it doesn't really scale, but that's easily fixed by making a lot of its functionality more data-driven. The other problem is that it was stateless. There was no concept of nesting (which would come in handy in an RPG where you get thrown into random fight scenes, and then end up back on your merry way). Like, say you are on the world map, from where you enter a dungeon, in which you enter a fight. It's not guaranteed that you can trace your way back once those sub-events finish, without some hackery. Anyway, I've been rambling, so now it's your turn to ramble. What are your favourite design patterns/approaches for this general problem, and what have you learned when writing games that are more complex than Tetris, which consists of a title screen and the game itself?
Advertisement
you know what? i don't have a clue to the answer to your problem. but! i'm gonna rate you up anyway because this is an excellent question and one i would like to get answers to myself.

cheers! (++OP)

Beginner in Game Development?  Read here. And read here.

 

Hi!

I am in a hurry at the moment but I really like your question since it bothered me hell of a long time as well. But here is something that might fit in:
http://www.gamasutra.com/features/20050414/rouwe_01.shtml

This is a really nice approach to the overall layout of a gameengine.

CU
Incommunicado
Quote:Original post by Alpha_ProgDes
you know what? i don't have a clue to the answer to your problem. but! i'm gonna rate you up anyway because this is an excellent question and one i would like to get answers to myself.

cheers! (++OP)

I'll be very interested in the answers to this too.
My opinion is a recombination and regurgitation of the opinions of those around me. I bring nothing new to the table, and as such, can be safely ignored.[ Useful things - Firefox | GLee | Boost | DevIL ]
Its a very good question and there are no perfect ways of doing.

In the RPG I am writing I plan to do it via something similar to your Driver class. I think driver is misleading so I use the term "Scene". In simple design terms (I am still planning this out by the way) each type of mode in a game is a inherited from the scene base class. Now there is a scene manager class with which you register a scene with. The scene manager class handles the management of these scene objects.

I have scene classes which handle loading rooms, battle scenes, cut scenes and even the pause menu is its seperate scene.

The scene manager class allows you to execute a scene and will automatically hand control back to the scene which executed it. The problem with my approach, which is similar to your problem, is the storing of state throughout different scenes. To handle this I have made the storing of any information not linked specifically to a single scene completly independent of the scene structure. Singletons once again prove there use in this problem, I have a singleton object which is the golbal registar of any application states. It contains methods like GetXXX(). The values are stored in a collection of associative arrays.

This does mean that when a Scene executes another scene it has to reload all the global data it is using, by querying the state singleton.

So in summary:
1) Scenes are a collection of distinct types of parts of the game (battles, rooms, pause menu)
2)A scene manager class allows the scene to be executed and a linked list format allows for the scenes to be linked together (ie a battle can start in a room and you can pause the battle and when you unpause and finish the battle you will be in the room)
3)A state singleton is used to store all global information
4)After a scene loads another scene it has to reload any global information it uses

Now I know this isnt the best way, so Im interested about how up people approach it.
Quote:Original post by Replicon
When you guys are designing a new game from scratch, how do you go about architecting the thing?

Just to make some clarifications:

I'm not really interested in answers like "well, I have my graphics manager, my input manager, my sound manager and my FooBar manager as Singletons...." I'm talking more about game object hierarchy/workflow design (and not how they interface with the hardware).

So let's just say you have your favourite game loop setup:

while(!done) {    if(it's time to update) {        updateState();    }    render(); // or renderInterpolate(percentWithinState) or whatever..}


So it's easy to visualize how stuff is setup, more or less. You have some collection of game objects, and those get displayed by render(). updateState would do all kinds of neat stuff (collision detection, reading input, updating player characters, doing the AI dance and updating NPC's, carrying forwards any animation that's under way, and so on).

That's all fine and dandy, but what I'm trying to wrap my head around is a practical (read: performant and scalable) way to handle all the 'triggering' that happens in the game. Screen shifts, and all that stuff. For instance, in your kung fu fighting game, you won't just be having two characters fight. Once one character dies, a big congratulatory animation will be displayed, and then you get to ...choose your next oponent or something. Or perhaps your RPG character walks through a door and enters the next room. Next room has to load, and your character's position has to reset. Or maybe your RPG guy hits one of those random fights.

All these things trigger big changes (in-game context-switches, if you will). Are there some really good design patterns meant for dealing with this stuff? What I've done in the past (and I really haven't written any very complex games) was to have a 'driver' class for each scene type. When the game starts up, I would load the 'Menu' driver, which in turn would load the background, some foreground movement, and the text menu. It would also have its own 'read input' function to handle keyboard bindings.

Then, once you select a menu option, it would unload the current driver class and load the appropriate driver class for the next game state (say 'single player game', with some number of opponents or whatever).


I noticed an article on game states (http://tonyandpaige.com/tutorials/game1.html) in another thread about game engine design (http://www.gamedev.net/community/forums/topic.asp?topic_id=388490). The game states described in the article sound related to your 'driver'.
I've implemented these game states (a little different from the ones in the article, though) so that I can push onto/pop off a stack in the engine kernel whenever the state changes.

Quote:
Although this was pretty nice, and prevented me from having to do that really stupid thing I see in a lot of code where there's a separate game loop hardcoded for each scene type, there are some problems with this approach.


Well, even with using game states as in the article above, you actually are kind of hardcoding a game loop for each state... Though I don't think it's as big a problem because code gets re-used alot more, and alot of the redundant code gets factored out.

Quote:
For one, it doesn't really scale, but that's easily fixed by making a lot of its functionality more data-driven. The other problem is that it was stateless. There was no concept of nesting (which would come in handy in an RPG where you get thrown into random fight scenes, and then end up back on your merry way).

Like, say you are on the world map, from where you enter a dungeon, in which you enter a fight. It's not guaranteed that you can trace your way back once those sub-events finish, without some hackery.


I suppose a stack of game states would allow this. Without hacks even!

Quote:
Anyway, I've been rambling, so now it's your turn to ramble. What are your favourite design patterns/approaches for this general problem, and what have you learned when writing games that are more complex than Tetris, which consists of a title screen and the game itself?


I haven't written any games more complex than Tetris yet, (I actually never seem to complete any of the bloody projects I start), but I think I'm well on my way to writing a complete game engine with a nice, consistent interface and a good set of features. Anyways, have a look at the game states and see if they help.
How strange, I have just recently finished a group project that employed both Game states and Gamesutra's MVC. Although a little difficult to get off the ground with the large number of classes that you have to employ for either method, once it gets going, the whole project is very managable as it is nicely modular as it allows one group member to work on a section/state/entity behaviour without affecting another member allowing tasks to be performed in parallel once the central engines and managers are built.

One of the problems with the MVC is that it can get too abstract and to get to the information you need from one class you have to go to the other side of the design to reach it although this is more of a design issue.

Steven Yau
[Blog] [Portfolio]

Quote:Original post by Zidane
Its a very good question and there are no perfect ways of doing.

In the RPG I am writing I plan to do it via something similar to your Driver class. I think driver is misleading so I use the term "Scene". In simple design terms (I am still planning this out by the way) each type of mode in a game is a inherited from the scene base class. Now there is a scene manager class with which you register a scene with. The scene manager class handles the management of these scene objects.

I have scene classes which handle loading rooms, battle scenes, cut scenes and even the pause menu is its seperate scene.


Scene is pretty much the same as what I called a game state here. However I didn't feel the need to add a scene manager and just added the functionality in the engine kernel class. It saves having yet another class (and a singleton at that!), and it made sense.

Quote:
The scene manager class allows you to execute a scene and will automatically hand control back to the scene which executed it. The problem with my approach, which is similar to your problem, is the storing of state throughout different scenes. To handle this I have made the storing of any information not linked specifically to a single scene completly independent of the scene structure. Singletons once again prove there use in this problem, I have a singleton object which is the golbal registar of any application states. It contains methods like GetXXX(). The values are stored in a collection of associative arrays.


I'm sorry, but this sounds dreadfully complex, and quite ugly. What states exactly are you storing? Which ones need to be restored when you change the scene?

Quote:
This does mean that when a Scene executes another scene it has to reload all the global data it is using, by querying the state singleton.

So in summary:
1) Scenes are a collection of distinct types of parts of the game (battles, rooms, pause menu)
2)A scene manager class allows the scene to be executed and a linked list format allows for the scenes to be linked together (ie a battle can start in a room and you can pause the battle and when you unpause and finish the battle you will be in the room)
3)A state singleton is used to store all global information
4)After a scene loads another scene it has to reload any global information it uses

Now I know this isnt the best way, so Im interested about how up people approach it.


I didn't understand how the scenes were linked with a linked list. Perhaps you could explain a bit more? Isn't a stack, where you can push/pop scenes, a more simple and intuitive approach?

Why don't you make the scene clean up after itself when it unloads? Wouldn't that save using a singleton to get all the states and whatnot? This might just be moving the code to another place though, but I think it sounds much cleaner.
IMHO the top level of your game will probably be best based on some kind of finite state machine to control what bits are currently 'active' (eg. are we in a menu state, or a loading state, or a single player game state). Anything more specific than that you'll probably have to start thinking about what your specific game needs.

If you've got an interface heavy game (like an RPG, with maps, inventory screens, quest pages, etc. etc.) then you would probably be well suited to having some kind of MVC approach (either parallel or within a particular state). Your model becomes the actual world data, the view is whatever is currently rendering and the controller would probably be your current state. Depending on the complexity it might be benifitial to have nested state machines.

I wouldn't try to overthink this though - although your general game structure may contain lots of elements of these kind of patterns it doesn't have to be overly explicit or formal. Just keep an eye on your dependancies and make sure that you're not doing the OOP equivilent of a goto and you can usually 'grow' a good solid design from your initial test code. Refactor constantly and you'll end up with a better design than you could of thought up of in the first place. [grin]
One way of dealign with this (and is can easily be visualised in the RPG fight system you described) is to have a simple state stack based structure.

Every state in your game (frontend, main game, pause menu, loading etc.) is a discrete state, which can be pushed and popped onto the game state stack at will. So for example, the game starts, you push the front end state, which pushes the main menu state. You choose options, the options menu is pushed, you chose to leave the options, the state is popped, passing the control back to the main menu. Start the game, the whole stack is flushed, and the game state is pushed etc.

With this system you can keep it as simple or as complicated as you wish. For example, when a state is pushed, you can specify if it will update or draw when it is not the top state/in focus. So if you push the game state, and say "Only update when in focus, but draw it all the time", you can push the pause menu, and have a transparent background, showing the game (which is still being drawn, but not updated).

You can take it a step further, and have a popped state stack, which updates states that have recently been popped. That way you can have transition effects between states depending on the state.

The game state manager is the key in this system, which races through the stack every frame, updating/drawing the entry depending on the state. Again, adding some extra functionality allows you to do a wide range of things.

In this system there is no passing of data between the states, as each one acts independantly of every other, the only control being the flags passed when pushed, and how the state manager chooses to deal with thses.

Hope thats useful to you
Spree

This topic is closed to new replies.

Advertisement