#1 Lina Engine: Initial Layout
One of the hardest things about trying to start writing an engine from somewhere, was to decide what kind of a layout that our systems would be bound to. To do that, we first needed to actually define our boundaries of the capabilities of the engine. Here is our initial thoughts:
The engine would be able to run on Windows, Mac and Linux platforms.
The engine would be focused on 3D rendering for now.
Our initial type of game genre would be First Person Shooters.
We would have basic input, events, physics and rendering systems.
No editor is being thought about for now, maybe we plan to add some editor features after we pack the whole framework together.
After throwing out couple of more ideas about the technical specifications of the engine, we thought the best way to define our boundaries better is to start witing some stuff somewhere, and see what the road brings next. First we should think and decide about our implementation specifications. Language? IDE? Libraries? So, we did our research, and initially decided on few things:
C++: We decided to go with C++ 17 to write our engine. Since it's the most logical option, because we would be dealing with a lot of low-level surface stuff and we need to build our own libraries and operations from scratch. CPP is the only language, that is capable of providing Object Oriented Design in such manner that efficiency is the key and you only get what you use, no unnecessary performance overheads. So it's the one to go.
C++ / CLI: For the future steps, we thought maybe we could write some form applications with C# for providing an editor to the engine framework. Then we would simply use C++ / CLI to achieve interoperability between C# editor classes and our C++ engine API.
Visual Studio 2017: Of course, my favourite IDE, with enough features to handle such a huge project, with it's awesome C++ 64x Compiler, Debugging Tools and extensions.
Simple Direct-Media Layer: We would use SDL to handle our low-level interactions with the hardware. In order to receive input, operating system window handling, creating contexts and handling them over windows for GPU, any many more, we decided to use SDL due to it's extensive features and sources online.
OpenGL: We had decided on using OpenGL for our rendering. Maybe in the feature, we can implement a rendering system that would work on different modules, so that OpenGL would be one of this modules, as well as DirectX, but for now, we would stick with OpenGL, due to it's robust ability to communicate with the GPU and sources online.
GLEW: To extend the features of OpenGL, there is nothing better than GLEW extension library.
After picking our libraries in our baby steps, we started to struct the initial layout. For that, we have to declare our must-have systems, so that we can start to figure out where to begin and what to do. We figured out that we would have:
Core System: Responsible for managing the main loop, and calling the necessary loop methods for other systems.
Rendering System: Responsible for all the rendering for now.
Input System: Responsible for receiving input from the hardware through the SDL.
Physics System: We don't need it initially, but we would like to have some cool physics eventually.
Gamecore System: A system that would receive function calls from the core, and will be responsible for scene handling.
Scene System: Will be responsible for object handling in an existing scene.
These were the initial system we think we will have. These are the low-level systems in the engine architecture, and the layout for them is very important, because if we mess up and create a spaghetti festival in the low-level systems, then for sure the high-level game classes will suffer due to the conflicts and injection issues. So we had to come up with a robust way of communications between these systems. For now, we decided that our Core would be the center in these communications.
This, of course, is a really primitive explanation of the layout with my state-of-the-art drawing skills.
However, even when it can look naive and simple, the problems begin to arise with even this less amount of systems. See, there would be cases, Input & Render would need to communicate, as well as the others with each other. Core sending messages and managing other systems is fine, but the other way around, the communications of the systems to each other, is a though step to decide. Of course, if you like an architecture that resembles Red Wedding from Game of Thrones, you can come up with something like this:
I know, my amazingly inaccurate drawing skills doesn't help, but you get the idea. Imagine a communication system like this, think about the dependencies. A single change in a single system may affect many others. And it will even get more and more complex as the sub-systems and high-level communication gets involved. So, a direct communication between the systems like this, is a no go. Then what would be do? Well, one option is to make Core handle every communication between other main systems. But then, it would clutter the Core system a lot, and it's important for it to run efficiently, since it will be dealing with the main loop of the whole engine.
Then, what would be do? One other option is to use framework integration. Now, that means that, we would be collecting all of our important main systems, into a single framework. And the communication of main systems with each other, would be done via the framework, while an external message bus handles all other communication of the framework to the core and through it, high-level game classes.
Look at this image that I definitely found online, and think of the services as our systems. We would group each X amounts of services together into a framework, and than the message bus system will handle the messaging. No system would need to have a dependency to another one, it would just fire off messages to the bus and the interested parties would pick them up from the bus. It's a robust and a nice way to go, however, too many message handling will slow our main communication down, but it can be an affordable trade-off on the long run.
So yeah, basically we had thought about several structures and ways to handle messaging, and would definitely try to implement something robust. As the progress will take place, we do think of handling the communication with a hybrid system between message buses and direct dependencies. For now, our next step is to figure out the main engine loop in the core system, so that we can start trying some stuff out and iterate our messaging throughout the process.
Github Repo: https://github.com/inanevin/LinaEngine