All you have to do is rate limit the velocity of the enemy.
// 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 > maxVel) {
var r = maxVel / vel;
velx *= r;
vely *= r;
}
// Move the enemy
moveX += velx;
moveY += vely;
You have essentially implement only the "proportional" part of what control systems engineers (1) call a PID controller. Your desire is for the enemy to track the player, and the PID controller is a nice simple tunable (think enemy difficulties) tracking controller.
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 distx and disty.) In a PID controller, you keep a memory of past errors so that you can act differently based upon different perspectives of the error.
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;
};
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:
// distx and disty are calculated as normal
var velx = pidx.step(distx);
var vely = pidy.step(disty);
moveX += velx;
moveY += vely;
You can now get a variety of behaviors out of enemies by varying the p,i,d parameters of the PID object. To replicate your current AI, you would set:
pidx.p = 0.00005;
pidx.i = 0;
pidx.d = 0;
// same for pidy
While a more interesting AI can be achieved by bumping up the i parameter and reducing p even further:
pidx.p = 0.000005;
pidx.i = 0.0005;
pidx.d = 0;
Every so often you will want to clear the enemy's memory if he lasts for a very long time. Just call pidx.reset(distx) to reset that memory.
Also you will still want to rate-limit the velx, vely as given earlier in this answer.
What are the benefits of all this complexity? 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 distx * 0.00005 logic.
(1) 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.