log #1: the entity system

Time interval: 2022-12-30/2023-01-14

I started out by working on the entity system for my game. It had to support the following things:

At first I went with a design similar to what I used in the unfinished RAIDER rewrite. It basically tried to emulate inheritance using umka’s interfaces:

// the "base class"
type EntPs* = struct {

type Ent* = interface {
    getPs(): ^EntPs

This worked well, but had one major issue - it was pain to work with and required a lot of boiler plate, since every entity would have to implement lot of (often empty) methods. For this reason I decided to abandon this idea and try an event driven design instead. I extended tophat’s signals and got to work.

This worked out well, especially since most entities only do something when interacted with. Each entity also has a tag. The tag is a bitfield, which says what the entity supports etc. For example there is a tag for collisions or interactions.

I also added support for items, which can be picked up and then used. Example of a pocket watch item:

gif showing the pocket watch item

adding proped support

I also implemented PropEd definitions for the entities. I had to make some tweaks to how PropEd loads resources to make it usable as a library, but overall it was a simple task and I definitely plan on adding more PropEd defs later down the road.

gif showing proped support

loading entities from a file

Last thing I added was the ability to load entities from a file. I chose TOML as the format I will be using in the game (i use toml.um by skejeton to parse it. You can define basic properties of entities like this:

t = 4
i = "watch"
x = 2.0
y = 2.0

When the entity is loaded, it is available as res.ents["watch"]. The image is specified as a string. This is possible because all loaded images are also accessible by name from a map. You can also specify an init function for an entity.

res.registerEnt("box", function(e: world.Ent, ctx: any): world.Ent {
    printf("initializing the box entity\n")
    return e