基本上,我正在做一个游戏,当敌人出现时,敌人会追赶英雄。我要做的是
var distx = hero.px - px;
var disty = hero.py - py;
moveX += distx * .00005;
moveY += disty * .00005;
现在我必须将其乘以.00005,因为任何更高的值都会使他很快就上英雄。我希望敌人移动缓慢,所以我将其乘以.00005。我的问题是,它们之间的距离越远,怪物移动得越快,这会使英雄更难逃脱。我知道为什么会这样,我只需要知道如何解决它。
我开发游戏,如果怪物离得太远,我会将他从舞台上移开。但问题正在解决。无论他们相距多远,我都希望他以恒定的速度运动。
我也想通过不使用任何类属性来实现这一点。 (即我希望所有变量都在本地)。该方法也处于循环中
我究竟做错了什么?什么是解决方案。
谢谢你们
最佳答案
您要做的就是限制敌人的速度。
// 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;
实际上,您仅实现了控制系统工程师(1)称为PID controller的“比例”部分。您的愿望是让敌人追踪玩家,PID Controller 是一个很好的简单
tunable
(认为敌人遇到困难)追踪 Controller 。在跟踪PID Controller 中,您首先要测量所需目标与当前事务状态之间的误差。 (您现在执行此操作,并将其称为变量
distx
和disty
。)在PID Controller 中,您可以存储过去的错误,以便根据错误的不同角度采取不同的行动。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;
};
您为要控制的对象(敌人)的每个可控制状态创建一个PID Controller 。因此,您的更新逻辑将更改为:
// distx and disty are calculated as normal
var velx = pidx.step(distx);
var vely = pidy.step(disty);
moveX += velx;
moveY += vely;
现在,您可以通过更改
p,i,d
对象的PID
参数来摆脱敌人的各种行为。要复制当前的AI,您可以设置:pidx.p = 0.00005;
pidx.i = 0;
pidx.d = 0;
// same for pidy
通过提高
i
参数并进一步减少p
可以实现更有趣的AI:pidx.p = 0.000005;
pidx.i = 0.0005;
pidx.d = 0;
如果敌人持续很长时间,您经常会想清除敌人的记忆。只需调用
pidx.reset(distx)
即可重置该内存。同样,您仍将按照本答案前面给出的对
velx, vely
进行速率限制。所有这些复杂性有什么好处? 与简单的数学相比,您的敌人表现得非常自然。我还想指出,您正在使用
distx * 0.00005
逻辑沿着正确的轨道前进。(1)将控制工程师视为研究封闭系统行为并使用该知识强迫系统按照其期望方式工作的人员。