获得更准确的浮点计算

时间:2013-02-19 21:01:13

标签: javascript floating-accuracy

我正在使用由JavaScript驱动的canvas元素构建游戏。我的播放器类的一部分包括update()方法,每个方法调用一次。在这个方法中,我正在做一些数学运算,根据键盘输入更新球员的速度,并移动球员。这是代码的一小部分:

// Gradually make the players velocity 0
if(this.xv > 0) {
    this.xv -= 0.1;
} else if(this.xv < 0) {
    this.xv += 0.1;
}
if(this.yv > 0) {
    this.yv -= 0.1;
} else if(this.yv < 0) {
    this.yv += 0.1;
}

// Update player position based on velocity
this.x += this.xv;
this.y += this.yv;

// Update velocity based on keyboard inputs
if(keyState[87]) {
    this.yv -= 0.5;
}
if(keyState[65]) {
    this.xv -= 0.5;
}
if(keyState[83]) {
    this.yv += 0.5;
}
if(keyState[68]) {
    this.xv += 0.5;
}

现在理论上这应该都可行,如果玩家按住W键4个刻度,它们的速度将是2,然后再经过40个刻度后,它们的速度将降低到{{1} }。

但这在实践中不起作用,因为JavaScript在处理浮点数时似乎并不完全准确。如果我0每个游戏的速度变量滴答我得到这种输出:

console.log()

所以这里有两件事看起来不对,一个是JavaScript从未以高精度计算速度,另一个是当速度为负时它总是至少x: -1.0241807402167069e-14 y: -1.379452108096757e-14 x: 0.09999999999998976 y: 0.09999999999998621 x: -1.0241807402167069e-14 y: -1.379452108096757e-14 x: 0.09999999999998976 y: 0.09999999999998621 ,这是一个问题因为玩家精灵现在每个刻度移动1个像素。

如何为此任务获得更准确的计算?

1 个答案:

答案 0 :(得分:1)

我建议使用“指数衰减”方法来平滑速度转换。我将使用以下内容代替您当前用于将速度降低到零的条件块:

this.xv *= 0.9;
this.yv *= 0.9;

请注意,这会使您的最大速度达到恒定加速度的十倍,并且改变衰减速率将改变该乘数。这可能没问题,但如果不是这样,你可以通过调整方程式来简化目标速度:

var p = 0.9;
var q = 1.0 - p;
this.xv = this.xv * p + this.txv * q;
this.yv = this.yv * p + this.tyv * q;

免责声明:这在牛顿物理学中没有真正的基础;这只是我想出来帮助平滑机器人状态转换的东西。但它对我来说很有用,并且希望也适合你。