Penguin
Penguin

Reputation: 411

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

So I have a variable attemptedFPS. This is how many times my loops will be run per second.

Example loop:

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

So for example if the attemptedFPS is set to 50, that loop would run every 20 milliseconds (which would add up to 50/second).

My issue comes in having the same output no matter what the attemptedFPS is set to. I want to add a variable speed to x per second. (i.e. if speed is set to 10 that means add 10 to x by every second).

So, if inside that loop, I had:

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

Now, of course, that yields different results depending on the attemptedFPS.

What would be the equation for having the speed added to x per second be the same no matter what attemptedFPS is?

Upvotes: 1

Views: 111

Answers (2)

Remi Guan
Remi Guan

Reputation: 22292

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

This could be a basic math question. Answer is quite simple:

Divide the speed variable to attemptedFPS pieces.

Because it will get added back within your loops.

To test, this loop will run 1000/attemptedFPS times, and whatever you set attemptedFPS to what, the result will always be x += speed (10 as the example).

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

// result: 9.999999999999996;

But as you can see, it should be 10 exactly. This is because Floating point precision problem in JavaScript. I'd suggest Number.toPrecision()) to handle this problem, however it should works.

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

// result: 10;

So, answer to your question:

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

Upvotes: 1

backtick
backtick

Reputation: 2775

This will ensure that x increases by speed every second, by taking into account the milliseconds elapsed since the last time the interval fired. For instance, if the interval fired 100ms ago, that would be a tenth of a second which means we add speed * .1 to x.

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

This is necessary because an interval is not guaranteed to execute exactly every 'frame', it only guarantees that at least 1000/attemptedFPS milliseconds will pass before the function is enqueued in the event loop. The variance can easily exceed a millisecond which means simple arithmetic won't get you there. So instead we essentially check what time it is when the function fires to decide how much speed x should gain.

Upvotes: 1

Related Questions