Developing a game engine can be a lot of work. Over the years, I’ve developed quite a few game engines, and I’ve learned a lot of lessons doing it. I want to share some of those lessons by giving a very high level overview of my current game engine.
When developing my current game engine, I wanted it to be modular and expandable. Because of this, I decided to make the engine into separate libraries and I tried to limit dependencies between libraries to the most minimal extent possible. This methodology also carried over to the way I designed my individual classes. Limiting dependencies is one of the most important things that I feel is needed to write clean maintainable code. Below is a diagram of the main libraries that I created for the Squared Game Engine. Note that these are libraries and not classes and that the graph shows the dependencies.
I keep to this strictly. The code in DSquaredCore knows nothing about SquaredDPublic and should never directly or indirectly try to access anything inside of it. DSquaredNet “knows” about DSquaredLogic, but DSquaredLogic should never try to access DSquaredNet. Keeping these strict dependencies has helped my quickly spot design issues in other parts of the code. Sometimes code needs to be made quickly to get things done, but fooling around with the dependencies is unacceptable.
But what is in all of those libraries? Here’s a quick overview.
The purpose of classes and functions under this namespace and library are to provide a multiplatform framework from which the game can be built from. For platform support and graphics, I have separate libraries for each platform that link with the rest of the application. For example, I currently have two WindowsDirectX9 and a WindowsDirectX11. When one of those libraries is linked with the application, the other classes in this namespace will use them to provide graphics and input support for the application. Initially, this namespace was just a bunch of utility functions, but it’s been morphing into the basic game framework. For the 3D engine, the code in SquaredDPublic has been locked. The next version is being built alongside an experimental 2D engine. In the future, I want SquaredDPublic to be able to be the base for any type of game. Currently this code is closed source, but I in the future I want to release the source code of it with demos. That’s why I named it SquaredDPublic.
I developed DSquaredCore to be the core components of a game and able to exist with or without graphics, sound, and user input. DSquaredCore provides functionality but it was meant as a hub to which other modules should link to. I did this because I wanted to be able to build a graphical game, and at the same time be able to build a console-based server only version. The code in this library includes the game state manager, the game loop, and the component-based entity system. The code in this library was developed to work with the code in SquaredDPublic, but it can work with any graphics engine as long as the proper “bridge” code is written for it.
DSquaredLogic as its name implies has the code that includes most of the simulation logic. It provides classes for physics and collision detection (via NVidia PhysX), AI, and the base character controllers. The classes in this library are focused on the game logic needed once gameplay starts. It also has some basic code for initializing levels. The code was written with expansion in mind so there are many places for linking in extra features. The game uses component-based entities so AI and physics components are defined in this library.
DSquaredNet uses RakNet4 to provide networking capabilities to the game. It has classes that plug into DSquaredLogic to handle network connections and synchronization. One major design decision that I made early on was I wanted to be able to make a server only console app without graphics using only DSquaredCore, DSquaredLogic, and DSquaredNet.
DSquaredGame provides functionality to link the engines core systems with SquaredDPublic to make a game with graphics, sound, and user input. DSquaredGame provides all of the graphics entity components. DSquaredGame was designed for 3D games and doesn't provide any 2D support apart from what's provided in SquaredDPublic. The GUI system is totally separate and interfaces with SquaredDPublic directly to to access the 2D functions.
The code in this library started out as game specific code. Over time I saw that it could be reused so I extracted the code into it's own library. The code in this library helps to bind everything together. This code is not needed when making a game using the engine, but it greatly simplifies the task of making 3D multiplayer games. Game specific code under normal circumstances will only need to access the code in this library. Game Specific Code
There are some other things that in the code that I didn't mention, but these are the main parts. From this, you can get a basic understand of the engine’s modular design.