Sophie

Sophie

distrib > Fedora > 13 > x86_64 > media > updates > by-pkgid > fba45f71a752b715a482b8d4a068e673 > files > 275

simspark-devel-0.2.2-3.fc13.x86_64.rpm

<html>
<head>
<title>How to implement a Control Aspect</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" href="highlight.css" type="text/css">
</head>

<body bgcolor="#FFFFFF" text="#000000">
<p><font size="6"><i><b>How to implement a Control Aspect</b></i></font></p>
<p><font size="4">In this HowTo we will focus on creating a Control Aspect. The 
  Control Aspect is responsible for maintaining the rules of a simulation. It 
  also decides, which agent can request which effectors and perceptors. Thus, 
  it has at least two tasks to fullfill. For one, check effector and perceptor 
  requests, and for two, chech and enforce the rules of the simulation each frame.</font></p>
<p><font size="4">Implementing the request feature of the control aspect is simple. 
  All custom Control Aspects derive from the kerosin::ControlAspect class. This 
  class is an abstract base class, requiring descendants to implement two protected 
  functions: RequestEffectorInternal() and RequestPerceptorInternal(). Their function 
  prototypes look very similar:</font></p>
<pre><span class="com">  //! function used by agents to request effectors (this must be implemented to provide custom behavior)
</span>  <span class="key">virtual </span>boost::shared_ptr&lt;Effector&gt; RequestEffectorInternal(boost::shared_ptr&lt;AgentAspect&gt;&amp; agent, <span class="typ">const </span>std::string&amp; effectorName) = <span class="num">0</span>;
  <span class="com">//! function used by agents to request perceptors (this must be implemented to provide custom behavior)
</span>  <span class="key">virtual </span>boost::shared_ptr&lt;Perceptor&gt; RequestPerceptorInternal(boost::shared_ptr&lt;AgentAspect&gt;&amp; agent, <span class="typ">const </span>std::string&amp; perceptorName) = <span class="num">0</span>;</pre>
<p><font size="4">The functionality of these two functions is nearly identical, 
  except that one deals with Effectors and the other with Perceptors. Other than 
  that, everything is the same. Therefore, we will only look at one of them. RequestEffectorInternal() 
  accepts two parameters, a (smart) pointer to the AgentAspect which is requesting 
  the Effector and the name of the Effector requested. An implementation then 
  has to first check the type of the AgentAspect and then check if it should allow 
  the request. This is best illustrated by a small code sample from the Survival 
  plugin (a sample simulation located under plugin/survival):</font></p>
<pre>
shared_ptr&lt;Effector&gt; SurvivalControlAspect::RequestEffectorInternal(shared_ptr&lt;AgentAspect&gt;&amp; agent, <span class="typ">const </span>string&amp; effectorName)
{
  <span class="com">// always make sure, we know how to treat an agent class
</span>  <span class="key">if </span>(agent-&gt;GetClass()-&gt;Supports(<span class="str">&quot;SurvivalAgentAspect&quot;</span>))
  {
    <span class="key">if </span>(effectorName == <span class="str">&quot;kerosin/ForceEffector&quot;</span>)
      <span class="key">return </span>CreateEffector(effectorName);
  }

  <span class="com">// no valid agentaspect/effector combination
</span>  <span class="key">return </span>shared_ptr&lt;Effector&gt;();
}
</pre>
<p><font size="4">As we can see, the function first checks, if the agent is a 
  SurvivalAgentAspect. Only requests for the kerosin/ForceEffector are permitted. 
  In all other cases the smart pointer equivalent of a NULL-pointer is returned. 
  This is analogous for the RequestPerceptorInternal() function.</font></p>
<p><font size="4">Besides checking these kinds of requests, a Control Aspect also 
  has to enforce the rules of the simulation. This is best done in the PrePhysicsUpdateInternal()-function 
  (dictated by the BaseNode class). The Control Aspect holds the relevant world 
  state. For example, in the Survival Simulation it holds the current health of 
  the two agents, as well as the rate at which it decreases and the number of 
  times each agent died. Every frame, it updates these values. This is done during 
  the PrePhysicsUpdate() as this is before any simulation for this frame has taken 
  place. Some of the things to do during this phase of the update cycle are best 
  demonstrated by the Survival Simulation's Control Aspect ... the <a href="examplesrc/survivalcontrolaspect.cpp.html">SurvivalControlAspect</a> 
  class. The code should be fairly easy to understand.</font></p>
</body>
</html>