Required knowledge would be intermediate programming, different styles of programming paradigms, and OOP. The requirement for OOP is to understand fully the difference between inheritance and composition. If those terms are unfamilliar please look them up before continuing.
Component Based Entity System
Now, we must discuss what exactly a CBES is, in order to understand how the MVC paradigm works.
Component
Components are the most basic elements that our entities are comprised of. Components can be very granular or very fine depending on taste or desire. For example, a physics component could represent an object in the world as a rigid body, a rag doll, a ray, etc or each of those could be its own component.
By its very definition,
components are "a constituent part [or] ingredient." This means that to make up an entity we must combine or compose different components together.
So to create a car we would combine a physics component (for movement and collision), a model component or maybe a sprite component (for rendering), a sound component or 2 (for horn, brake squeal, and engine noise), and a control component (for user input). Once all of these are combined we have created a car. This could have been done using traditional OOP inheritance (PhysicsObject -> 3DPhysicsObject -> Car <- SoundEffect), but now if a different type of car, such as a race car, with a different type of physics or a second model for the driver using the traditional inheritance way becomes more cumbersome as we either need to add another layer of inheritance or create a new class just for the 3DPhysicsObject with two models. However using components we just remove the old model component and add in our 2-model component, or if the components are designed right we can just add a second model component.
Components don't do anything though. They are just a way to store or model data for use by the system. That isn't to say components can't have functions or methods, but these shouldn't perform any logic with regard to data, and merely act as helpers and convenience for the programmer (such as
AddPoint() for a 3d component or
GetSongLength() for an audio component.)
Entities
Entities represent anything in the game's program. From actors, to sound effects, to UI widgets. Each entity has properties and components. Entities are read-only (in a vague sense) objects in the program that tie together the components and respective properties for that entity. Entities are just containers or glue and shouldn't have any functionality at all except for perhaps parent-child-sibling traversal.
Systems
Systems are the meat of the design. Systems operate on or control the data stored in components. Systems must provide a means for the programmer to manipulate the data in the components they control, and a component should only be allowed to be controlled by a single system. For example, only the Physics system can move a physics component and the Script System should tell the Physics system to apply the force instead of moving the physics component itself.
Model, View, Control
Next up, we will discuss how the MVC paradigm works great with regards to CBES.
Models
This section will be fairly self-explanitory as we just covered it in 2 previous sections (Components and Entities). Components model the data in a specific way that allows systems to control it and views to present it.
Modeling is "a system of postulates, data, and inferences presented as a mathematical description of an entity or state of affairs; also : a computer simulation based on such a system." That is to model data is to store it in a specific way.
Entities aren't technically part of the data model as they are just an abstract concept that is used as a glue or container to hold the components and properties associated with the entity.
Controls
Controls are the systems that control or manipulate the data stored by the components. Systems can also be views, so care must be taken to ensure that a system is well-defined in its actions and not attempt to maniupulate data while trying to present a view of it.
Systems could include physics simulations, user input, network input, and script input. The pattern should be clear in that controls act upon input (direct in the case of input or indirect in the case of simulations.)
Views
Views are how the data in the components are rendered, presented, or transmitted to the user or clients (networked or otherwise). Views might be a rendering engine, database query, audio playback, or even a network transmission.
Views must take care when reading components so they don't read it as a control is operating on that set of components. Views typically only present data from a specific set of components, but when provided with how to understand the data from another component, a system could present it.
The Flow
Inside the game program execution flow should follow this simple pattern:
- Load and model the data
- Loop
- Gather inputs
- Call control systems
- Call view systems
This will ensure that the view is presented the most updated data. This will also ensure that views don't try to present components that are being manipulated by controls causing concurrency issues or other similar problems (depending on the programming language or system.)
Article Update Log
2 May 2013: Initial release
There is one thing I caught. Something like physics, scripts, etc... should not be handled by a system itself. This is more low-levelish compared to what an Entity/Component-system represents. The way I prefer it is to have a "synchronisation" system - my physics would be entirely encapsulated a series of classes including world representation, solver etc... . Then I would store a reference to a physics body from this system in a component. The physics system would then hold the phyiscs objects, to process input (like you described) and sync the states of the physics body with the entities various components. My point is - implementing something like a complex physics simulation (sure, it depends) in a system is overkill, encapsulation still needs to be applied properly.
Therefore, I also wouldn't say a component should only be controlled by a single system. Of course it depends of the implementation, but I like to implement more fine-grained components, and also prefer to, instead of tell the system to make a change at a component, change some settings for the component itself, which will cause the system to update the components internal on the next update step. For example, for the "model" component I would store mesh name and material id, and a model object. The model system would take care of assigning the correct mesh and material regarding those parameters, but if I wanted to change them, I would directly change them at the component, instead of sending a message to the system or something. That way, things are even more loosely coupled, at least functionality-wise.
But of course, these things are highly subjective, and I'd really say you should do how it works for you. In this regards, thats a good article to get a start with the whole topic.