Skip to main content

Entity / Component Systems

I've been writing a new game recently -- and this time, I decided to use an entity/component system. Boy, does that approach make things easier! In other games I've written, I've struggled to fit new gameplay features into the existing code base. With a entity-component based systems, it's easy to add new features:
  • Need a way to track targetable objects in your game? Add a Targetable component that advertises the unit's position, name for display in the HUD, etc.
  • Need to add some new AI behavior to a unit? Add a component! Update all the AI components once per frame and you're on your way.
  • Does your game need networking? What should you do...? Add a component containing all the info for network serialization!
  • Need to control a unit from user input? Add a joystick component that updates the unit's position component in response to user input.

Basically, any new feature can be folded into a component. The best thing about components is that they are dynamic; you can add and remove components at runtime to change the behavior of a unit. If you think of the entity as a vector, then each component is like a separate "dimension" to your entity. Additionally, each component is a lot like a table in a relational database. The actual "entity" is just the sum of its components; that is, the sum of all its entries in each relational database table. I find this design incredibly elegant.

So, how have I implemented my entity/component system? I have a Table template class, which is basically a wrapper around std::unordered_map, indexed by the entity ID. To look up a component, you simply do a "query" (to borrow from relational database terminology) using the entity's ID and look up the component. For example:

Id id = ... 
// get the entity's ID
Ptr<Table<Position>> table = db->table(); 
// get position table
Position position = table->component(id);
// do something with the position
Say you want iterate over all the targetable enemies and select the closest one. This is really easy with entity/component systems:
Id nearestTargetableEnemy(Vector myPosition) {
    auto nearestId = Id();
    auto nearestDist = std::numeric_limits::max();
    for (auto i: *db->table()) {
        auto target = i.value;
        auto id = i.key;
        auto position = db->table(id);
        auto dist = position.origin.distance(myPosition);
        if (dist < nearestDist) {
            nearestDist = dist;
            nearestId = id;
        }
    }
    return id;
}
Simple! And, this code automatically works for any entity that has a Target and Position component! Pretty cool. The possibilities are pretty much endless. Here are some more things that are easy to implement with entity/component systems:
  • Recharge/powerup stations
  • Pathfinding
  • Serialization/save game
  • Camera tracking
  • Collision detection
  • Damage/hitpoints
  • Rendering effects
Next time you write a game, give the entity/component system approach a try. It's just too much fun not to use.

Comments

Popular posts from this blog

Lua-Style Coroutines in C++

Lua's implementation of coroutines is one of my all-time favorite features of the language. This (short) paper explains the whole reasoning behind the Lua's coroutine implementation and also a little about the history of coroutines. Sadly, coroutines are not supported out-of-the box by many modern languages, C++ included. Which brings me to the subject of this post: Lua-style coroutines in C++! For those who don't know (or were too lazy to read the paper!), Lua's coroutines support three basic operations: Create: Create a new coroutine object Resume: Run a coroutine until it yields or returns Yield: Suspend execution and return to the caller To implement these three operations, I'll use a great header file: ucontext.h. #include <vector> #include <ucontext.h> class Coroutine { public: typedef void (*Function)(void); Coroutine(Function function); void resume(); static void yield(); private: ucontext_t context_; std

Criterium: Road Screenshots

I finally got around to making the road tool for Criterium.  The tool has two parts: a Java application that lets you paint roads on the 2D heightmap texture, and a Ogre-based tool that automatically converts a 2D path into a 3D mesh.  The Ogre-tool queries the heightmap to get the height of the road, and performs smoothing so there are no discontinuous road segments.  I've posted a screenshot below.  Also, I've got my GIMP terrain shown in the screenshot.  I generated it using random noise and the GIMP lightmap filter.

Jet: Particle Systems

Here's a demo of the new particle systems I've implemented in OpenGL.  Performance is much improved over the DirectX version.  Particles are initialized in C++ rather than in Lua.  Also, I use two particle buffers and swap between them, rather than using one buffer per particle system.  Anyway, here's a video capture: