Home » Uncategorized » Component System

Component System

The component system in Pocket is designed so that components only consists of data. This means that no logic is put there. Logic is restricted to systems.

This design is inspired by a library called Artemis

Also this article Entity Systems are the future of MMOG development will be a good read

In Pocket we operate with 4 key concepts to get our logic to play together:

* World
* Object
* Component
* System

=== World ===
The world is a container object that contains objects, components and systems. This is so that everything in the same world can easier communicate and are more maintainable.

=== Object ===
Objects can be anything in a game, like a cube, particle system, tree, texture, mesh, or just about anything you can imagine. An object does really nothing on it’s own. You need to add properties to them via components for then to be useful. Basically objects are just what connects components.

=== Component ===
Components are what adds properties to your objects in your game. In Pocket components are just data. No logic is going on in components, although simple getter and setter logic is ok.

=== System ===
Systems are where the logic happens, here you tell a system to operate on different component types and it is it’s job to modify the component data over time.

== Example ==

The 4 component system classes are prefixed with “Game”, so they are called GameWorld, GameObject, GameComponent, and GameSystem.

In Pocket the component system is really easy to use:

GameWorld world;
GameObject* object = world.CreateObject();

Here we create an empty GameWorld and create an empty GameObject in it.
A GameWorld is always needed to create any GameObjects, so you cannot go:

GameObject* object = new GameObject();

this will result in a compile error, since the GameObject’s contructor is private and thus can only be created through the GameWorld class.

Since an empty GameObject is really not useful lets add some components to it:

object->AddComponent<Position>();
object->AddComponent<Velocity>();

This will make our GameObject contain two Components: a Position and a Velocity component.
Lets say our object is a thing that needs both a position and a velocity, such as a car or a bullet or something like that.

lets see how these two components are defined:

Component(Position)
public:
   Vector3 Position;
};

Component(Velocity)
public:
   Vector3 Velocity;
};

Here we are creating the components using a macro called “Component” which is defined something like this:

#define Component(ClassName) class ClassName : public GameComponent<ClassName> {

Now before these components actually do anything we need to add some logic to them. That is done through GameSystems:

lets define a system that updates a GameObject’s Position using it’s Velocity. This is so we can move the car or bullet with simple physics:

class PositionUpdater : public GameSystem {
public:
   void Initialize() {
      AddComponent<Position>();
      AddComponent<Velocity>();
   }
   void Update(float dt) {
      for(ObjectCollection::const_iterator iterator =     Objects().begin(); iterator!=Objects().end(); ++iterator) {
GameObject* object = *iterator;
object->GetComponent<Position>()->Position += object->GetComponent<Velocity>()->Velocity * dt;
}
}
};

Here we specify in the {{{ Initialize()}}} method that we are only interested in GameObjects that has a Position and a Velocity component, since we need both to be able to update an object’s position.
This simple system will work on all objects we add to our world. So we need to say to our GameWorld that we need this system added, we do it like this:

world.CreateSystem<PositionUpdater>();

Now the system is added and it will get it’s {{{ Update(float dt)}}} method called every time we update the world like this:

world.Update(dt);

Where dt is the delta time, ie time passed since last frame.

Now every time a GameObject has a Position and a Velocity component added it will automatically be updated through this system. Really useful.

Our complete logic program looks like this:

#include "Engine.hpp"
#include "GameWorld.hpp"
#include "Vector3.hpp"

using namespace Pocket;

// define our components (data only)
Component(Position)
public:
Vector3 Position;
};

Component(Velocity)
public:
Vector3 Velocity;
};

//define our system (logic only)
class PositionUpdater : public GameSystem {
public:
void Initialize() {
AddComponent<Position>();
AddComponent<Velocity>();
}
void Update(float dt) {
for(ObjectCollection::const_iterator iterator = Objects().begin(); iterator!=Objects().end(); ++iterator) {
GameObject* object = *iterator;
object->GetComponent<Position>()->Position += object->GetComponent<Velocity>()->Velocity * dt;
}
}
};

class Logic : public GameState {
GameWorld world;
GameObject* object;

void Initialized() {
world.CreateSystem<PositionUpdater>();

object = world.CreateObject();
object->AddComponent<Position>();
object->AddComponent<Velocity>();

object->GetComponent<Position>()->Position = Vector3(0,0,0);
object->GetComponent<Velocity>()->Velocity = Vector3(0,1,0);
}
void Update(float dt) {
world.Update(dt);
cout<<object->GetComponent<Position>()->Position<<endl;
}
};

int main() {
Engine e;
e.Start<Logic>();
}

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>