Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>For my soon-to-be personal game project, I use a component-based entity system.</p> <p>You can read more about it by searching "component based game development". A famous article is <a href="http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/" rel="noreferrer">Evolve Your Hierarchy</a> from the Cowboy programming blog.</p> <p>In my system, entities are just ids - unsigned long, a bit like in a relational database. All the data and the logic associated to my entities are written into Components. I have Systems that link entity ids with their respective components. Something like that:</p> <pre><code>typedef unsigned long EntityId; class Component { Component(EntityId id) : owner(id) {} EntityId owner; }; template &lt;typename C&gt; class System { std::map&lt;EntityId, C * &gt; components; }; </code></pre> <p>Then for each kind of functionality, I write a special component. All entities don't have the same components. For example you could have a static rock object that has the WorldPositionComponent and the ShapeComponent, and a moving enemy that has the same components plus the VelocityComponent. Here's an example:</p> <pre><code>class WorldPositionComponent : public Component { float x, y, z; WorldPositionComponent(EntityId id) : Component(id) {} }; class RenderComponent : public Component { WorldPositionComponent * position; 3DModel * model; RenderComponent(EntityId id, System&lt;WorldPositionComponent&gt; &amp; wpSys) : Component(id), position(wpSys.components[owner]) {} void render() { model-&gt;draw(position); } }; class Game { System&lt;WorldPositionComponent&gt; wpSys; System&lt;RenderComponent&gt; rSys; void init() { EntityId visibleObject = 1; // Watch out for memory leaks. wpSys.components[visibleObject] = new WorldPositionComponent(visibleObject); rSys.components[visibleObject] = new RenderComponent(visibleObject, wpSys); EntityId invisibleObject = 2; wpSys.components[invisibleObject] = new WorldPositionComponent(invisibleObject); // No RenderComponent for invisibleObject. } void gameLoop() { std::map&lt;EntityId, RenderComponent *&gt;::iterator it; for (it = rSys.components.iterator(); it != rSys.components.end(); ++it) { (*it).second-&gt;render(); } } }; </code></pre> <p>Here you have 2 components, WorldPosition and Render. The Game class holds the 2 systems. The Render component has an access to the position of the object. If the entity doesn't have a WorldPosition component, you can choose default values, or ignore the entity. The Game::gameLoop() method will only render visibleObject. There is no waste of processing for non-renderable components.</p> <p>You can also split my Game class into two or three, to separate display and input systems from the logic. Something like Model, View and Controller.</p> <p>I find it neat to define my game logic in term of components, and to have entities that only have the functionality that they need - no more empty render() or useless collision detection checks.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload