need help on game driver design

Member
Posts: 45
Joined: 2006.11
Post: #1
I'm working on a game engine for OpenGL and I'm having trouble with a particular issue with the highest level of the engine, which is the window/event manager. Here's a summary of what I have. I wanted to have a system like GLUT, where the game has callbacks for draw, idle, and input. I also wanted to have multiple independent parts of the game, such as the menu, the gameplay, a tutorial level, etc... so that each part can define its own callbacks, and I can switch between parts of the game easily. I also wanted to abstract the windowing/event system from the game part (or Scene) so that I can switch from, say glut, to SDL or even custom CG etc... I have a pretty good scheme for these needs, but one thing I'm having trouble with is getting the scene switching done correctly without hacky type methods. Here are some details:

The basic unit of the engine is the Scene or Module (someone suggested not calling it scene since it conflicts with things like scene graphs and such, so another name could be Module, but I think it is overly ambigious, so I just use Scene for now). The scene responds to events much like a typical GLUT application would. It has functions to draw, idle, keydown, keyup, etc... You create a number of custom scenes which inherit from the same virtual base class which sets up the interface for a scene. The scene is unaware of the event and windowing system it is being run on, but it has full control of OpenGL state and/or any other libraries not related to windowing and events (like FMOD for sound, etc..). It has functions for initializing the OpenGL state when the scene is initialized, and it is responsible for loading all its data and managing its own memory space. Since the Scene is pretty much aware of how and when to switch to another scene, the Scene is responsible for initializing the switch to another scene. The actual handling of the switch may occur in the GameController, described below.

At the top is a virtual base class called GameController, which defines the interface for the overall driver of the game. Now, subclasses of these include either GLUTController or SDLController or perhaps in the future my own custom controller using CG or something. A subclass of the controller or one of its subclasses like SDLController, contains a number of Scenes it is responsible for managing. This includes initializing the scenes, starting the correct scene, and managing the switch between scenes.

Now, here's the problem with scene switching:
The scenes themselves are aware of when they need to switch to another scene. For example, the gameplay scene will know that when the player dies or wins, we should switch to the winner/loser screen. This means that a scene must be aware of the other scenes in its parent GameController, and must have some interface into its parent GameController in order to initiate the switch, which also requires that each Scene know where to find its parent GameController. Either that, or each scene must know where to find the scenes it will be switching to, and the scene switching interface will be part of the scenes themselves. Both ways are somewhat shady in terms of data encapsulation. Is there an alternative? And finally, sometimes I don't want one scene to lose its data or position when I switch to another scene. For example, if the menu and the gameplay are scenes, and you bring up the menu during gameplay, I want to keep the player's place and all the data that was allocated while I'm running the menu, and then resume the gameplay scene when the menu is done, possibly with some changes. This suggests a kind of stack-based implementation for scene switching... but then again sometimes I just want to switch all the way into another scene and clear out the current scene...
Quote this message in a reply
Member
Posts: 156
Joined: 2002.10
Post: #2
Again this is possibly a bit hacky, but it is another possibility - have your base class store the current subclass (the current scene) as an instance variable. Also have storage (array, stack, ... depending on exactly what you want to do) for 'dormant' scenes - ones which you want to store the data from.

In your subclass, set an instance variable, say nextScene when you want to switch scenes - also set a boolean variable to say whether you want to dispose of the scene or store it. A function in the controlling class can read the nextScene variable - if there is a corresponding one in it's store of scenes, load that scene. If the boolean is set to true, then store the current scene and perform the switch. Otherwise, dispose of the current scene, and either switch to an existing one, or instantiate a new one entirely.

Effectively, you're running a finite state machine (finite automata), but storing the info from some of the states in case you need to return to them.

This would require a bit more overheads in the way of storage management / garbage collection in the controlling superclass, but I think it is possible to implement, and hopefully might be useful to you.

- Iain
Quote this message in a reply
Member
Posts: 104
Joined: 2002.04
Post: #3
The way that i do this is to have each "Scene" as you call it have a pointer to the main controller object. Put all of the switching logic into the controller so that it will be easy to rearrange or change the order of things (eg. maybe you used to go from game over to choose new game, but now you want to add a summary screen or optionally go to the high score entry screen on game over) That way you have only one place that you need to change the order, and not a spaghetti of interdependencies.

just my 0b00000010 cents
Quote this message in a reply
ylaporte
Unregistered
 
Post: #4
Here is how I am doing it right now:

I have some kind of controller class that holds a pointer to the current Scene (or module or whatever you call it), this pointer is of type of a base class from which all of my scenes inherit. The controller calls a processFrame() at every frame, the processFrame() method returns a pointer to the scene to be shown next (most of the time it just returns this or self) and the controller replaces the ponter to the current frame by the returned value. This design as the advantage that the controller doesn't have to be modified whenever I add a new scene type or if I change the transitions possible among these scenes. If I add a new scene, teh only classes that need to be modified are the ones for the Scenes from which you can get to the new scene. The code for the controler is also extremely simple.

Other notable points in the architecture I use is that all Scenes are singletons and teh base Scene class features load() and unload() methods in case I want to dealocate some of the memory used by very large scenes. I could probably implement a better scheme for memory preservation such as some deamon that dealocates (unload()) scenes that haven't been used for a long time or if more memory is needed.
Quote this message in a reply
Member
Posts: 45
Joined: 2006.11
Post: #5
Thanks guys.
ylaporte:
Yeah, that's pretty much how I have it set up. There is a pointer to the currently active scene in the controller class. The scenes need to be aware of what other scenes there are (simply because the scenes will know when to switch to another scene). The problem with having a pointer to the controller inside each Scene class is that I ONLY want the scenes to be able to tell the controller to switch scenes. The controller class also has public interfaces to initialize, start, etc... which the scenes should not have access to. In general, it's best not to have objects double back (an object which contains another object which has a pointer to the first object). So, to get around this, I could use two methods. First, I could use scene state. A scene can be set into a state such as running, paused, stopped, etc.. The controller can then check this state and switch accordingly. Second, I could use exceptions to send messages to the controller.

The second method, I think, is better than the first because switching to another state is more intuitively an "event" and almost always goes along with some associated information. For example, the gameplay sends a message to switch to the final-score scene with the information on who won the game, what all the scores were, etc..

