Javascript - Can't Adjust Framerate - Requestanimationframe
Solution 1:
rAF is locked to monitor's sync, typically 60 Hz, so we can't adjust the FPS for it in itself (browser may reduce FPS when tab is inactive or on batteries).
Also, what you are trying to change is the fallback for the poly-fill; that is: if rAF is not supported in the browser it will instead use setTimeout
. However, most browsers nowadays do support rAF (even un-prefixed) so the setTimeout
will never be used.
You can do two things:
- Replace rAF in your loop by using
setTimeout
directly (when testing)
Example:
var FPS = 1;
function testLoop() {
... ordinary code
setTimeout(testLoop, 1000/FPS);
}
- Throttle rAF by using a counter:
Example:
var framesToSkip = 60,
counter = 0;
function loop() {
if (counter < framesToSkip) {
counter++;
requestAnimationFrame(loop);
return;
}
/// do regular stuff
counter = 0;
requestAnimationFrame(loop);
}
There are most likely better ways to implement throttling, but I am trying to just show the basic principle. This will still run at full speed, 60 FPS, but your code will do minimal of operations and only when the counter has reached its count will it execute the main code.
You do not need to clear the canvas each time if what you draw next will cover previously drawn content, or if you want to keep it of course. You can also clear a portion to optimize further, if needed.
Solution 2:
A bit late to the party, but here's how to get the benefit of RAF while also controlling frames/second.
Note: requestAnimationFrame now has a better way of doing things than by using the code pattern in my original 3 year old original answer ... see my update below for the new and improved way.
[Update: requestAnimationFrame now has a better way of throttling]
The new version of requestAnimationFrame
now automatically sends in a current timestamp that you can use to throttle your code execution.
Here is example code to execute your code every 1000ms:
var nextTime=0;
var delay=1000;
functiongameLoop(currentTime){
if(currentTime<nextTime){requestAnimationFrame(gameLoop); return;}
nextTime=currentTime+delay;
// do stuff every 1000msrequestAnimationFrame(looper);
}
}
Solution 3:
You should look at this article which gives a proper treatment of the subject. http://creativejs.com/resources/requestanimationframe/
var fps = 15;
functiondraw() {
setTimeout(function() {
requestAnimFrame(draw);
// Drawing code goes here
}, 1000 / fps);
}
Here is the code I think you want, but in the original article it said used requestAnimationFrame, but here I am using requestAnimFrame. I think maybe it changed and you're supposed to use requestAnimFrame now. requestAnimationFrame did not work for me while requestAnimFrame did.
Solution 4:
The way browsers and javascript work makes it difficult to set up a fixed frame rate. Say you want to do something every one second, like updating and drawing. One way of doing that could be to call window.setTimeout()
with a setting of one second. But the problem is that this is not that reliable, even if you configure a callback every second you can't be sure all callbacks will be in time. A high processor load, for example, could make the callbacks arrive much later than they should. And even if the callbacks would be on time, you have no control of when the actual drawing to the screen will happen.
A better way of handling it is to accept the fact that you can't get a very precise timing of your calls, and instead, whenever you get a call, you calculate how much time has passed and act according to that. This means you'll let the system decide the frame rate, and you just take care of updating your animation or game depending on how much time that has passed.
requestAnimationFrame is a newer functionality supported by most browsers by now that is especially useful for games. It will be called every time the browser is ready to draw, which is good. Then you will know that the updates and drawing you are doing will happen right before the actual frame is drawn to screen.
Here's an example on how you could update your gameLoop to take the time difference into account.
var lastTimestamp = +newDate;
functiongameLoop(timestamp) {
var now = +newDate;
var dt = now - lastTimestamp;
// dt is the amount of time in ms that has passed since last call.// update takes this time difference (in seconds) and can then perform its// updates based on time passed.update(dt / 1000);
draw();
lastTimestamp = now;
requestAnimationFrame(gameLoop);
}
Solution 5:
That's how requestAnimationFrame
works. If you want a specific framerate, use setTimeout
only.
Usually you would take a parameter, which is the current time. Compare it to the last frame's time to find out how far along the animation should move.
Post a Comment for "Javascript - Can't Adjust Framerate - Requestanimationframe"