2-2
[EDIT]
Also this.

Maybe a concept every day? Maybe.
[/EDIT]
Last night I wrote (most) of that article series. I made it all the way into part 3, and I wrote the code for the whole thing. (Someone) pointed out that it isn't as much an article, as, 'here is my code, look at it.' (Someone) is right, but I don't care. Here is the first part of that article. I'm looking for feedback. Comments are welcomed.
This is an article about an entity component system. It's specifically for XNA, but this first part is applicable to any language. After this, I'll get into things that are very XNA-specific, and use C#'s reflection, and winforms, and XNA's serialization and content pipeline - and those things won't translate too well to a different environment. But if you are using XNA, well, this is going to be awesome!
This article is a rough draft. There will be mistakes. The code won't be perfect, either. I've pulled this code from a real project, but that project is very complex. I had to simplify this a lot - and a lot of details were removed. Some of those forgotten details could have been important. This is meant to give you the ideas, not the code, so don't copy it and just expect it to work!
In part 1, I'll talk about what a component actually is, and how they are put together to make an entity. I'll go over how they communicate with each other and the various sub systems in the game.
In part 2, I'll use XNA's content pipeline to turn an XML document into a set of entity components. This is as simple as adding a few references to the game project, and writing the XML. I'll also go through the use of reflection to clone entity components, and why they have to be cloned this way.
In part 3, I'll examine a simple scripting system. The scripts themselves are in C#, and are actually entity components. This should demonstrate just how powerful an entity component system can be. It will also cover implementing closures in C#.
In part 4, I'll create an editor for assembling entity templates. This will remove the need to write the XML directly, and will also demonstrate XNA's intermediate serializer, the property grid control, and another use of reflection.
These articles are not a step by step tutorial. There's sample projects at the end, but they are full of stub functions, and they actually do almost nothing at all.
Before I dive in, a few words on the project structure. The solution contains three projects - Engine, Game, and Editor. Most of this stuff goes in the Engine project. I'll explain why in part two, but for now, all the classes I list here go into the Engine project.
Part 1
So what is an entity component? It's a component of an entity. Okay, so that definition is entirely useless. A component represents some unit of logic. Entities bind these components into a single object. Wait, so what is a component then? That's hard to say. A component is useless without the entity. The idea can only be defined as that part of a whole. By itself, it is nothing. Thankfully, the ideas don't need to be clear for the code to be.
I can answer the question 'What is a component' in code.
public class EntityComponent
{
//V- What the hell is that? It's some cruft for XNA's Intermediate Serializer. See part 2.
[Microsoft.Xna.Framework.Content.ContentSerializerIgnore]
public Entity Me { get; internal set; }
public virtual void Initialize(ContentManager Content) { }
public virtual void Destroy() { }
public virtual void Update(float ElapsedSeconds) { }
}
That's rather bare. The component keeps track of what entity it belongs to. The property is public, but only types from the same assembly can modify it.
Components are grouped using an EntityTemplate class.
public class EntityTemplate
{
public List<EntityComponent> Components;
public EntityTemplate()
{
Components = new List<EntityComponent>();
}
}
I use this class so that in Part 2, I can load these, instead of trying to load complete entities which have members that XNA can't serialize. This also allows multiple entities to share a template. Okay - they can't right now. Each entity needs it's own instance of the components. In part 2, I'll go over how I clone an EntityTemplate so that I can create many entities from a single template.
For now, we'll have to create entity templates the hard way.
EntityTemplate Template = new EntityTemplate(); Template.Components.Add(new ExampleComponent());
The entity class needs to provide a way to get a component. Other than that, it does nothing more than pass through to it's components.
public class Entity
{
public Simulation Sim; //This is the 'world' the entity exists in.
public EntityTemplate Template;
//I'll use these delegates in Part 3.
public Action<Entity> OnContact;
public Action OnSpawned;
public bool Alive { get; private set; }
public T GetComponent<T>() where T : class
{
foreach (EntityComponent Component in Template.Components)
if (Component is T) return Component as T;
return null;
}
public void Initialize(Microsoft.Xna.Framework.Content.ContentManager Content)
{
foreach (EntityComponent Component in Template.Components)
{
Component.Me = this;
Component.Initialize(Content);
}
Alive = true;
}
public void Destroy()
{
foreach (EntityComponent Component in Template.Components)
Component.Destroy();
Alive = false;
}
public void Update(float ElapsedSeconds)
{
foreach (EntityComponent Component in Template.Components)
Component.Update(ElapsedSeconds);
}
}
When I create an entity, I have to assign a template to it's Template member, and then I call Initialize.
I'll show you an example of a Component.
public class EntityDrawComponent : EntityComponent
{
public override void Initialize(ContentManager Content)
{
//Use Me.Sim to get the Rendering subsystem, and add something to it, like a scene node, or whatever you want.
}
public override void Destroy()
{
//Remove what we added in Initialize from the Rendering subsystem.
}
}