New Entity System for C++, like Artemis...

Started by
10 comments, last by NetGnome 11 years, 9 months ago
Hi All,

I've been back looking into Entity Component Systems, and I've create a new system that's a lot like the Artemis System, which is for Java.

I've detailed it in my journal

If you just want to see the source, you can see it here. The includes directory is what's public to users.

I'm totally open to comments and criticism. I plan on using this for my next game, but I wanted to share it to see how i can improve it.

Thanks!

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

Advertisement
I wrote that as a comment to the journal entry, but I guess it does actually make more sense to add it here:

Why does the damage System handle the collisions? I would rather let a physics system handle collisions and send a message on collision which can be hooked by other systems.


Also, what does the input component do? Of course you have an input system (or maybe better player control system which gets input from the input system). Now lets say a key is pressed which should change the velocity. You should change the velocity i guess. What i want to say is that some systems work on the data which is already there, this is also why I do not like the idea of determining the systems used based on the components.

It should be the other way round. For each entity you define which systems it uses and the systems add the components needed (if not already added by another system)

edit: Another more general thing is that I am not sure what the application is of being able to remove and add components on the fly (other than maybe for testing). The way I see it the goal of the component based design is to make the creation of new entity types easier and more flexible and not making the entities themselves 'more flexible'
Hi Inferiarium,

Thanks for the response. I'll address the questions below:


I wrote that as a comment to the journal entry, but I guess it does actually make more sense to add it here:

Why does the damage System handle the collisions? I would rather let a physics system handle collisions and send a message on collision which can be hooked by other systems.

The Damage system I showed was just an example, but it doesn't really "handle' the collisions. The collision component is added to an entity when it is in contact with another entity. This example Damage handles entities with a Health component that have collided with another entity, so it can add damage to that entity. You could create another system, say StickyBombSystem, which, when a bomb entity (which has a stickybomb component) has collided with another entity, the StickyBombSystem would start a count down on the StickyBomb and permanently attach itself to the entity in question until the timer expired, which would cause the Stickybomb to explode.


Also, what does the input component do? Of course you have an input system (or maybe better player control system which gets input from the input system). Now lets say a key is pressed which should change the velocity. You should change the velocity i guess. What i want to say is that some systems work on the data which is already there, this is also why I do not like the idea of determining the systems used based on the components.
[/quote]

In the example, the Input component just signifies which entity the user can control. In typical games, the user can certainly control the Main Player, but there are times when the user will want to control different characters. If you have a "party" game, you might have 5 different characters the user can control. Being able to move the Input component from one entity to another allows you to do this (I actually do this in the example app TestEcs.cpp in the DeathSystem). Realize, as well, the user will have to control Menus, and the Input Component could be added to those Menu Entities.


It should be the other way round. For each entity you define which systems it uses and the systems add the components needed (if not already added by another system)
[/quote]
I don't think that's the right way to go about it. It's the components that make the entity, and typically, all components will be acted on the same way by the same System. For example, the RenderingSystem operates on the GraphicalObject Component, and it does the same thing for all of them: Get the position and angle of the entity (from the PhysicalObject Component attached to the entity), get the sprite from the GraphicalObject, and draw the sprite, with the correct rotation at the correct position on the screen.


edit: Another more general thing is that I am not sure what the application is of being able to remove and add components on the fly (other than maybe for testing). The way I see it the goal of the component based design is to make the creation of new entity types easier and more flexible and not making the entities themselves 'more flexible'
[/quote]

As I've noted below, being able to move Components around entities is a major part of an Entity Component System. What happens when a Player picks up Armor? He needs to have an Armor component added. Or a Jetpack? And, I've described how I switch Input Components.

Thanks for the comments!

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

Hey there, I'm working on my own Entity Component System right now, too.

Your approach looks pretty much like my first one, which i redid because i ran into some inconveniences on the way.

One of them was that if you let your systems update one entity per time, you'll run into problems with the Collision and the Rendering system, because you'll have to make your own containers in order to check each Entity against each entity (for collisions), and you'll need to sort the entities for depth drawing (rendering).

My (not perfect, but improving) solution to the problem was to make a WorldIterator class, which's constructor takes information on what entities it's interested in, aswell as a reference to the world's entity container. Then I overloaded the operator++ to skip to the next entity that meets the requirements, and overloading the * and -> operators made accessing a lot nicer. I'm still in the development phase and haven't tested it yet, but I believe it to be a superior approach to the "one-entity-at-a-time-paradigm" that i see a lot of people use.

Another thing you should add (and that is in Artemis aswell) is the Component mapper. I saw you using a syntax like:
[source lang="cpp"]TMyComponent* myComponent = static_cast{TMyComponent*}(e->getComponent("MyComponent");
myComponent->setSomeValue(5);
myComponent = nullptr;[/source]

//For some reason it won't show these braces: <, So I'm using these instead: {

Now, while this works, it's pretty uncomfortable to type. What i suggest is to have the following syntax:
[source lang="cpp"]ComponentMapper{TMyComponent} mMyComponent;
mMyComponent.grab(e);
mMyComponent->setSomeValue(5);
mMyComponent.release(); //You don't really need this, I did it cause it's cleaner.[/source]

And if you make the grab function return a bool if it succeeded or failed to retrieve the component, you can do some pretty cool things like:
[source lang="cpp"]// In the rendering System
// blablabla drawing sprite
if (mHealth.grab(e)){
if(mHealth->drawBar){
//Draw health bar
}
}[/source]

But overall, It's an OK approach and should be sufficient for most of what you'll set your mind to.

Greets, Xelvair
Ok so you are basically passing a message through the collision component. I guess that can work.


I don't think that's the right way to go about it. It's the components that make the entity, and typically, all components will be acted on the same way by the same System. For example, the RenderingSystem operates on the GraphicalObject Component, and it does the same thing for all of them: Get the position and angle of the entity (from the PhysicalObject Component attached to the entity), get the sprite from the GraphicalObject, and draw the sprite, with the correct rotation at the correct position on the screen.


The systems define the behavior, since as you said they act in the same way for all entities which use them. The components are just the data that is needed by the system. A system does not need its own component. Also why does the rendering system have to access the physics component? what if the entity does not need to be physically simulated, do you still need the physics component for rendering? In Artemis' system the components are more lightweight. Like position componen, velocity component. In my opinion this is a better approach.

What I do not like with Artemis' approach and I guess you are doing it the same way is the following: what if two entities are represented by exactly the same components, but behave differently? You would have to make fake components (with no data) to make sure each entity is handled by the appropriate system. Wouldn't it be better to store the systems the entity uses since the set of systems actually defines the behavior.

You can still change the systems dynamically. I guess the sticky bomb you mentioned is a good example. Let's say it is thrown into the air. The movement is governed by the physics system. Then a collision is detected. Now we do not longer need the physics system but a stiction system, but we still need information like position and orientation.

For the player picking up stuff, I guess i would not implement the jetpack or whatever as a component but as an entity. I mean for the player to pick up stuff, the picking up has to be managed somehow (by a system) and that system can store the picked up items int an inventory component. And if the item entities get notified when they get picked up you can assign the owner as the player, and then the Jetpack System does what it does on the player entity.

In my system an entity looks like this

class Entity {
uint id;
map<string, void*> properties;
}

with an overloaded access operator so I can do stuff like this:

Entity ent;
ent["pos"] = new vec3(1,0,0);

etc.

In my opinion this is very convenient. Now if i create an entity of a certain type it registers with all systems it uses.
We will tend to disagree on how some things work. I agree the Jetpack would be an entity while sitting on the ground to be picked up, but when a player a picks it up, I want the player entity to add the Jetpack component. Of course, you can define it however you want in this entity system, but that's just how i would look at it.


The systems define the behavior, since as you said they act in the same way for all entities which use them. The components are just the data that is needed by the system. A system does not need its own component. Also why does the rendering system have to access the physics component? what if the entity does not need to be physically simulated, do you still need the physics component for rendering? In Artemis' system the components are more lightweight. Like position componen, velocity component. In my opinion this is a better approach.

Systems do not need components, correct. But Systems need to know what components to act on, so I link the components to the Systems in the SystemManager for efficiency.

Also, in my game, I use chipmunk-physics which handles all my physics, and it uses bodies to represent objects in space. I attach these bodies to the PhysicalObjects. In order to get the position and rotation, I check the PhysicalObject.

Of course, if I didn't use a physics library,I would have a Position and Angle component. That's not how my game works.


What I do not like with Artemis' approach and I guess you are doing it the same way is the following: what if two entities are represented by exactly the same components, but behave differently?
[/quote]
IMO, and the philosophy I follow says the Bold line above is impossible. I believe an entity is defined by it's components. If an entity is to act differently, it needs different components.

That doesn't mean my way is "Right" it's just different ways of looking at it. Your way might be better, I really don't know at this stage, but I'm glad to have a different opinion to think about these things.

Cheers!

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)


