Wiki

Clone wiki

Tecs / Home

Tecs

Tecs stands for "templated entity-component-system". It's a fast, light-weight, and multi-purpose ECS library.

Wiki contents

World

Basic concepts

Entities are "objects" that are little more than integers. Each entity has a unique identifier number. Without any components, entity does nothing. Basically, entities can be thought of as "bags" of components, becoming the sum of its parts when components are added. In games, entities represent characters, bullets, cars, trees, houses, particles and just about anything concrete.

Components are basic building blocks that attach themselves to entities. They (usually) consist of pure data. In games, components provide sets of data for entities, and represent such things as location, orientation, size, velocity, color, texture, speed, and many others. Components can also be empty when no data is required, but the component is used as a "hint" - kind of like attaching a tag to an object.

Systems are closed environments that operate on certain components. Each system is interested of entities that have only the components the system wants. An example of a system would be a physics sytem that modifies the location of entities based on their velocities.

Managers are a more internal part of Tecs. They handle the different elements of Tecs. An example of a manager is the entity manager which is responsible for creating and destroying entities. On the contrast, the component manager is responsible for creating and destroying components, as well as attaching them to entities. Tecs has a couple of managers built-in for convenience.

Worlds are closed environments that compose of entities, components, systems and managers. A world is not aware of other worlds.

Basic usage example

#!c++
// Create a new world. The default managers
// are automatically created and initialized.
World world;

// Add a system to the world.
world.addSystem<PositionSystem>();

// Create an entity.
Entity& entity = world.createEntity();

// Attach a position component to the entity.
entity.addComponent<PositionComponent>();

// Add the entity to the world.
world.addEntity(entity);

// Update the world. This makes the world check for
// changes in entities and components. These changes
// are reported to the managers and the systems.
// Finally, all system updates are invoked - this is where
// the systems do their work.
world.process();

Creating systems

Creating a new system is rather simple: Each system should inherit the System class. When creating a new system, an aspect should be constructed. Aspects are simple rulesets about the entities the system would be interested in. An aspect lists all the entities that have to be attached to an entity, as well as components that must not be attached.

The following code example creates an InputSystem that is only interested of entities that have both InputComponent and PositionComponent attached.

#!c++
class InputSystem : public System
{
public: 
    InputSystem()
      : System(Aspect::createAspectForAll<InputComponent, PositionComponent>())
    {
    }
};

To process the entities, each system should implement the processEntity() method of System class. This is the method that gets called once for each entity the system is interested of. Here's an example of the InputSystem's implementation, which modifies the X coordinate of the position component of the entity when the user pressed either the left or the right key:

#!c++
void InputSystem::processEntities(const std::vector<unsigned int>& entities, float delta)
{
    for(unsigned int i = 0; i < entities.size(); ++i)
    {
        PositionComponent& pc = m_world->getComponentManager().getComponent<PositionComponent>(entities[i]);

        if(Input::isKeyPressed(Key::LEFT))
        {
            pc.x -= 1.f;
        }
        if(Input::isKeyPressed(Key::RIGHT))
        {
            pc.x += 1.f;
        }
    }
}

Creating components

Components are created the same way as the system. Each component class should inherit the Component base class.

To build on the previous code examples, here's a naive implementation of the PositionComponent:

#!c++
class PositionComponent : public Component
{
public:
    PositionComponent()
      : x(0.f),
        y(0.f)
    {
    }

    float x;
    float y;
};

Updated