xbEngine

This page documents my ongoing work on a custom engine to be used with applications and games.
After having used Unity and Godot for several years, I wanted to create my own engine from scratch.
My engine is using SDL2 to communicate with the platform and future implementation of Vulkan for 3D graphics is planned.


Platform Layer

2025

XB_platImgA

The first step on my journey toward my own engine was the platform layer.
I wanted to support as many platforms as possible and write platform code that would not need to be changed frequently. The SDL2 library seemed like a good choice for me. It is lightweight, supports a large amount of platforms and is also well integrated into Steam. The API is nice to use as well.
The boundary between the platform code and the application code is designed to be very strict, so changing the platform layer to use a different method of communicating with the hardware would be possible without modifying the application code itself.

I did a lot of research into game engine architecture before writing my code and found Casey Muratori's Handmade Hero to be a good reference.

My code is written in C++.
The underlying architecture of my engine is as follows:
A separate compilation unit is created for everything that is platform dependent, that includes audio, input, managing the window, managing memory, etc. Essentially anything that has to talk to the hardware goes in that file. (sdl_xbEngine)
The platform layer communicates with the operating system and thus hardware via SDL2 and in the future Vulkan.
It also contains the main update loop.
From that loop, calls get made into the application code itself. (xbEngine)
The application code can then be totally platform independent and would not need to be changed when the platform code changes.

XB_platAnmA

I have uploaded an initial, working version of the platform layer (plus mini engine) to github.
That version implements some test functionality, such as a framerate independent scrolling texture, a modulatable sine wave audio tone output, and keyboard input visualization along with window management.
It is currently using a simple software renderer to display the image to the window.

This engine is not a finished product but I hope that anyone interested in creating their own engine as well can look at it for reference.


First Explorations

2025

XB_frstImgA

To test my design, I started to implement some ideas I had about creating and simulating a procedural world.
Currently, the result is a 2D representation of a landscape's height that gets created from a randomly generated noise texture.
Then, as an additional property, a texture representing temperature gets created. The temperature is dependent on a simulated daily and hourly temperature value.
Given these two input values, my next goal was to create a simple simulation of migration patterns for animals.

XB_frstImgB

An amount of animals are randomly distributed across the landscape.
They have a desired target height and temperature. Every iteration, they should move towards a more desirable location.
To simulate more realistic migration patterns, I use a loss function to decide on where they should move. The value of a location gets modified by the distance of the animal to it, to decide on which direction to move in.
The image shows the loss function from >= 0.0 (red) to 1.0 (green) for the animal marked as a blue square, with more green values being more desirable.

XB_frstAnmA

The temperature desirability is marked in magenta in the animation and changes over time depending on the daily temperature and some randomness. It gets combined with the height and distance in the loss function.


Hot Reloading

2025

XB_relAnmA

During my initial explorations, the update cycle was pretty slow, as the entire program had to be recompiled and restartet, losing all state changes in the process.
To incentivize faster iteration and decrease friction when making changes, I implemented a hot reloading feature into my code.
I changed the platform independent part of my code to be compiled into a shared library instead of being compiled into the main executable itself.
Having an automatically reloading library allows for fine-tuning of parameters and functions while the program is running, similar to an interpreted language but without the performance disadvantage of them.

XB_relImgA

The engine component that contains all the update functions was changed to a shared library, which gets loaded in by the platform layer that contains the application's main loop.
All persistant memory is allocated in the platform layer and a pointer to it is passed to the shared library. In turn, the shared library contains the update function's implementation and the platform layer has a pointer to that function that gets called once per iteration.

By implementing loading and unloading of shared libraries and their functions, the library can be reloaded while the program is running.
Because memory is managed outside of that library, the application's state can persist even when changing functionality, as long as the memory layout remains the same.
Deciding when to reload the shared library is done by checking the compiled library's modify time against the that time stored when it was last loaded.