One of them was that if you let your systems update one entity per time, you'll run into problems with the Collision and the Rendering system, because you'll have to make your own containers in order to check each Entity against each entity (for collisions), and you'll need to sort the entities for depth drawing (rendering).


In my Game, I have a Collision component which gets assigned to objects that are in contact with another (assuming the physics library has them in the same group/layer), and the collision component points to the entities that are in contact with the owner entity. Obviously, I could change this and modify the PhysicalObject to have the list of object in contact, and it would have to check everytime if it's in contact or not, instead of automatically having the a system for that case.

Your point about depth drawing is valid. I'll have to figure out how to do that. Your idea is interesting, I'll consider something like that.

And the Component Mapper sounds like a good idea too, I'll look at that as well.

Thanks!

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)


IMO, and the philosophy I follow says the Bold line above is impossible. I believe an entity is defined by it's components. If an entity is to act differently, it needs different components.


It depends on the kind of components we talk about. I started the discussion because you stated that you wanted to implement a system, where the components only represent the data. And it could definitely possible to have two entities with the same data set that behave differently. For example you have two different AI systems, which need the same data but lead to different behavior etc.

It depends on the kind of components we talk about. I started the discussion because you stated that you wanted to implement a system, where the components only represent the data. And it could definitely possible to have two entities with the same data set that behave differently. For example you have two different AI systems, which need the same data but lead to different behavior etc.


OK, I see where you're coming from. It's another way of looking at it, and I hope it works for you. Good luck!

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

One of them was that if you let your systems update one entity per time, you'll run into problems with the Collision and the Rendering system, because you'll have to make your own containers in order to check each Entity against each entity (for collisions), and you'll need to sort the entities for depth drawing (rendering).[/quote]

Systems do not have to update one entity at a time. If you need to process through several at a time, you just extend the base EntitySystem class so that the process calls gives you all registered entities for that system and not just one at a time. Name it something like CascadingEntityProcessingSystem or somesuch.

so where a normal EntityProcessingSystem looks like such:


public abstract class EntityProcessingSystem : EntitySystem
{
public EntityProcessingSystem() : base() { }
public override bool shouldSystemProcess()
{
return true;
}
protected abstract void process(Entity entity);
protected sealed override void processEntities(Bag<Entity> entities)
{
for (int i = 0; i < entities.Size(); i++)
{
process(entities.Get(i));
}
}
}


the cascade variant would work like so:


public abstract class CascadingEntityProcessingSystem : EntitySystem
{
public EntityProcessingSystem() : base() { }

public override bool shouldSystemProcess()
{
return true;
}

protected abstract void process(Bag<Entity> entities);

protected sealed override void processEntities(Bag<Entity> entities)
{
process(entities);
}
}



It depends on the kind of components we talk about. I started the discussion because you stated that you wanted to implement a system, where the components only represent the data. And it could definitely possible to have two entities with the same data set that behave differently. For example you have two different AI systems, which need the same data but lead to different behavior etc.


In this case, neither entity actually owns that data. it is accessed through a separate entity that they are both referencing. There is no true "ownership" in an ECS framework like there is in an OO or Hierarchical framework, its all about references, relationships and associations. Its very loosely coupled, very similar to a simple database.

This topic is closed to new replies.

Advertisement