Boy this is something I spent a lot of time with. There are a lot of books for stuff like this, but I've never found an optimal solution. I think that it's because there
is no optimal solution. There will always be something you didn't think of later on in the coding phase, and you have to refactor your code because of it. The best way to go about your code is to design as many independent segments as possible: you should be able to change one part of the code without having to change too much, if any, of the other parts of the code.
But that's general advice for programming. The way I have my engine set up is that there is one application manager that handles various subsystems, like sound, input, video, and then calls an event functions on a scene class. Something like this:
class ApplicationManager {
Scene *currentScene;
public:
ApplicationManager() {
currentScene = NULL;
}
void setCurrentScene( Scene *scene ) {
scene = currentScene;
}
void Start() {
// Set Up SDL things, like the window.
SetupSDLAndSuch();
current_scene->OnInitialize();
while( SDL_Events ) { // I forgot the exact syntax
if( event == SDL_KEYDOWN )
currentScene->OnKeyDown( event.key );
// etc
}
}
}
class Scene {
void OnKeyDown() {
// Whatevs
}
// more handlers
}
void main() {
ApplicationManager appMan;
appMan.setCurrentScene( new Scene() );
appMan.start();
}
That's the jist of what my engine is doing, minus the exception handlers. It's pretty clean, but I'm always adding new things to it, and sometimes I have to refactor more code than I like. There's only so much abstraction you can do, and although you should make things (classes) as independent as possible, don't go crazy with that otherwise you'll end up with some crazy message-passing scheme and custom scripting language. Code readability is key.
This site was helpful:
http://gpwiki.org/index.php/Main_Page. Lots of design suggestions. As helpful as that site was, I found that the only way to really know if a design is good or not was to try it out.