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/