The RDBMS with "all code in external systems" approach to ES design
(based on: RDBMS Inspired)
(a.k.a. "ES Alpha")
Build an API for your ES that is conceptually identical to a relational Database, plus:
- disallow mixing "code" with your data
- create monolithic, opaque "Systems" which contain all the code necessary for a chunk of functionality
- e.g. "Physics System" runs once every 10 game-ticks, iterates over all physical objects, runs a frame of the physics-simulation
- e.g. "Rendering System" runs once per game-tick, iterates over all objects that have a 2D/3D representation, and renders them to screen
- e.g. "Positioning System" runs once per game-tick, combines physics-sim data, and player input, and info about the game-HUD, to set the positions of all renderable items
Extensions to this Approach
* RDBMS Beta - adds some practical improvements
Discussion and documentation
The T-Machine articles claim this is "anti OOP" (splitting code and data, instead of keeping them together in classes). A very long and detailed discussion of this approach, with thousands of comment-posts, can be found on T-Machine.org:
- (integer) Entity
- (enum) ComponentType
- (interface OR empty base-class) Component
- (interface OR empty base-class) System
- (class with implementation) EntityManager
This is a non-negative integer, and uniquely identifies an entity within the ES. If you serialize your ES, this SHOULD be the same after serialization. New entities have to be assigned a new, unique, integer value when they are created. When an entity is destroyed, its integer value is freed, available for re-use.
This is needed because this ES is so simplistic it has no other way of identifying which Component you're talking about when you're looking at a single Entity.
(richer EntitySystems MAY not need this type)
This exists purely to make method-signatures type-safe. We need to know that certain objects are valid instances of a "component" (so we use this superclass to indicate that), but we also need a method that's guaranteed to work on all those objects (see below).
(richer EntitySystems make more use of this, and require it to be a class, but for this simple ES, you can use an interface/header file)
This exists purely to contain a known method-signature that your game-loop can call once per game-tick.
EntitySystem Implementation Classes
Each subclass of Component
Internally, the class has the following functions:
- (ComponentType) getComponentType();
Just one method, that gives you a common interface to trigger each of the systems:
- processOneGameTick( long previousFrameTime );
- The master collections (arrays, hashmaps, whatever) that contain all the data for all the entities
- Logic for creating, modifying, fetching, and deleting entities
- Logic for fetching and modifying components-from-entities
Internally, the class has the following variables:
- LIST: all entities in existence (so it never duplicates entity-IDs!)
- MAP: from "Entity + ComponentType" to "concrete Component subclass"
Internally, the class has the following functions:
- (Component) getComponent( Entity, ComponentType );
- (List) getAllComponentsOfType( ComponentType );
- (List) getAllEntitiesPossessingComponent( ComponentType );
- (void) addComponent( Entity, Component );
- (int) createEntity;
- (void) killEntity( Entity );
- Because "System" is a reserved classname in Java, the "System" class has been renamed to "SubSystem"; maybe we need a better name for this.
Suggestions for Improvement
- Leverage Java's UUID as a drop in replacement for the standard Entity "object", which is typically just a non-negative integer. The upside is that UUID is universally unique, such that multiple computing agents could potentially share a set of entities. Secondly, UUID has some helpful serialization functions (toString / fromString). The downside is that UUID has a slightly heavier memory footprint than just a primitive data type.
Entity is implemented as a class instead of a plain uint; this is technically incorrect, although the rest of the system works as expected
NB2: Wikidot.com is broken in how it handles links - you MUST copy/paste this link, sadly:
Ruby / JRuby
The Ruby Entity Component Framework (RECF) is a complete and working entity-component system written for the elegant Ruby language.
The RECF has been documented in a series of blog posts by the author, "Entity-Component game programming using JRuby and libGDX".
- Part 1 - introduction and nomenclature http://cbpowell.wordpress.com/2012/10/30/entity-component-game-programming-using-jruby-and-libgdx-part-1/
- Part 2 - entities and the entity manager http://wp.me/pFIOD-f0
- Part 3 - components http://cbpowell.wordpress.com/2012/12/06/entity-component-game-programming-using-jruby-and-libgdx-part-3/
- Part 4 - systems http://cbpowell.wordpress.com/2012/12/07/entity-component-game-programming-using-jruby-and-libgdx-part-4/
- Part 5 - libGDX concepts http://cbpowell.wordpress.com/2012/12/11/entity-component-game-programming-using-jruby-and-libgdx-part-5/
- Part 6 - the Lunar Lander game http://cbpowell.wordpress.com/2012/12/13/entity-component-game-programming-using-jruby-and-libgdx-part-6/
- Part 7 - serialization http://cbpowell.wordpress.com/2012/12/16/entity-component-game-programming-using-jruby-and-libgdx-part-7/
- Part 8 - collision detection and more http://cbpowell.wordpress.com/2012/12/17/entity-component-game-programming-using-jruby-and-libgdx-part-8/
Source code and examples
ecs is a young but complete Entity/Component System for games in Python. While the concepts are identical, the API has been adapted slightly to be more Pythonic. Source code and documentation can be found through the home page:
It is also available for download from PyPi: