As evident in the many posts about component-based systems, interaction between components is difficult and often requires some sort of event system which complicates things even more. Also, spatial and other relationships between components are hard to express as components are stored as a list rather than a hierarchy. Above all, it is often overlooked that not all components are the same. Some are merely representative (like meshes or sound effects) whereas others control the entity or parts of it (like scripts, transforms, physics).
Apart from distinct components, I'd like to be able to add attributes to an entity which can be used and manipulated in scripts.
Here is an example of what a typical entity could like like:
Car( "car0" ) |--- Attribute<unsigned int>( "gears", 5 ) |--- Attribute<float>( "speed", 50.0, 0.0, 100.0 ) |--- AudioComponent( "sound0", sound0 ) |--- AudioComponent( "sound1", sound1 ) |--- AudioComponent( "sound2", sound2 ) |--- RenderComponent( "chassis", chassisMesh ) |--- TransformComponent( "transform0", vec3(5, 0, 10) ) |--- RenderComponent( "tire0", tireMesh ) |--- TransformComponent( "transform1", vec3(-5, 0, 10) ) |--- RenderComponent( "tire1", tireMesh ) |--- TransformComponent( "transform2", vec3(5, 0, -10) ) |--- RenderComponent( "tire2", tireMesh ) |--- TransformComponent( "transform3", vec3(-5, 0, -10) ) |--- RenderComponent( "tire3", tireMesh )
So what I want is more like a mix between the two approaches.
I started implementing this design and here is what I have so far:
The component base class contains the virtual member function update( TransformComponent &, bool active ) which has to be defined by all inheriting classes. The transform component passed to this function is the parent transform itself. This also ensures that non-transform components (i.e. representatives) add child components.
A component can use its update routine to do whatever it has to do to ensure that it can represent its parent entity adequately or control/modify and update its children, respectively. a TransformComponent will multiply its transformation matrix with the provided parent transform, a RenderComponent will set its transformation matrix to its parent transform's and update its materials, etc.
The class Entity derives from TrasnformComponent and adds a map to hold attributes.
While controllers like TransformComponent can contain other components, representatives like RenderComponent can not. A component never knows about its parent so interaction between components is limited to the information passed down through the update routine.
The rendering of representative components is handled exclusively by the world and not the entity. The world renders all meshes, light sources, sound effects etc. relying solely on the information in the components themselves. It does not care which entity a component belongs to.
So far a TransformComponent merely provides transformation like translate, rotate and scale but it could be extended to handle perspective/orthographic transformations, physics interaction etc.
So what do you say? Good start or dead end?
Thank you!
[Edited by - Vexator on July 12, 2010 4:17:10 PM]