C++: Designing a component-based entity system - advanced problems - c++

In my game engine, that is written in C++, I've moved away from the classical hierarchical entity system and build up a component-based one. It works roughly in this way:
An entity is merely a container for components. Some example components are: Point, Sprite, Physics, Emitter.
Each entity can hold at most one component of each type. Some component depend on another, like Physics and Sprite depend on Point, because they need a position and angle delivered by it.
So everything works fine with the component system, but now I have trouble implementing more specialized entities, like:
A camera, which needs additional functions to handle movement and zoom
A player, which needs support to receive input from the user and move
Now, I could easily solve this with inheritance. Just derive the camera from the entity and add the additional zoom functions and members. But this simply feels wrong.
My question:
How can I solve the problem of specialized entities with a component system in C++?

You seem to be doubting the IS-A relationship here. So why not make it a HAS-A relationship? Instead of being an entity, the camera and the player could be objects that have an entity (or a reference to the entity), but exist outside of your component-system. That way, you can easily keep the uniformity and orthogonality of your component system.
This also fits nicely with the meaning of those two examples (camera/player) as 'glue' objects. The player glues the entity system to the input system and acts as a controller. The camera glues the entity system to the renderer and acts as a kind of observer.

What about just creating components that enable that behavior? For example, an InputComponent could handle input from the player. Then your design remains the same, and a player is just an entity which allows input from a keyboard, rather than input from an AI controller.

Components based system usually have a general method allowing to send "messages" to entities, like a function send(string message_type, void* data). The entity then pass it to all its components and only some of them will react to it. For example, your component Point could react to send("move", &direction). Or you could introduce a moveable component to have more control. Same thing for your camera, add a component view and make it handle "zoom" message.
This modular design already allow to define different types of cameras (like a fixed one not having the moveable component), reuse some component for other stuff (another type of entity may use a "view") and you can also gain flexibility by having various components handling each message differently.
Of course, some optimization tricks could be needed, especially for frequently used messages.

How about giving each entity some restrictions to what kind of components it may hold (and maybe also what it should hold), and loosening those restrictictions when you derive from that entity. For example by adding a virtual function that verifies whether a certain component can be added to the entity.

A common solution is to use the visitor pattern. Basically, you'll have your entity being "visited" by a Visitor class. Inside your entity, you'd have :
void onVisitTime(Visitor* v)
{
// for each myComponent...
v->visit(myComponent);
// end for each
}
And then, you'd have, in the Visitor class :
void visit(PointComponent* p);
void visit(CameraComponent* c);
Be aware that it's a bit of violation of OOP (data-manipulation being handled outside the object, since the visitor will handle it). And visitors tend to become over-complicated, so it's a not-so-great solution.

Related

Providing interface for objects within objects

I am creating a model as in MVC which is made of other objects. My single main model object contains the constituents object. My question is should I be asking the main model object for all the operations that will actually be carried out by constituents object or should I ask for the constituents objects and run its operations? I can see in the first approach, the main model will have to account for all the operations of its constituents modules and will result in adding many functions which will simply delegate to the constituent objects.
Let me explain with an example which is very close to what I am doing. This code below is on fly so please ignore c++ syntax mistakes if any.
class Arm
{
public:
Move(int x, int y);
}
class Robot
{
public:
Arm leftArm;
Arm rightArm;
// should this function be there?
MoveLeftArm(int x, int y)
{
leftArm.Move(x,y);
}
// and likewise this?
MoveRightArm(int x, int y)
{
rightArm.Move(x,y);
}
}
// in the view when I want to move robot arms, should I do this
robot->MoveLeftArm(x,y);
//or this
robot.leftArm.Move(x,y);
A dump question but should it depend on how many operations the constituents objects actually support? Also since we are it, is this also an example of facade design pattern?
My concerns:
First approach can grow the main object to very large object. Do we really want such a large object with so many methods?
This sound like pyramid pyramid model where functions cascading down the chain. Is this discouraged? I seem to recall that way but I maybe wrong.
The 2nd approach let the external client module access its sub-components directly, not sure if this is entirely bad?
Please consider the constituents objects are many more than just two robot arms above and it has more methods.
I think it's usually better to encapsulate data and behavior and let each class maintain it so you don't create strong relationships between them.
So the best would be that the View calls Robot.MoveLeftArm and RobotMoveRightArm and the Robot is the one that would send the message down to the Arms which would execute the actual movement.
This way the call and implementation of the arm moving is encapsulated in the Arm and it could change without affecting the View.
There are also options to have interfaces define the behavior and have the classes actually implement that behavior, thus creating a contract between them.

