Let's Make an Engine: Project
Welcome to the first entry in a series where we will be creating a modern game engine from scratch using C++. It is the game industry standard and the language I am most comfortable with having used it for over 20 years now.
As a professional working on AAA games, it can often feel like the fable of the blind men touching an elephant, where you are only able to see a small part of the project at a time and never really grasp the totality of it. Adoption of new technology is also frequently slow, as companies are understandably risk-averse in the latter stages of a project’s life cycle. This series gives me the opportunity to revisit topics I haven’t had to seriously consider in many years, reevaluate my priors, and stay up-to-date with the state-of-the-art. I hope that others reading these posts will also find value in following my journey.
We will utilize SDKs and libraries where it makes sense. While there is value in learning about concepts such as the inner workings of the zlib compression algorithms, that is a separate journey. Our goal is to start simple and gradually build up to a game engine that can be used to create a variety of simple games.
Setting Up the Project
There are an infinite number of choices to make with a blank canvas so we just need to start. Our dev environment of choice is a Windows 10 host running VS 2022 with CMake using the latest C++ version.
We need 3 things to get started:
- Engine: A place to code the engine.
- Game: A place to code an app that uses the engine.
- Build: A build script to make the builds.
Engines are frequently coded as a library. If done well this can allow you to reuse the engine across multiple projects. Even if you are only interested in a single project it can be advantageous as game-only changes do not require rebuilding the engine which can typically take a while.
We’re going to use a C++ Module for our engine. It will start here as an empty placeholder we can fill in with features later.
This creates an empty module named LetsMakeEngine and exports a namespace also named LetsMakeEngine. An explanation of modules is beyond the scope of this post but I encourage you to watch this excellent presentation A (Short) Tour of C++ Modules - Daniela Engert.
Now we need a game or app that uses our engine to build something cool. Well we can worry about the cool part later. For now let’s just stub out a dirt simple empty game loop.
This is as simple as it gets. In fact it does literally nothing but spin in an infinite loop. I promise things will get more interesting quickly. Nevertheless let’s make sure this works before we move on.
We need to define the build script for our project.
A couple of things to note here.
We use 2 CMakeLists. One for the game and another for the engine. This isn’t strictly necessary but will make it easier to separate concerns later.
We’re using file glob with
CONFIGURE_DEPENDS this is fairly new. The standard best practice is to list out all of the files manually but this is safe and plenty fast for now and makes it easier to add and remove files as we rapidly develop.
And finally the helper function that enables C++23 and standard library module support.1 Tooling support for modules is fairly new, these are the incantations that work for now but it will change and become easier before long.
Going forward we’ll only show changes to the CMake configuration as necessary.
One final thing related to the project setup is setting up version control including a suitable ignore file to exclude intermediate and generated files from source control. Setting up a .gitignore or .p4ignore is beyond the scope of this article but there are plenty of examples available online.
With the skeleton in place, we are now ready to begin writing the interesting code for our game engine. While there isn’t much to see in this current setup, it is simple and flexible, providing a solid foundation for our future development.
In the next entry, we will transition from a terminal application to a proper GUI window.