是什么导致这个 "drone" 在以特定角度转弯时抖动?

What could be causing this "drone" to be jittery when turning at certain angles?

http://codepen.io/AlexKM/pen/JGEMjZ

turnTo: function (X, Y) {
    var angleDiff = 0,
        targetA = this.angleToPoint({
            x: X,
            y: Y
        }),
        dronA = this.angle;
    ///   If the angle difference can't be reached in a frame
    if (Math.abs(targetA - dronA) > this.turnSpeed * 1.25) {
        this.workingAngle = true;
        angleDiff = targetA - dronA;
        while (angleDiff < 0)
            angleDiff += 2 * Math.PI;
        while (angleDiff > 2 * Math.PI)
            angleDiff -= 2 * Math.PI;

        if (angleDiff >= Math.PI) {
            this.turningLeft = true;
        } else {
            this.turningRight = true;
        }

    } else ///  if the diff is negligible, reach it to save CPU
        this.angle = targetA;
},

更新处理实际转向的函数片段:

    // apply turning
    if (this.turningLeft) {
        this.angle -= this.turnSpeed;
    }
    else if (this.turningRight) {
        this.angle += this.turnSpeed;
    }

红点 - 无人机朝向
橙色点 - 无人机左转或右转时发出信号
青色点 - 无人机正在重新计算时发出信号 angles/doing 三角学

代码确实包含帮助它平滑的部分,如果可以在 testDrone.turnSpeed 变量的帧内到达鼠标角度,基本上只需设置鼠标角度即可。

大约有一半的时间,它可以顺利运行。另一半,它抖个不停,左右交替,不停地计算trig。

这可能是什么原因?

不错的剧本。 :)

我认为抖动可能是(帧率(fps)+处理时间)和显示器刷新率之间差异的函数。我这样说是因为它有时看起来很光滑,有时看起来有点凹凸不平,而且就鼠标 position/movement 而言似乎没有特定的模式。

您是否考虑过使用 requestAnimationFrame() 而不是 setTimeout()See MDN HERE,其中指出...

This will request that your animation function be called before the browser performs the next repaint. The number of callbacks is usually 60 times per second, but will generally match the display refresh rate in most web browsers as per W3C recommendation.

请参阅 markE's response to this Whosebug question 关于限制 requestAnimationFrame 对特定帧率的调用。

希望对您有所帮助。 :)

修复的是确保角度实际重置为特定值,而不是当它们超过特定限制时由 Pi inc/decremented。这是我的设计错误,因为抖动消除对角度 "above" Pi 或 "below" Pi

不起作用

这是为了进入更新功能:

update: function (ctx) {
    // reset angles below and above 2pi
    while (this.angle > Math.PI)
        this.angle = -Math.PI;
    while (this.angle < -Math.PI)
        this.angle = Math.PI;