ECS-can an entity have more than one component of given type

I've been recently assigned to code a Entity-component-system based framework. As I'm not experienced in that matter, I have a simple question:
Can I assume, that an entity can have maximum of one component of each type? I mean like:
int COMPONENT_COUNT; //number of different components available
class Entity
{
COMPONENT* component_list[COMPONENT_COUNT];
}
then adding a component would be like
component_list[component.id]=&component; //can't add more components of this type
Is that a correct assumption? I can't think of any situation when an entity would need two or more components of the same type.
I'm going to bring up my holy bible and say, yes, an entity should only have one component type! It is blasphemous to do otherwise!
Thou shalt not create entities with more than one component of the same type or else thou shalt face eternal damnation.
I'm normally pretty loose about this stuff but when you allow your system to have more than one component of a given type attached to an entity, that complexity spreads to every single corner of your systems.
Now every system has to work against the assumption that there could be more one component of the same type attached to an entity for any component type, at which point you're constantly faced with design questions like what a physics system should do when an entity has 14 position components attached. And what happens when a rendering system finds an entity with 15 motion components but only 4 sprites, expecting a matching motion component for each sprite component? Which motion components are used for which sprite?
Life becomes a whole lot simpler when you just say, "one component instance of one component type per entity."
If you want to aggregate, then just make your component a collection of something. Instead of Bone component, make it a Skeleton component which stores a list of bones. Instead of a Pixel component, make it an Image component which stores a collection of pixels. That's all fine, and doesn't require you to violate and defile the sacred commandment above.
Well, there isn't a holy bible of entity component systems. But many implementations I'm aware of don't make any provision for this, they allow entities to have or not have some kind of component but don't support multiplicity. Likewise, from a design perspective it seems like a rather bad idea (lots of complexity for naught). You could make it work, but neither you nor I can come up with a use case. KISS and YAGNI apply, this is a reasonable assumption. And if you do later need to add a component twice or thrice, it's easy to emulate by having two or three different kinds of components. Only with variable arity you need to change the innards of the system, but that seems even more outlandish.
Urho3D allows multiple same type components - and their components derive more than once sometimes - ie StaticModel from Drawable from Component
When you make a new component type - you can add as many of them as you want to a "Node" (same thing as Entity). This was pretty much a nuisance when using Urho - always thinking about "Wait, how many of these things does this Node have?".. For what?
Like others have mentioned, seems hard to justify all those extra for/while loops that go for 1 iteration always.. With Urho I got around it by just making it my own rule to never add more than one component of a type to the node... just too confusing otherwise

Entity Systems in C++

