Firstly I was quite taken with the idea of smart pointers, after reading Superpig's Enginuity articles. I decided to implement them, and use them for the main elements in the engine (dropping the 's for ease of typing). My implmentation for the moment is much like Superpig's. It took me a little working out to get it right though, as that was the first proper use of templates I had done.
After that I've pretty much struck out on my own, for better or worse. I figure that's the best way to go. The main idea around the structure is that there is a central Kernel (although not necessarily the only Kernel), and the kernel serves as a sort of "router" for the rest of the structure. The application and the various components - GLRender for OpenGL Rendering, SDLInput for SDL Input etc - register themselves with the kernel, as well as requesting a certain set of messages. So the application would probably request initialisation, destruction, update, rendering and input messages, but the SDLInput component might only request initialisation, destruction and rendering. Each component can then send messages to the kernel, and the kernel will disperse the message to each of its children that requested that message. This way none of the children need to know what other children are in use, but can let the kernel deal with that at runtime.
The pros and cons that I can see are:
- The components do not need to be aware of each other, the kernel sorts out getting messages to the right destinations.
- I could set up a system to add remote children - children across a network. ie. I'd then add a kernel as a child of another kernel and likely the opposite too. This sets up a peer-to-peer kind of system, so that update messages can run through several kernels. I could then have one kernel as a "server", and several others as "clients", children of the "server". The clients can send messages to the kernels (updates depending on user movement/whatever) and vice-versa. So there's no extra design setup for networking.
- The engine is modular, in a way. I can take out the rendering component, and nothing changes. This way I can also use this framework for text-based or other type programs.
- I need to package things up in message format, rather than using function calls. It becomes a little bit more hassle than simply calling a member function.
- I don't know how much of a performance hit I'm going to get from doing things like this. I'm trying to optimise the kernel as much as possible, but it might end up being slower than I think.
- It might end up that children that only want some messages end up getting messages they don't need. I don't know how common that will end up being, and how much that will slow things down by.
In the end I think I'm just going to have to go for it and see what happens.
I'm also trying out doxygen in this project, because my previous projects have all been way undercommented. I've got a slightly old set of docs up here which you can look at if you're interested.
Anyway, engine design is much the pain in the neck.