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.