Station 6 technical side: Component based entities
2,212
1
Advertisement
Hi again!
This week I'd like to give you a look at some of the technical details of Station 6. I'll be making numerous posts on how the game works as it develops, to give you an insight into the inner workings of the game and to show you my thought process when it comes to code. I'm using C++, with OpenGL for graphics and SDL for input, audio, etc. I'm using the SuperMaximo Game Library, created by myself, to help with this and handles a lot of the rudimentary code, such as creating an OpenGL context, loading shaders, handling matrix transformations, drawing sprites and 3D models, and a whole load of other stuff.
This week I'll be showing you my component based entity system. For those who don't care about my technical ramblings and would prefer to look at Ben's drawings, scroll down to the bottom of the post.
What is a component based entity?
An entity is an object in the game world that the player interacts with. These entities are constructed of numerous parts (components) that make up the whole functioning object. Each component has a very specific function, and can be mixed and matched to form various different types of entities. If at any time we needed a new piece of functionality for an entity we have in mind, we just create a new component that will handle that functionality, and then just plug it into our entity. If we take a car as an example, the wheels, engine, chassis, etc. are the components, and they come together to create the car; a fully functioning entity. Now that we have an idea of what a component based entity is, lets take a look at some code.
The Entity class
As this is a blog about Station 6, and not just a blog about technical game development stuff, I'm going to show you the exact code that's in the game and explain it, although slightly condensed as not all of it is necessary to the current topic (i.e. we're talking about components, so there's no need to delve into the rendering side of things). So here's the entity class:
Going from top to bottom, the Entity inherits from the SuperMaximo::Object class from my library, and there's a static vector (for those who don't know what a C++ vector is, think of it as a fancy array) that contains pointers of entities, so they can all be looped through, if necessary. We then see a vector of pointers to components. Notice that there isn't some sort of 'update components' method; the components manage themselves and the entity itself doesn't interfere. We'll have a look at that in more detail later.
After the constructor and destructor there's some component methods. addComponent simply pushes a pointer onto the end of the components vector, and gives the component a pointer to the Entity so that it can perform various operations on the Entity. The removeComponent takes an enumerated type representing the type of component that needs to be removed. It searches for the component that corresponds to the enumerated type in the components vector and if it's found, deletes it and removes it from the vector. There's a small gotcha with that which I'll explain later. We then have methods that return whether an entity has a certain component, and a pointer to a component.
The Component class
In the Component class there is a pointer to the Entity that it is attached to, so that the component can manipulate the Entity. We then have an abstract method, type, which returns the enumerated type that the component corresponds to, and a virtual destructor, which is a fix for the gotcha I mentioned earlier (explained later). There is then a static class method, updateAll, which updates all of the components in turn, in a specific order. All of the component updates have their place in the cycle of the game and interactions between them are very well defined and predictable, which makes debugging a heck of a lot easier.
For example, all of the Pushable components are updated before the HorizontalVelocity components. The Pushable components check whether their Entity is being pushed by something, and then updates the Entity's HorizontalVelocity component (if any) with the velocity that the Entity now has due to the push. Then the HorizontalVelocity components are updated so that they simulate the motion and update the Entities' position in the world accordingly.
A component example
Let's have a look at the Gravity component. Entities that have this component are obviously subject to a pull down towards the floor.
You can probably guess a lot of what this component is doing! On construction the component adds itself to a static vector, and on destruction removes itself. It has a yVelocity data member that is updated when the Gravity components are all updated in the static update method, and the Components' Entities' positions are updated accordingly. The type method is an implementation of the abstract type method in the Component class. The collisionTestBelow and pushOutOfFloor methods are self explanatory.
Here's the gotcha. Why did we use a virtual destructor in the Component superclass? Consider this code that we might use for the Entity class' removeComponent method:
See a problem? Well, the problem lies in 'delete components'. components is a vector containing pointers to instances of Component. So, if we simply use the above code, only the destructor of the Component base class will be called, and not the destructor of the component that we want to delete. So, if we wanted to remove a Gravity component, it's destructor won't be called and therefore it won't be removed from the list of the Gravity components. We'll have a dangling pointer, and when the Gravity update method is called, there'll be a crash when it tries to dereference the pointer to update the (now deleted) Gravity component instance.
You could solve this problem by either using a switch statement that will compare against the component's type enum and then cast the Component pointer to a pointer of the relevant type before deleting it, or by making the destructor virtual. The Component class destructor doesn't do anything anyway, so we don't need to worry about it being called, and instead the Gravity component's destructor will be called.
A concrete example of an entity
Now for the fun bit. Let's say we want to make a crate. We want to be able to collide with it, have it subject to gravity, and be able to pick it up. Here's the resulting Crate class:
That's it! Nothing more is needed. We have a fully functioning crate that we can put into the game world and it'll work perfectly. We can jump on it, pick it up, and throw it off a cliff and watch it fall. After all the effort of implementing a component system, it pays off when you actually start making entities for the game. It makes creating new objects so much easier and if I want some new functionality for whatever reason, I just code in a new component to handle it. The only downside to this system is that for each entity that is created, a bunch of other objects (the components) are created as well. There are four objects created when instantiating a new Crate, one Entity and three Components. But for a game of this scale, it doesn't really matter!
And that's about it for my post on component based entities!
Art time
Here's a concept for a boss that I thought of today, which Ben kindly drew for me. It shoots lasers from it's pupil and retracts it legs to roll around in an attempt to squish the player.

