Decisions, decisions…#
OK, let’s cut straight to the chase - the first problem with starting something you expect to work with for years is the old ‘paralysis by analysis’! There are any number of choices you can make that you expect to live with for a long time and so it is easy to stall right at the gate. But hobby coding life is a bit different. I can actually change any and every aspect of this project in due course - the important thing is it will be my decision if, and when, I choose to do so. This is actually quite a radical thought for a professional developer used to all the constraints of the commercial work environment. Just relax into it - agree that whatever you decide now will change in the future but you will always own the choice, the timing and the outcome.
Next important personal agreement with myself, unlike in my professional life, is that throughout I am going to deliberately try to only address the immediate problem in front of me for the project I am currently interested in - maintaining momentum and exploring problems using code is more important than up-front planning or ideology. I am going to embrace the idea that good code structure for a game toolkit will emerge as I use it to solve problems in a broad range of projects! I expect to refactor a lot and iterate towards solutions.
OK - so what can’t I defer or avoid right now? Well, I guess I need to pick a language.
Language & Build System#
Despite a lot of time in C# land during my XNA days, and the serious pull of Rust in recent years I am developing my library in C++17. Whoa! I know some of you have already dropped your biscuits into your tea, and your tea onto your keyboards, so let me layout the case for the defence:
- This is a long-term project with stability at its heart - I don’t think C++ will let me down in this front.
- C++ really has already stood the test of time and the standard is truly open - Flash game anyone? remember Silverlight? No, thought not… sadly for me, I do.
- Standard updates are never forced - C++17 should keep me going for decades.
- Changes to the standard are almost never breaking (std::auto_ptr was obviously for perverts).
- libraries, APIs, support, examples and documentation are all going to be mature and widely available.
- I’ve been using C & C++ for 30 years and have already got over most of its peculiarities and foibles.
- I just really need to resist the overhead learning another language as well :) !
- I do, though, really want to understand the details of how things work. In not hiding much of the system beneath I can convince myself this is actually a benefit of C++? No, I mean that, honestly.
I will try to mitigate the downsides with some well-established idioms, coding patterns and practices - hopefully more on this stuff once we get into the meat and potatoes later in this series.
My other choice at this point is CMake to wrangle those cross-platform builds. Yes, I know it is drawback of the C++ choice that I even need to consider a separate build system and, yes, it is pretty horrible. But it is the least worst option for now. It does mean I am not dependent on a particular IDE (Visual Studio, Visual Code, CLion & Xcode will all provide support) and I can, and do, simply use command line, terminal or ssh for native builds.
I’m compiling using msvc on windows, apple-clang on MacOS, clang and gcc on Linux. I’ll get into the details about my CMake structure in a future post.
Graphics API#
OK, next most controversial decision is that I target OpenGL ES 2.0 as my graphics baseline. Not Vulkan, not even modern OpenGL. ES 2.0, from 2007. Why?
The practical answer is portability. ES 2.0 runs everywhere I care about: desktop Linux and Windows, macOS (for now), Raspberry Pi, web browsers via Emscripten, and even obscure ARM handhelds like the R36 Max. A shader I write once actually works on all of these without (much) modification. That’s genuinely valuable when you’re a single developer who doesn’t want to maintain multiple rendering backends.
The honest answer is also that I’m not building the next Unreal Engine. I don’t need compute shaders or tessellation or bindless textures. For the kinds of games I make - 2D sprite-based things, simple 3D scenes - ES 2.0 is entirely sufficient. Choosing a “better” API would add complexity without enabling anything I actually need.
The cost is real though. There’s no geometry shaders, no instancing (well, there’s an extension, but patchy support), no modern debugging tools. When I do want a more advanced effect, I have to get creative or accept the limitation. And there’s always that nagging feeling that I’m learning an obsolete API.
I have, as with some other dependencies, built a simple abstraction layer between most of my rendering code and the OpenGL ES2 GraphicsDevice implementation so I am leaving the door open for a future implementation on top of a different graphics API…
Dependencies#
My starting point here was no complete dependencies so, as with the OpenGL ES 2 graphics device, almost all 3rd party libraries (see below) are hidden from the core Gremlin classes behind a thin abstraction layer - with one exception.
Direct Dependency - Maths & Linear Algebra#
I have previously written my own fairly extensive geometry and linear algebra library, but I honestly never perceived any tangible benefit from this. Even in a hobby project I feel compelled to write extensive unit tests for library such as this. If cross-platform, cross-compiler and multi-architecture is going to burn me anywhere it will be the hard to debug subtleties of precision and low-level maths algorithm performance and behaviour. This is just a headache I really wanted offloaded to a much more widely tested framework.
GLM#
I chose the header-only OpenGL maths library GLM because it is mature, robust and has common conventions with glsl shader maths. I did not write any abstraction layer here. Although I have stated I am not worrying unduly about performance issues, vector/matrix data and functions are utilised extensively on the hot path of every application and so the penalties of any indirection just can’t be ignored.
Abstracted Dependencies#
I will discuss this pattern in more detail in later posts, but I have used the Private Implementation (pimpl) idiom extensively to create an abstraction layer between specific 3rd implementations of key functionality.
OS Window, GFX Context Creation & User Input - SDL2#
You will note a theme developing - I have deliberately stayed off the bleeding edge whenever possible. SDL3 was similarly avoided for now. I have used SDL2 to back my OS window and OpenGL context creation. This has proven a fantastic decision so far because SDL2 is just so mature and ubiquitous that in several important cases I have been able to utilise existing system setup or other trail-blazers’ work to get my stuff up and running on the back of pre-existing SDL2 support. Nice.
Audio - OpenAL#
Not sure about the OpenAL API - it is meant to be OpenGL-like but I was glad to get it wrapped up and then not have to touch it again! It is a more powerful API but I could probably have leveraged the SDL2 audio mixer with the same effort for my simple use case. Actually I have been pleased with the choice though, as there has always been extensive existing support for OpenAL everywhere I have needed it.
PNG images & TTF fonts - Sean Barrett#
I’ve use two of Sean’s header only classes (via a pimpl interface) from his STB library of really useful classes for my bitmap image and ttf support. Probably revisit this library for ogg vorbis audio file support at some point too. Thanks Sean!
AI?#
Yep, I am not taking any ideological position on this - my sycophant of choice currently is Claude Code. I still tend to do a lot of typing myself (because I like it) so Claude helps with true boilerplate shizzle or as a planning and research tool primarily. In due course, I may use AI for art asset creation but, as with the coding, I am doing this stuff as leisure activity, so I want to make art, sound and music - that is all an intrinsic part of the fun! So, as with Claude, I expect I will look more for inspiration than implementation.