In game development there is a notion of Entity System which is aiming to simplify the game loop by gaining a flexible architecture. For details see the links below:
http://www.richardlord.net/blog/what-is-an-entity-framework
http://shaun.boyblack.co.za/blog/2012/08/04/games-and-entity-systems/
Now I wonder how it is possible to realize automatic Node creation when a Component is added to an Entity in C++? Please tell me the principle of identifying what Nodes can be spawned from a specific Entity, i.e. you should have list of Component and classes that aggregate components. And you should understand what classes can be created with the list of data.
For example I have Components:
class PositionComponent
{
int m_x;
int m_y;
int m_rotation;
};
class VelocityComponent
{
int m_vX;
int m_vY;
int m_vAngular;
};
class RenderableComponent
{
Sprite m_view;
};
And nodes:
class MoveNode
{
PositionComponent m_position;
VelocityComponent m_velocity;
};
class RenderNode
{
RenderableComponent m_rend;
PositionComponent m_position;
};
Now if I create an Entity like this:
Entity * e = new Entity;
e.add(new PositionComponent);
e.add(new VelocityComponent);
Then I want to have a code that creates a MoveNode automatically, and if I add also this:
e.add(new RenderableComponent);
Then I want to know that also RenderNode is created. Consequently, when I delete it:
e.remove(new RenderableComponent);
the RenderNode should be deleted. And this process, of course, should not be bind to the specific Nodes and Components I have defined.
How is it possible to realize this in C++?
I am slightly confused, since it appears to mix concepts. I will try to shed some light on the two concepts.
Entity & Component
The entity component system is quite common in game engines, for example Unity implements it quite visibly. It tries to address the issue that simple inheritance does not work well in many cases, such as mixing rendering and collision information; is a Collidable also a Renderable? And since multiple inheritance is a scary thing for many and not supported in many languages, the only way out of this is the Entity/Component design. (Actually not the only solution, but that is a different issue.)
The design for entity component is quite simple, you have a class Entity that takes multiple objects of type Component. There will be multiple components that "do" something, like a MeshRenderer, TriMeshCollision or RigidBodyMotion. As stated in the articles, the actual logic does not need to be implemented in the components themselves. The component just "flags" the entity for specific logic. It makes sense to delegate the actual work to be done in a tight loop in a system, maybe even in a different thread, but more to that later.
Then the actual entity is composed. There are two basic ways to do this, in code or in data.
For example you compose objects in code that represent one "real world" object; the object of type Goblin exists and it is derived from the class Entity. The constructor from Goblin will then create all components and register them on itself. Inheritance is now only done for high level logic, for example the FastGoblin is derived from Goblin and only has a different material and speed setting.
The second way to create objects is through data, that is you have some form of object description language. (Take something in XML or JSON) This will then create in a factory method something based on a given template in that is defined in this object description language.
Node Based Work Scheduling
It may make sense to have objects that are fully defined, but the logic not being executed. Think about objects on the server or in the editor. On the server you do not want the rendering code to be in the way. So the basic approach is to create components that contain no data. The problem to solve is, how do you efficiently get things done without iterating through the entire scene each frame and typecasting the objects around?
What your second link describes is basically a botched version of Designing the Framework of a Parallel Game Engine
There needs to be a way to schedule the work in an efficient way. The proposed solution is to have "nodes" that each do a specific task. The nodes are then scheduled, by submitting them to either a work scheduler or a specific system.
Take for example rendering. You have an entity and it has a MeshRenderer component. This component will create a RenderNode and submit it to the RenderSystem. Then when it is time to render the frame the RenderSystem will simply iterate over each RenderNode and call its display method. In the display method the actual rendering is done.
Alternatively the system, engine or entity can create nodes based on specific component configurations. Take for example physics. The Entity has the TriMeshCollision and RigidBodyMovement components. The PhysicsSystem seeing this configuration creates a RigidBodyNode that takes the two components as inputs and thus implements rigid body motion. Should the entity only have a TriMeshCollision component the PhysicsSystem would then create a StaticColliderNode to implement the behavior.
But like the construction mechanic for components from data, the nodes can also be created and attached to the entity through a factory function. This can be part of either the object definition or a rule based system.
Mapping this design into C++ should be straight forward. The rather difficult bit is to figure out a way how the different bits get connected; for example, how the MeshRenderer gets access to the RenderSystem so it can submit its RenderNode. But this can be solved with a singleton (shudder) or by passing a Game/Engine object around at the construction of the Entity or Component.
Is this good design?
But the issue I want to address here is: Is this good design?
I have troubles with your second link (Games And Entity Systems), since I think the design will fall flat on its nose quite quickly. This is true for other aspects like physics, but this will become quite inefficient when considering modern 3D rendering.
When you need to organize the scene spatially to efficiently cull hidden objects, organize the objects into batches for lighting and reduce resource switching then the entire "list of nodes" concepts is moot since you need a separate organisational structure anyway.
At this point you can let the components "talk" directly to the systems and each system has its own unique specific API that is fit for its specific purpose. The requirements of rendering, sound and input are each significantly different and tying to cram them into on API is futile.
See Also
Entity/Component based engine rendering separation from logic

