Reputation: 411
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
Reputation: 22292
- add
speed
tox
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 toattemptedFPS
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
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