如果我不知道每秒 运行 有多少次,我怎样才能得到相同的输出?

If I don't know how many times something will run per second, how can I get the same output?

所以我有一个变量attemptedFPS。这是我的循环每秒 运行 的次数。

示例循环:

setInterval(console.log, 1000/attemptedFPS, "Hello World");

因此,例如,如果 attemptedFPS 设置为 50,则该循环将每 20 毫秒 运行(加起来为 50/秒)。

我的问题是无论 attemptedFPS 设置成什么,输出都是一样的。我想每秒添加一个变量 speedx。 (即,如果 speed 设置为 10,则意味着每秒向 x 添加 10)。

所以,如果在那个循环中,我有:

setInterval(function(){
  x += speed;
}, 1000/attemptedFPS);

现在,当然,根据 attemptedFPS 会产生不同的结果。

无论 attemptedFPS 是多少,每秒将 speed 添加到 x 的公式是什么?

这将确保 x 每秒增加 speed,考虑到自上次触发间隔以来经过的毫秒数。例如,如果间隔在 100 毫秒前触发,那将是十分之一秒,这意味着我们将 speed * .1 添加到 x

let then = Date.now()
setInterval(function(){
  const timeSinceLastFrame = Date.now() - then;
  then = Date.now()
  x += speed*timeSinceLastFrame/1000;
}, 1000/attemptedFPS);

这是必要的,因为不能保证间隔恰好每隔 'frame' 执行一次,它只能保证至少 1000/attemptedFPS 毫秒后函数才会在事件循环中排队。方差很容易超过一毫秒,这意味着简单的算术不会让你到达那里。因此,我们实际上是检查函数触发的时间,以决定 x 应该获得多少速度。

  • add speed to x by every second.
  • whatever the function execute how many times (also by every second).

这可能是一道基础数学题。答案很简单:

Divide the speed variable to attemptedFPS pieces.

因为它会被添加回您的循环中。

测试一下,这个循环会运行1000/attemptedFPS次,不管你把attemptedFPS设置成什么,结果总是x += speed(以10为例).

for (let i = 0; i < 1000; i += 1000/attemptedFPS) {
  x += speed / attemptedFPS;
}

// result: 9.999999999999996;

但是如您所见,它应该正好是 10。这是因为JavaScript中的浮点精度问题。我建议 Number.toPrecision()) 来处理这个问题,但它应该有效。

for (let i = 0; i < 1000; i += 1000/attemptedFPS) {
  x += speed / attemptedFPS;
  x = +parseFloat(x.toPrecision(12));
}

// result: 10;

所以,回答你的问题:

setInterval(function(){
  x += speed / attemptedFPS;
  x = +parseFloat(x.toPrecision(12));
}, 1000/attemptedFPS);