Reputation: 3889
I have been playing around with canvas
and animation, with HTML5 games in mind specifically and quickly learnt the limitations of just using requestAnimationFrame (rFA)
and have moved to time-based animations.
I want to maintain constant gameplay regardless of monitor refresh rate or FPS but am unsure how best to handle the animations. I have read through all sorts of implementations but have not found any best practice so to speak. Should I be using a combination of the two?
So far I have considered several options:
rFa
only (changes results when fps changes):
var animate = function() {
draw();
requestAnimationFrame(animate);
}
time-based only (not always consistent):
var animate = function() {
now = Date.now();
delta = now - last;
last = now;
draw(delta);
window.setTimeout(animate, 1000/60)
}
set FPS on rFA
with setInterval
(not always consistent):
setInterval(function () {
draw();
requestAnimationFrame();
}, 1000/fps);
rFA
trying to force fps (does not seem very robust, variable delta would work better):
var delta = 1000 / fps;
var animate = function() {
now = Date.now();
if (now - last >= delta) {
last = now;
}
draw(delta);
requestAnimationFrame(animate);
}
time-based rFA
(some strange results):
var animate = function () {
now = Date.now();
delta = now - last;
last = now;
draw(delta);
requestAnimationFrame(animate);
}
Ignore the lack of browser support and the use of Date.now(), I just want to demonstrate my flow of thinking. I think that the last option is preferable, but the last two can run into problems with updating too far and missing collisions etc as well as updates taking too long that the animation looses all control.
Also when a user tabs out using rFA
only the animation will pause, using a time based function to call rFA
means that the game/animation will continue to run in the background which is not ideal.
What would be the best way to handle animations trying to keep consistent results regardless of fps, all of the above might be bad and my apologies for the long post (it is just what I have tried so far and am still pretty lost)? even better with with the above issues in mind?
Upvotes: 1
Views: 4336
Reputation: 664307
If you have requestAnimationFrame
available, I wouldn't go against it and only call draw()
from its callbacks. Of course, you should always use delta timing.
Here's a sophisticated variation of raF
with a fallback to setTimeout
for the game logic updates in case the frame rate is too low:
var maximalUpdateDelay = 25; // ms
var updateTimeout, now;
function animate() {
updateTimeout = setTimeout(animate, maximalUpdateDelay);
var delta = -now + (now = Date.now());
update(now, delta);
}
function main() {
clearTimeout(updateTimeout);
animate(); // update the scene
draw(); // render the scene
requestAnimationFrame(main);
}
main();
Upvotes: 2
Reputation: 2649
I think you're on the right track with the last one because it should give you the most consistency across devices running at different frame rates, but you definitely want to force your delta value down if it gets too high to avoid big jumps:
var animate = function () {
now = Date.now();
delta = now - last;
last = now;
if(delta > 20) {
delta = 20;
}
draw(delta);
requestAnimationFrame(animate);
};
Upvotes: 0
Reputation: 1757
I'ld recommend taking a look at the HTML 5 - Game Development course on Udacity. I don't remember the implementation of this problem from the course (but there definitely was one), but my opinion from a gameplay perspective is that just using rAF (like your first bullet) is the most fun, even if there is game slow down due to too much processing needed on slower computers.
Upvotes: 0