I consider to build a game engine with the following design approach.
The principal characteristic is to create so called systems, which cover game menus and game levels. These systems are provided with objects like Window to draw, Input to fetch, Sound to play, and maybe Network to communicate with a server.
class System // abstract class
{
Window* Window;
Input* Input;
...
System(Window* Window, Input* Input, ...)
{
this->Window = Window;
this->Input= Input;
...
}
virtual Pause() = 0;
virtual Resume() = 0;
}
The main function handles the systems thus menus and levels. Say LevelOne is derived from System.
int main()
{
LevelOne Tutorial(&Window, &Input, ...);
Tutorial.Pause();
...
}
This way my code becomes structured and (in my opinion) easy to understand. But how could the main function communicate with the systems?
For example, how could the menu tell the main function that the user had selected a level, and which one? In order to let the main function delete the menu and create a new level object.
I think what you are trying to do here is organize a complete model-view-controller architecture, and the code you provided here is the model and controller portion of it. See some explanations on MVC on the web:
http://www.codinghorror.com/blog/2008/05/understanding-model-view-controller.html
If you have a single main() function trying to listen for messages from your subsystems and calling the appropriate actions as a result, you are trying to implement a single-threaded reactive message loop. You could consider running an ACE reactor that can listen for Qt GUI messages as well as others such as network events, then call your subsystems appropriately (though there may be some performance issues):
http://www.cs.wustl.edu/~schmidt/PDF/reactor-rules.pdf
I am not familiar with graphics engines for video game programming, but most graphics libraries offer a message loop for you during its initialization that doesn’t require you to go through this kind of detail. All you typically have to do is create your graphics objects and register them with the main message loop of the library.
And I would recommend using a separate thread listening for network events compared to your message thread listening for graphics events. It separates the work out and helps to improve the performance of your graphics.