Entity Component System for Cerberus X


For my previous game (Bird Hop) I wanted to use an entity component system, but there were none available for BlitzMax, so I coded my own. Now I am using Cerberus X, and again there is no ECS module available, so I’ve translated my BlitzMax module. In rewriting the module, I’ve cleaned it up and made it more robust.

There are three key elements to the module: Entities, Components, and Systems. An Entity is a thing. Components are characteristics of things. Systems contain logic that is applied to things with certain characteristics. In a game there could be a component for a 2D position, and another for an image or animation. A movement system could select entities with a 2D position, and move them according to their speed. A rendering system could select entities with 2D positions and images/animations, and draw them to the screen. This approach is much more flexible than a class hierarchy approach. Entities can be built, changed, and destroyed at runtime.

'Create a new Ecs object
Local myEcs:= New Ecs()

'Add user defined Systems to the Ecs
myEcs.AddSystem(New MoveSystem())
myEcs.AddSystem(New DrawSystem())

'Add Component classes to the Ecs
myEcs.AddComponent("Position")
myEcs.AddComponent("Image")

'Create Entities, bind/unbind Components, whenever you like
Local myEntity:= myEcs.CreateEntity()
myEntity.Bind("Position")
myEntity.Bind("Image")

'Update the Ecs once per iteration of your game loop
myEcs.Update(deltaMillis)

'Kill Entities when they are no longer needed
myEntity.Kill()

Note: User defined System and Component classes must be added to #REFLECTION_FILTER. Some of the ECS’s inner workings rely on reflection.

Class DrawSystem Extends System
    Method GetArchetype:String[]()
        Return ["Position", "Image"]
    End
    
    Method Update:Void(entities:List<Entity>, dt:Int)
        For Local e:= EachIn entities
            Local pos:= Position(e.GetComponent("Position"))
            Local img:= Image(e.GetComponent("Image"))
            DrawImage(img, pos.x, pos.y)
        Next
    End
End

My ECS is designed with a naïve object-oriented (OO) approach, however there is a more advanced, more performant way via data-oriented (DO) design. Some excellent examples of DO ECSs are EnTT and flecs.

Click here for a simple example of the ECS.

This module is available on Codeberg as part of RCGE.