[2D Game Engine] Starting A New Project - The Project Setup
Edit 02/2023
Since I haven't found time to proceed on this project and it seems this doesn't really change in the future, I wont continue on an entire 2D game engine. I renamed the github repo so nobody gets confused anymore and I'll make a post on entity-component-systems with a a SDL example there.
Find the project here: https://github.com/ThoSe1990/sdl-ecs-example
First things first, since you probably don't know me. I'm not a game developer and I don't work in the game industry. But I like games and grew up in the 90s with my Game Boy, Nintendo and some other devices to play video games. However, I'm a C++ developer and this brings me to this sideproject, to have fun, to learn and to write about.
Game Engines helped me in the last years to improve coding, because learning with a game is more fun, isn't it? Three specific sources I want to mention here are:
So thanks to the authors to make their code available to others (like me) that we can take advantage of that. I'll use code snippets from here and explain them to the best of my knowledge.
A 2D Game Engine From Scratch
In the next articles I'll create a 2D game engine. I try to go step by step to have a dedicated topic for each article I write. A rough estimation about the posts can look like this:
- Project setup (this post)
- Creating a window class
- Creating an event system
- Creating an entity-component-system
- Adding components (transform, sprite, collider, tilemap, etc.)
- Integrating Lua (scriptable component)
- Creating an API, API tests and a Python API
- Adding a camera
- ....
Project Setup
You can find the project on GitHub. The game engine shall be cross plattform and run on Windows and Linux. I don't have a Mac but actually it should work on it too. This means we'll use CMake.
External Dependencies
Basically I wanted to use Conan for external dependencies but I couldn't find the required packages available for GCC on Windows (I only found them for MVSC, but I don't use Visual Studio). I don't like git submodules nor CMake's external projects, so we're installing them manually. In my experience this keeps the CMakeLists
more clean and you install dependencies once and have them always available then.
We'll need SDL as media layer, spdlog for logging and googletest as testframework.
Installation On Linux
I'm running a Ubuntu 20.04 and use the package manager (I presume build tools are installed) to install. To do so, run the following commands in the terminal.
sudo apt install libsdl2-dev
sudo apt install libsdl2-image-dev
sudo apt install libsdl2-ttf-dev
sudo apt install libspdlog-dev
sudo apt-get install libgtest-dev
Installation On Windows
We'll install all libraries separately.
SDL
Download prebuild SDL libraries (SDL2 and SDL_image). Place them on a destination of choice. Later you'll pass the path of your location to CMake.
https://www.libsdl.org/download-2.0.php
https://www.libsdl.org/projects/SDL_image/
spdlog
Clone the spdlog git repository and build it. Set CMAKE_INSTALL_DIRECTORY
to the desired install location. On my private computer I use in general ./build/out
as install directory.
git clone https://github.com/gabime/spdlog.git
cd spdlog
cmake -S . -B ./build -DCMAKE_INSTALL_PREFIX=<drive>/<current project path>/build/out
cmake --build ./build
cmake --install ./build
Googletest
Like spdlog, download and bulid googletest from GitHub. Set CMAKE_INSTALL_DIRECTORY
to the desired install location.
git clone https://github.com/google/googletest.git
cd googletest
cmake -S . -B ./build -DCMAKE_INSTALL_PREFIX=<drive>/<current project path>/build/out
cmake --build ./build
cmake --install ./build
Build And Run
Use CMake with following commands from the project root directory. You'll build an example unittest and an executable where a SDL window pops up for a few seconds. The install directory is in ./build/Debug/bin
or ./build/Release/bin
depending on the build type and the chosen build directory.
cmake -S . -B ./build
cmake --build ./build
cmake --install ./build
If you're running on Windows, add the following variables to your CMake build:
-DSDL2_PATH="<path to SDL2>\\SDL2-2.0.20\\x86_64-w64-mingw32"
-DSDL2_IMAGE_PATH="<path to SDL2_image>\\SDL2_image-2.0.5\\x86_64-w64-mingw32"
-Dspdlog_DIR="<drive>\\<projects>\\spdlog\\build\\out\\lib\\cmake\\spdlog"
-DGTEST_ROOT="<drive>\\<projects>\\googletest\\build\\out"
Additional Tools For Development
Later means never, this means we are integrating additional tools from the beginning.
clang-tidy and cppcheck
For static code analyzis we'll use clang-tidy and cppcheck. Thanks to Jason Turner I took the additional cmake files and the .clang-tidy file from here. Enable the corresponding variables in cmake -DENABLE_CPPCHECK=ON
and -DENABLE_CLANG_TIDY=ON
.
clang-format
For automated formatting we use clang-format. Up to now I didn't find an integration in cmake, so I'll use clang-format manually. I took the .clang-format file from here too.
Compiler Warnings
There are plenty of warnings enabled on each compiler, also this I took from the cpp_starter_project and we can make use of the CMake Interface library project_warnings
.
Code Coverage: LCOV
It is helpful to have a coverage report. I'll use lcov and please note this only works (at least for me) on Linux with GCC. Thanks to the author of this cmake file.
Use -DENABLE_COVERAGE=ON
to enable the coverage report. Run the cmake configuration and then explicitly build the target gtest_coverage
.
cmake -S . -B ./build-linux -DENABLE_COVERAGE=ON
cmake --build ./build-linux/ --target gtest_coverage
During the build the tests are executed and you'll find the report in your build directory: ./build/gtest_coverage/index.html
. Navigate to a dedicated file to see the executed lines in the code. In this case take a look at this example test case. The executed lines are highlighted in blue.
Precompiled Headers
All system headers in this project are in ./src/cwt_pch/cwt_pch.hpp
. You can enable -DENABLE_PRECOMPILED_HEADERS=ON
to precompile system headers and to reduce compile time. I had sometimes issues by using it in Windows, if so, disable it (quickest fix for now...).
Azure Pipeline
I integrated Microsoft Azure for builds on the repository. So we'll make sure the project compiles and all written unittests are passed.
Conclusion
So thats my project setup for now, I really wanted to integrate conan, but as I mentioned I haven't found SDL and spdlog for Windows GCC. I know about hosting own packages, but this will be another article.
Anyway I think this is a good start, in the next article we'll create the a window class to soon render something on the screen.
If you have other useful tools or tips, feel free to get in touch with me.
Thats it for now.
Best Thomas