How to avoid having my GameManager class be friend with most stuff?

I'm writing a game for a video game course (which unfortunately taught nothing), and I'm having trouble designing the interactions between the game entities and the class that actually runs the game.
My problem reduces pretty much to this: assuming an entity has a position, it shouldn't be able to modify it directly (instead having to wait for the game manager to run a game step), but it should be able to access it, to run AI checks and so on.
My solution would be to create a Position class that is friend with GameManager, and to create an entity class like this
class Entity {
public:
Position & getPosition() { return pos_; }
private:
Position pos_;
};
So the manager would be able to modify the entities' positions but other classes would only be able to observe. However this reasoning would hold for lots and lots of other properties, and since the entity class is actually derived into a series of subclasses, which have more and more properties, I would have to put the friend attribute almost everywhere.
What would be a better approach to solve this problem?
The idea of identifying certain classes as friend and certain others as non-friend is not a good idea, for many reasons. What this means is that,
How this class is being used is also a concern of this class.
But this is not its concern at all. This class, whatever class is under consideration, should be designed to do its own responsibility.
Now, with your case, first of all you should decide on where the action/behaviour of changing position belongs to; does it belong to Entity, Entity Manager, or something else. For example, which of these two cases make more sense:
Entity changes its position from x1 to x2.
Entity Manager changes to position of Entity from x1 to x2.
Suppose you decided that this behaviour really belongs to Entity, rather than Entity manager (case 1). In that case, as is pointed out in the comments by #bengoesboom, it should provide a setter that users of the class can use to change its position.
Now, if you think that this class might be used in ways that is not desired, then you should enforce constraints and business rules within this class. For example (just a simple example), if you want to allow only certain range of values in an operation. You check the input, if it is not in the range, then you throw an exception.
Once, you have properly taken care of rules and constraints, then you don't care about who will use this class.

managing relationships between aggregated / composited members of a class