Now, I still want to be able to switch scenes without unloading other scenes. I also want to be able to have two scenes which run simultaneously, and a scene which draws over the top of another scene (for example, a menu that pops up over the gameplay which still runs in the background while you're looking at the menu. For this purpose, I need a kind of string-stack. Each scene can send one of three switch messages, AND can set one of several states. Also each scene can be classified as either transparent (draws over the top of another scene) or solid (takes over the entire screen). The switch messages are: PushScene (pushes a scene onto the top of the stack), PopMe(pops this scene from the top of the stack), and PopMePushScene(pops this scene from the top of the stack, then pushes another scene onto the top of the stack). Each of those messages go along with some data that the new scene uses to figure out what to do once it starts up. The stack is also like a string-stack because you need to visit all the elements in the stack (usually the stack only has a maximum of like 4 scenes) to process the scenes which are still in the running state. In order to figure out what order scenes need to be drawn, you start from the top of the stack, check if it is transparent. If it is, go down the stack until you find a scene that is either solid paused. Then you draw that scene, followed by the next scene till you get to the top again.
Quote this message in a reply
ylaporte
Unregistered
 
Post: #6
Quote:Originally posted by JeroMiya
The problem with having a pointer to the controller inside each Scene class is that I ONLY want the scenes to be able to tell the controller to switch scenes. The controller class also has public interfaces to initialize, start, etc... which the scenes should not have access to. In general, it's best not to have objects double back (an object which contains another object which has a pointer to the first object).

That is why my scenes have no knowledge of the controller. The way they tell the controler to switch scene is by returning a pointer to the scene to be displayed on the next frame (note that this doesn't allow fade ins/outs, but there is most likely a workaround for that). When the controler call processFrame() teh method returns a pointer to a scene, itself if it should still be displayed on the next frame and a pointer to another scene if teh controller should switch to the next.

Using a state variable is not a bad idea... However, it implies that your controler "knows" the scenes or that the scenes have to register themselves using some method. Using good old events is a good solution I think, the controler registers itself as a listener of scene_switch events to each scene that becomes active. I would go against using exceptions to solve this problem since there are fewer drawbacks with other solutions.

Ah.. and maybe you shouldn't worry too much about your scenes being able to call public methods of your controler... After al, you are writing the scenes... Or having the controller inherit or implement some interface with only the method switching the scene and the scenes being capable to only access the controller through this interface should solve the problem.
Quote this message in a reply
Member
Posts: 201
Joined: 2002.06
Post: #7
I didn't read everybody else's answers, so I may just be summarizing something else. Either that or this may just be a very bad idea....

The way I would tackle this problem (if I had no outside advice) would be to let the controller, rather than the scenes themselves, decide when to switch scenes and which scene to switch to based on the conditions of the game.

Take your game-over screen example. The way you would do it with the scenes deciding themselves would be to have the scenes introspecting on the conditions of the game and then telling the controller which scene to switch to. This means that each scene must know about each other scene it may switch to. If you used your controller to do this, all it would take is the passing along of a condition of the game, such as a boolean variable called isDead or something, which the controller interprets and makes decisions on itself. The controller being aware of all the scenes is much preferred to each scene being aware of each other scene. This is much like an event loop now that I think about it.

Based on how I interpreted your description, a scene appears to fit into the MVC paradigm as both a model and a view, but not a controller. That also makes me instantly think to do this.
Quote this message in a reply
ylaporte
Unregistered
 
Post: #8
One of my goals when building this arcitecture was to minimise code changes when I add new parts to the game (Scenes). If I need to change the controler (I call it the dispatcher but who cares) everytime. That would make the controler more and more complex with each iteration. However, the controler ccouldn't possibly take the decision to switch scene by itself. I can easily give example of this: the game over scene should be swtched to something else only when the game over animation is done, the game over scene should only be switched to if the game is indeed over and the menu scene should end when the user chooses an item in the menu. Now, there is no way for the controler to be directly aware of these events. It has to be notified somehow by the active scene and then take the decision of which scene it should switch to. In other words, there is no way to take the scene switching logic completely out of teh scene. So why bother reducing it when it is quite simple to manage (just a return statement) from the Scenes themselves. Plus, if you look at it as a state machine, it means that teh current state is stored in the controler, but that transitions between states are determined by the current state, which actually makes sense.

I am not saying this is the best way to do it, but putting the switching logic in the controler is not a better solution. It would mean that the logic for transitions between two scenes is spread over many classes... when there is no need to do so.

I see the scenes as having a complete MVC of their own. In many of them such as a GameOver Scene or the mainMenu Scene, it is more VC than M. The scene not only display a picture and animation, it also treats user inputs and can have model objects associated (in the case of the main game scene). Note that the scene itself is an agregate of other components.

What my response to teh initial poste really was is to return the next scene through a metjod call initiated by the controler. That and use singleton patterns for Scene classes.

Geee... I should watch myself, I keep writing extra long posts on this topic.
Quote this message in a reply
ylaporte
Unregistered
 
Post: #9
One of my goals when building this arcitecture was to minimise code changes when I add new parts to the game (Scenes). If I need to change the controler (I call it the dispatcher but who cares) everytime. That would make the controler more and more complex with each iteration. However, the controler ccouldn't possibly take the decision to switch scene by itself. I can easily give example of this: the game over scene should be swtched to something else only when the game over animation is done, the game over scene should only be switched to if the game is indeed over and the menu scene should end when the user chooses an item in the menu. Now, there is no way for the controler to be directly aware of these events. It has to be notified somehow by the active scene and then take the decision of which scene it should switch to. In other words, there is no way to take the scene switching logic completely out of teh scene. So why bother reducing it when it is quite simple to manage (just a return statement) from the Scenes themselves. Plus, if you look at it as a state machine, it means that teh current state is stored in the controler, but that transitions between states are determined by the current state, which actually makes sense.

I am not saying this is the best way to do it, but putting the switching logic in the controler is not a better solution. It would mean that the logic for transitions between two scenes is spread over many classes... when there is no need to do so.

I see the scenes as having a complete MVC of their own. In many of them such as a GameOver Scene or the mainMenu Scene, it is more VC than M. The scene not only display a picture and animation, it also treats user inputs and can have model objects associated (in the case of the main game scene). Note that the scene itself is an agregate of other components.

Geee... I should atch myself, I keep writing extra long posts on this topic.
Quote this message in a reply
Member
Posts: 201
Joined: 2002.06
Post: #10
As an answer to your example, the way to do this with controller deciding when to switch scenes would be to send an isGameOverFinished event to the controller. True that you would have to add to the controller to create new types of scenes, but this same code would have to be in each individual scene if not in the controller. Why add this complexity and extra coding?

I'm having trouble with words today. I also have to leave soon. I'll come back to this topic later.
Quote this message in a reply
ylaporte
Unregistered
 
Post: #11
Well actually the code is not eliminated from the Scenes... They strill have to determine which events to send and when to send them (such as your proposed isGameOverFinished). I beleive that putting the switching logic in the Scenes actually reduces the amount of code and complexity while reducing coupling between the controller and other modules.
In case of bugs in a particular scene switch you only have to look at a single place to figure out what is going on.
I fail to see how putting a big switch(){case:...} in the controller to map events with scenes to switch to reduces complexity. Maybe I just don't understand what you mean... I do have my share of problems with words in these forums too Smile
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Weird driver problem! Dracir 2 2,688 Jul 9, 2002 06:38 AM
Last Post: kainsin
  Game Engine Design / DLL Loading Mutle 4 4,306 Jul 5, 2002 08:59 AM
Last Post: Feanor