Entity Component System

fightlessbirds

New member
CX Code Contributor
Joined
Apr 15, 2022
Messages
7
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.

rcge-ecs-uml.jpg


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.

Here we can see a simple usage example:
Cerberus:
Local myEcs:= New Ecs()

myEcs.AddSystem(New MoveSystem())
myEcs.AddSystem(New DrawSystem())

myEcs.AddComponent("Position")
myEcs.AddComponent("Image")

Local myEntity:= myEcs.CreateEntity()
myEntity.Bind("Position")
myEntity.Bind("Image")

myEcs.Update(deltaMillis)

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.
  1. Create a new Ecs object.
  2. Add user defined Systems to the Ecs.
  3. Add Component classes to the Ecs.
  4. Create Entities, bind/unbind Components, whenever you like.
  5. Update the Ecs once per iteration of your game loop.
  6. Kill Entities when they are no longer needed.
Example System:
Cerberus:
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.

This module is available on Codeberg as part of my game framework.
 
Last edited:

MikeHart

Administrator
CX Code Contributor
3rd Party Module Dev
3rd Party Target Dev
3rd Party Tool Dev
Joined
Jun 19, 2017
Messages
3,504
Welcome! That looks quite a bit of work you put in there. Thank you for sharing it.
 
Top Bottom