Has anyone else tried component based programming? After I programmed my first video game I became sort of attached to it, though not glued to it (I find being glued to a paradigm causes more problems than it solves), I find it generally elegant, and more flexible than more traditional Object Oriented programming.
The idea generally is that you make a class have its most basic necessary parameters, and then have some other base abstract class or interface like “Component” (or a specific type of component for that class) that you can extend for various behaviors and glue together to create the full representation of your class. So rather than your construction being like
A extends B
C extends B
B extends D < etc >
You get more like
Class A
B extends Component
C extends Component
D extends Component
I find it adds more modularity, and it can shy away from some odd pitfalls and refactoring necessities in the long run, in that you only need one or two classes, but you can create completely different behavior as necessary, including making it easier to create two classes that are almost identical except for a key difference.
The main drawbacks are that they can be a pain to debug since often it’s hard to trace exactly where something went wrong and why (since the component has no strict tie to the owner’s information it can be hard to tell which instance of the base class it’s tied to, for instance). The other issue is that if not used wisely you get a lot of extra pointer dereferences and function calls.
Either way, I’ve found a lot of things simpler to program this way, I’ve completely shifted away from the way I was taught to write state machines (and hierarchical topological controllers etc) for instance. Now instead of extending a state class and rewriting the transition function and action to be taken, I can have a generic State and Transition class, and have plug-and-play “checks” and “actions” that can be added to them at construction time, it can also be used to more easily create self-modifying FSMs… but that’s not usually something one wants to be doing.
I’m using Unity3D for work, and it is mostly component-based, so I have lots of experience with it. You can have a game object, then slapped a Rotate component on it and it will start rotating.
One issue I have is are states. Say if you have a component that allows an object to read from the keyboard, and you enter a state where the keyboard is not available, all instances of that component must be notified. There are many ways around it (such as a FSM, as you have described), but it’s less straightforward. In the traditional state machine, you just need to pop off the current state or switch a state so that the event loop won’t invoke the keyboard routine of each object (top-down); in a component-based programming you have to manage that manually.
Another issue is if you need inter-component communication, or if there is any dependency between components. You can solve the problem with a context object that is shared among the components, but it reduces the re-usability of the components. Another way is to use callbacks, but it you probably need a factory to create the components and setup the callbacks.
One issue I am still thinking through is how should entities be manipulated -should it be through a facade, or is one allowed to directly attempt to retrieve a component inside the entity and manipulate its value. In the end I just have a ‘master component’ which holds interfaces to required sub-components and use that as a facade…
Hmm, you can get around the issue with accessing subcomponents with a Listener pattern, usually. On parameter <P> send out an event to some central event manager class in the update loop, which pops the update queue each cycle and notifies object registered for that type of event. In this event you can encode the necessary information to A. Execute the change and B. Determine WHICH listener is being specifically talked to (i.e. each entity has a health component it may encode the name of the entity whose health component your damage event is affecting as well as the numeric value of damage done).
The only problem is that if events rely on multiple components it may take 2-3 “event pops” to propagate (i.e. event A is dispatched which is caught by component B which re-encodes with more information to dispatch event C which is caught by component D and enacted).
As far as managing deactivated components, I’d say use a meta-component that intercepts certain events (as described above) and deactivates certain components in response – you can even make the code generic by forcing the event to encode the entity name and component name so you don’t have to define special behavior for each event.
I should mention that the event manager idea also requires that the individual components register themselves with the event manager for certain event types at construction, but that may be self explanatory for a listener pattern.