2024-04-01

Project Dusk #8 - Realizations

First a working build:

"Global states are evil" isn't a new insight, but I am learning more reasons why this is the case firsthand. I haven't achieved hot reloading the game while retaining the game state. The reason is, that quite a few things taken for granted don't mix well with unloading and reloading code (just similar to how impossible it is in Unity to develop a game in a way that hot code reloading works). While global state variables are obviously problematic, there are other not-so-obvious global value types that we typically don't recognize as such. Function pointers for example. When creating the scene's content and creating objects and components, storing a function pointer inside a component is a sureway to not only make the object not serializable, it's also going to crash when trying to reload the code. The reason is, that the function pointer is pointing to the old code, which is no longer there. I assume C string literals are also problematic, but those can be copied easily.

To add insult to injury, I am suffering also from having worked out a lot of code before I came to the conclusion that this isn't really a demo sized coding test but an actual game. There's no better way to test an API if it works for making games than actually making a game, so ... this is something worthwhile to do. But I am suffering from a couple of problems from this approach:

The latter point is most annoying. Here's what I mean with that:

Initially, I had 4 to 5 different files and several different locations in each file where I would write the new component content with quite a bit of repetition. I am attempting to reduce this to make it easier adding new components, but while it works perfectly well on paper, the actual implementation suffers from bad IDE support because it's macro based. The basic idea is rather simple:

// a list of all components "components.h"
COMPONENT(HealthComponent)
COMPONENT(MeshRendererComponent)
COMPONENT(VelocityComponent)
...

// some other file: function declarations to register components
#define COMPONENT(name) void name##_register();
#include "components.h"
// produces: void HealthComponent_register(); ...
#undef COMPONENT

// in some function:
void registerComponents() {
    #define COMPONENT(name) name##_register();
    #include "components.h"
    // produces: HealthComponent_register(); ...
    #undef COMPONENT
}

This basic example (my code works differently) shows how to reuse a header file that contains a list of component names to generate different looking code in different places. I actually changed the "components.h" file to include a file that depending on the context provides the declarations and definitions. So technically, this is reducing the repetition a lot and only the actual file and the list file needs to be modified when adding a component - which is really a great improvement. The downside is, that the IDE is quite confused how the file is supposed to work when I edit it and I regularly see error highlights or syntax highlighting that is off. So I am still trying to figure out a better way to solve this.

🍪