Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>All you have to do is rate limit the velocity of the enemy.</p> <pre><code>// Calculate velocity just as you're doing it var p = .00005; var velx = distx * p; var vely = disty * p; // Rate limit that velocity var maxVel = 5; // You will have to tune this value as your max speed var vel = Math.sqrt(velx*velx + vely*vely); if (vel &gt; maxVel) { var r = maxVel / vel; velx *= r; vely *= r; } // Move the enemy moveX += velx; moveY += vely; </code></pre> <p>You have essentially implement only the "proportional" part of what control systems engineers (1) call a <a href="http://en.wikipedia.org/wiki/PID_controller" rel="noreferrer">PID controller</a>. Your desire is for the enemy to track the player, and the PID controller is a nice simple <code>tunable</code> (think enemy difficulties) tracking controller.</p> <p>In a tracking PID controller, you first measure the error between your desired goal and the current state of affairs. (You do this now, and called the variables <code>distx</code> and <code>disty</code>.) In a PID controller, you keep a memory of past errors so that you can act differently based upon different perspectives of the error.</p> <pre><code>PID = function() { this.p = 0; this.i = 0; this.d = 0; this.reset(0); }; PID.prototype.reset = function(error) { this.error = error; this.integral = 0; this.differential = 0; } PID.prototype.step = function(error) { this.integral += error; this.differential = (error - this.error); this.error = error; var control = this.p * this.error + this.i * this.integral + this.d * this.differential; return control; }; </code></pre> <p>You create a PID controller for each of the controllable states for the object you are trying to control (the enemy). So your update logic will change to:</p> <pre><code>// distx and disty are calculated as normal var velx = pidx.step(distx); var vely = pidy.step(disty); moveX += velx; moveY += vely; </code></pre> <p>You can now get a variety of behaviors out of enemies by varying the <code>p,i,d</code> parameters of the <code>PID</code> object. To replicate your current AI, you would set:</p> <pre><code>pidx.p = 0.00005; pidx.i = 0; pidx.d = 0; // same for pidy </code></pre> <p>While a more interesting AI can be achieved by bumping up the <code>i</code> parameter and reducing <code>p</code> even further:</p> <pre><code>pidx.p = 0.000005; pidx.i = 0.0005; pidx.d = 0; </code></pre> <p>Every so often you will want to clear the enemy's memory if he lasts for a very long time. Just call <code>pidx.reset(distx)</code> to reset that memory.</p> <p>Also you will still want to rate-limit the <code>velx, vely</code> as given earlier in this answer.</p> <p><strong>What are the benefits of all this complexity?</strong> You get enemies that behave very naturally as compared to simpler maths. I also wanted to point out that you're moving along the right tracks with your <code>distx * 0.00005</code> logic.</p> <p><strong>(1)</strong> Think of controls engineers as those who study the behavior of closed systems and use that knowledge to force the system to act in ways they desire.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload