After a discussion with my editor I agreed to try to cross-reference my posts if a subject carries over from one entry to another. So here goes nothing.
Vehicle and Obstacle components merged into one Body component
Previous discussion about Obstacle in this entry.
Last weekend I began to tear up the Vehicle and Obstacle components and to try to combine them into one Body component. You may remember than Vehicle controls autonomous movement of entities (mostly through steering behaviors) and Obstacle does simple physics.
My reason to merge them is that they were never independent anyway. Physical response affects motion too so they both relied on a single integrator. Placing the integrator in either one would cause a coupling while having two independent integrators would be very, very bad.
The key point of the Body component is that it is based on the Box2D physics library instead of my own simple one. Steering behaviors are now an optional part of the Body component and they simply exert extra forces sand torques on the body when active.
I've never worked with Box2D before but it was simple enough to get up and running. The hard part was and, still is, to adapt the system and design the new component, atoning for past mistakes.
For example the bodies need a way to track other bodies both passively (for cohesion/separation behavior) and actively (for targeting/seeking). The passive is done by simply giving the steering behavior update a collection of all bodies.
Previously the active tracking was done by storing the ID of the tracked entity and looking up its vehicle component each frame. The continual lookup was slow but I didn't want to hand out pointers between components because of the security risk. Another flaw was that the tracked entity was required to have a vehicle component even if it didn't do any auto-movement (like the mouse pointer).
The new system introduces a Target component that is lightweight and only exists to flag an entity as targetable. When a body component picks a target it gets coupled with this target component and can request its location each frame. The coupling is done using a set of smart pointers, see below, so it's safe if the target is destroyed.
So far so good. Right now I'm trying to figure out how to attach entities to each other in the new design. My previous concept of hierarchical structures of entities doesn't work here. I'm figuring if using joints between bodies could work but that would require a Body component on both attached entities. Hmm.
Extensive use of smart pointers
Previous discussion about smart pointers in this entry.
I've also gone further in my studies of smart pointers and how to apply them. I recently talked about using boost::ptr_map and other collections. Now with the added requirement that my components should be safely distributable within the system such a sealed collection was not enough.
Instead, by using a collection (map) of boost::shared_ptr, components flying around are reference counted to prevent premature deletion. The system distributes boost::weak_ptr objects instead of actual boost::shared_ptr objects so that if a component is distributed and then deleted the links to it will be safely inoperable.
You can read more about boost::shared_ptr and boost::weak_ptr in the documentation. Briefly, boost::weak_ptr is a sealed pointer that needs to be promoted to a boost::shared_ptr through a lock() call before it can be used. This way it doesn't pin down the resource until it really needs to.
Yeah, and please ignore this old lashing out on shared pointers from a year back! I overreacted to say the least. Of course you should use them only where they fit in.