Thanks for reading! If you have any comments, I'd really like to hear them!
EDIT 19/11/2011: Changed so that Components have a virtual destructor. I have no idea why I forgot about them
This week I'd like to give you a look at some of the technical details of Station 6. I'll be making numerous posts on how the game works as it develops, to give you an insight into the inner workings of the game and to show you my thought process when it comes to code. I'm using C++, with OpenGL for graphics and SDL for input, audio, etc. I'm using the SuperMaximo Game Library, created by myself, to help with this and handles a lot of the rudimentary code, such as creating an OpenGL context, loading shaders, handling matrix transformations, drawing sprites and 3D models, and a whole load of other stuff.
This week I'll be showing you my component based entity system. For those who don't care about my technical ramblings and would prefer to look at Ben's drawings, scroll down to the bottom of the post.
What is a component based entity?
An entity is an object in the game world that the player interacts with. These entities are constructed of numerous parts (components) that make up the whole functioning object. Each component has a very specific function, and can be mixed and matched to form various different types of entities. If at any time we needed a new piece of functionality for an entity we have in mind, we just create a new component that will handle that functionality, and then just plug it into our entity. If we take a car as an example, the wheels, engine, chassis, etc. are the components, and they come together to create the car; a fully functioning entity. Now that we have an idea of what a component based entity is, lets take a look at some code.
The Entity class
As this is a blog about Station 6, and not just a blog about technical game development stuff, I'm going to show you the exact code that's in the game and explain it, although slightly condensed as not all of it is necessary to the current topic (i.e. we're talking about components, so there's no need to delve into the rendering side of things). So here's the entity class:
class Entity : public SuperMaximo::Object {
static std::vector instances;
std::vector components;
protected:
Entity(std::string & name, int x, int y, SuperMaximo::Sprite * sprite) :
SuperMaximo::Object(name, x, y, -200.0f, sprite) {
instances.push_back(this);
}
~Entity();
void addComponent(Component * componentPtr);
void removeComponent(entityComponentTypeEnum entityComponentType);
bool hasComponent(entityComponentTypeEnum entityComponentType);
public:
Component * componentPtr(entityComponentTypeEnum entityComponentType);
};Going from top to bottom, the Entity inherits from the SuperMaximo::Object class from my library, and there's a static vector (for those who don't know what a C++ vector is, think of it as a fancy array) that contains pointers of entities, so they can all be looped through, if necessary. We then see a vector of pointers to components. Notice that there isn't some sort of 'update components' method; the components manage themselves and the entity itself doesn't interfere. We'll have a look at that in more detail later.
After the constructor and destructor there's some component methods. addComponent simply pushes a pointer onto the end of the components vector, and gives the component a pointer to the Entity so that it can perform various operations on the Entity. The removeComponent takes an enumerated type representing the type of component that needs to be removed. It searches for the component that corresponds to the enumerated type in the components vector and if it's found, deletes it and removes it from the vector. There's a small gotcha with that which I'll explain later. We then have methods that return whether an entity has a certain component, and a pointer to a component.
The Component class
class Component {
Entity * entitySelf_;
protected:
Entity * entitySelf();
virtual entityComponentTypeEnum type() = 0;
public:
virtual ~Component() {}
static void updateAll();
};In the Component class there is a pointer to the Entity that it is attached to, so that the component can manipulate the Entity. We then have an abstract method, type, which returns the enumerated type that the component corresponds to, and a virtual destructor, which is a fix for the gotcha I mentioned earlier (explained later). There is then a static class method, updateAll, which updates all of the components in turn, in a specific order. All of the component updates have their place in the cycle of the game and interactions between them are very well defined and predictable, which makes debugging a heck of a lot easier.
For example, all of the Pushable components are updated before the HorizontalVelocity components. The Pushable components check whether their Entity is being pushed by something, and then updates the Entity's HorizontalVelocity component (if any) with the velocity that the Entity now has due to the push. Then the HorizontalVelocity components are updated so that they simulate the motion and update the Entities' position in the world accordingly.
A component example
Let's have a look at the Gravity component. Entities that have this component are obviously subject to a pull down towards the floor.
class Gravity : public Component {
static std::vector instances;
float yVelocity;
entityComponentTypeEnum type() {
return GRAVITY;
}
void collisionTestBelow();
void pushOutOfFloor();
public:
Gravity();
~Gravity();
void setYVelocity(float amount);
static void update();
};You can probably guess a lot of what this component is doing! On construction the component adds itself to a static vector, and on destruction removes itself. It has a yVelocity data member that is updated when the Gravity components are all updated in the static update method, and the Components' Entities' positions are updated accordingly. The type method is an implementation of the abstract type method in the Component class. The collisionTestBelow and pushOutOfFloor methods are self explanatory.
Here's the gotcha. Why did we use a virtual destructor in the Component superclass? Consider this code that we might use for the Entity class' removeComponent method:
void Entity::removeComponent(entityComponentTypeEnum entityComponentType) {
for (unsigned i = 0; i < components.size(); ++i) {
if (components->type() == entityComponentType) {
delete components;
components.erase(components.begin()+i);
break;
}
}
}See a problem? Well, the problem lies in 'delete components'. components is a vector containing pointers to instances of Component. So, if we simply use the above code, only the destructor of the Component base class will be called, and not the destructor of the component that we want to delete. So, if we wanted to remove a Gravity component, it's destructor won't be called and therefore it won't be removed from the list of the Gravity components. We'll have a dangling pointer, and when the Gravity update method is called, there'll be a crash when it tries to dereference the pointer to update the (now deleted) Gravity component instance.
You could solve this problem by either using a switch statement that will compare against the component's type enum and then cast the Component pointer to a pointer of the relevant type before deleting it, or by making the destructor virtual. The Component class destructor doesn't do anything anyway, so we don't need to worry about it being called, and instead the Gravity component's destructor will be called.
A concrete example of an entity
Now for the fun bit. Let's say we want to make a crate. We want to be able to collide with it, have it subject to gravity, and be able to pick it up. Here's the resulting Crate class:
class Crate : public Entity {
static SuperMaximo::Sprite * sprite;
public:
Crate(int x, int y) : Entity("Crate", x, y, sprite) {
addComponent(new Collidable);
addComponent(new Gravity);
addComponent(new Pickupable);
}
};That's it! Nothing more is needed. We have a fully functioning crate that we can put into the game world and it'll work perfectly. We can jump on it, pick it up, and throw it off a cliff and watch it fall. After all the effort of implementing a component system, it pays off when you actually start making entities for the game. It makes creating new objects so much easier and if I want some new functionality for whatever reason, I just code in a new component to handle it. The only downside to this system is that for each entity that is created, a bunch of other objects (the components) are created as well. There are four objects created when instantiating a new Crate, one Entity and three Components. But for a game of this scale, it doesn't really matter!
And that's about it for my post on component based entities!
Art time
Here's a concept for a boss that I thought of today, which Ben kindly drew for me. It shoots lasers from it's pupil and retracts it legs to roll around in an attempt to squish the player.

Thanks for reading! If you have any comments, I'd really like to hear them!
EDIT 19/11/2011: Changed so that Components have a virtual destructor. I have no idea why I forgot about them
Advertisement
Advertisement
Advertisement
Discussion