I am creating entities for a simulation using aggregation and composition.
In the following C++ example:
class CCar
{
CCar( CDriver* pDriver )
{ m_pDriver = pDriver; }
CDriver* m_pDriver;
CEngine m_Engine;
CDriverControls m_Controls;
};
in the above example, a car consists of an engine and a set of driving controls (by composition). A car must also have a driver (by aggregation).
But this only explains the hierarchial relationships - a driver belongs to a car, and an engine and controls also belong to the car. But these members all relate to each other also - a driver must perform an action on the controls, the controls must perform actions on the engine. These relationships also work in multiple directions - the engine can stall and cause the controls to seize up, or the controls could spin wildly and hurt the driver? And what if the driver doesnt like the sound of the engine and leaves the car? How do these relationships work?
I am compositing many different entities from many different objects which often interact with other objects, and am interested in how to manage these relationships in a designed way.
thankyou!
edit:
as responses suggest, one way to manage this is through pointing the car to the driver, and giving the driver a pointer to the car, etc. This makes sense and solves this specific example. However, in a design sense, this increases responsibility of the driver, where this object is tasked with keeping track of which car it belongs to, but surely this is the duty of the container to keep track of which objects belong together? Likewise, tasking CCar with managing these relationships will turn CCar into a blob. Is there a designed solution to dealing with these kinds of relationships?
You build those into the methods of each class. What you're describing is the behavior of each class. Your requirements suggest that the relationships are bi-directional as well. Your Controls class will have methods that take an Engine parameter and call its methods. The Engine will have limits on its RPM, HP, torque, etc., manipulated by the Control, that will have limits built into them (e.g., "If your RPM drops too low, stall out").
It's more than just composition. Your build behavior and rules into the methods. The methods might take parameters that express what you need.
The question should be "does my application need this relationship?" For example, if you are modelling steering a car for a simple driving game, you probably don't need to worry about the motor for the sunroof at all. The steering wheel may need to know it is connected to the road wheels, but there is no need for the reverse relationship.
Bottom line - in the real world everything is connected, but in the computer models we make of that world to solve particular problems, they are not.
It may be useful to emphasize interfaces rather than composition, aggregation, or inheritance. For example, your driver class could be written such that it can use the "steering wheel" interface. Naturally, your implementation of the steering wheel provides an implementation of the "steering wheel" interface. Likewise, the car supplies a "car interface" which the steering wheel implementation might be written to take advantage of.
Your implementations may use composition, aggregation, and inheritance. But in this approach it is really the interfaces that drive the design. Whether you use composition, aggregation, or inheritance in a given instance becomes merely an implementation detail.
You probably want a two way association between the car and the driver:
CCar( CDriver* pDriver ) :
m_pDriver(pDriver)
{
m_pDriver->SetCar(this);
}
Then the driver can access the members of Car through the Car's public interface.
To solve this question, it is first important to establish what each component does.
CCar - a container holding components and aggregates.
CDriver - an object representing a driver
CEngine - an object representing an engine
etc.
For a small and simple program, a simplified design should be used where the driver is given a pointer to the car
CCar( CDriver* pDriver )
{
m_pDriver = pDriver;
m_pDriver->SetCar(this);
}
For a larger application this is unacceptable where a CCar may require new components adding, etc. and it would be poor design practice to give a driver access to the whole CCar - here the driver would be able to change not only the steering wheel, but the cars colour, etc. which is clearly not the intention.
What about just giving the driver access to the bits it needs?
m_pDriver->SetSteeringWheel( m_SteeringWheel );
m_pDriver->SetHandBrake( m_HandBrake );
this solves that problem, now the driver has no access to the cars other attributes ( such as colour ). However, it gives the CDriver class more responsibilities. Where CDriver may be able to use alot of controls, the class can get very large, and holds the responsibility for operating these steering wheel and handbrake objects. What if the driver gets in a different type of car that doesnt have the same controls as the others? Now the driver has to figure out how to operate the vehicle with the controls it has? Extra logic. Extra blob.
The solution to all of this is to use a mediator class (or variant), to control how the driver interacts with the vehicle. This could be done in one of two ways, the driver can have a mediator to the car, which controls how the driver interacts with the car. Or the driver can have a mediator for each component or aggregate of the car that it must deal with. This is probably a better solution as the mediators can be reused for different types of car. The mediators must be able to handle the bi-directional relationships between components.
The CCar, being the container, is responsible for maintaining the mediators and hence the relationships between its components. Just the way it should be.
The mediator is responsible for handling this relationship between the components.
class CMediatorDriverToSteeringWheel
{
CMediatorDriverToSteeringWheel( CDriver* pDriver, CSteeringWheel* pSteeringWheel )
{
m_pDriver = pDriver;
m_pSteeringWheel = pSteeringWheel;
m_pDriver->AddMediator(this);
m_pSteeringWheel->AddMediator(this);
}
};
...
CCar::CCar( CDriver* pDriver )
{
m_pDriver = pDriver;
new CMediatorDriverToSteeringWheel( m_pDriver, &m_SteeringWheel );
new CMediatorDriverToHandbrake( m_pDriver, &m_HandBrake );
}