How to implement an Effector

In this HowTo we will focus on creating an effector. An Effector allows an agent to somehow modify/interact with the virtual world. Implementing an Effector is similar to implementing a Perceptor. All effectors derive from a common base class, kerosin::Effector, and must implement the Perform() function. It's signature looks like this:

virtual bool Perform(boost::shared_ptr<BaseNode> &base, float deltaTime);

The first parameter of this call is the node, which the effector should act upon and the second parameter is the amount of time, which is to be simulated (in miliseconds). The function returns true, if the operation was successful and false if not. That's all there really is to it. A small question yet remains: How can one pass parameters to an Effector? This is usually done by other external functions. Let's look at the ForceEffector (lib/kerosin/agentaspect/forceeffector.h/cpp). It applies an accumulated force vector to a Body object in its Perform() function. The amount of force to apply is accumulated via the AddForce()-function. This modifies the internal state of the ForceEffector instance. Its Perform() function looks like this:

bool ForceEffector::Perform(boost::shared_ptr<BaseNode> &base, float deltaTime)
{
  if (!base) return false;

  // base should be a transform, or some other node, which has a Body-child
  shared_ptr<Body> body = shared_static_cast<Body>(base->GetChildOfClass("Body"));

  if (!body) return false;

  if (mForce.Length() > mMaxForce) mForce = mMaxForce/mForce.Length()*mForce;

  dBodyAddForce(body->GetODEBody(), mForce.x(), mForce.y(), mForce.z());

  mForce.Set(0,0,0);
  return true;
}

void ForceEffector::AddForce(const salt::Vector3f& force)
{
  mForce += force;
}

First, it checks if base is valid. Then it retrieves the Body object belonging to the base object and then applies the accumulated force via an ODE function.