patternjavascriptMinor
Efficient way to calculate game time
Viewed 0 times
efficientwaytimegamecalculate
Problem
It's a common occurrence nowadays to have different refresh rates across different devices. That's why it's very important to keep track of the device's frame rate to keep the game time consistent across different refresh rates.
Is this an efficient way to go about this?
Is this an efficient way to go about this?
var timeBetween;
var timeLast;
function gameLoop() {
var timeNow = window.performance.now();
timeBetween = timeNow - timeLast;
timeLast = timeNow;
gameLogic(timeBetween); // Send time to game logic to calculate e.g. game speed etc.
gameDraw();
requestAnimationFrame(gameLoop);
}Solution
One thing I recommend is to use a "scale factor" (I'm making names, there might be an official name for this approach) - a unit-less value that you multiply to time-sensitive values to compensate for frame rate differences. One perk when doing it this way is you don't have to write time sorcery in your equations (which is everywhere usually). You write them as is and just multiply this value to the result.
The formula is
The number of callbacks is usually 60 times per second, but will generally match the display refresh rate in most web browsers as per W3C recommendation.
https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
Here's an example calculation with a box that should move 60 units at 60fps. At 60fps, it moves an intended 60 units. But if the frame rate drops to 40fps, it should not move 40 units. Scale factor compensates for that by scaling up the calculated value.
Your code would look like:
In terms of the code you just posted, there isn't much of a difference. But where the difference will be is in how you write your game logic using this value.
The formula is
scale = delta / 16.6 where 16.6 is the frame time for 60fps. But this may differ per device, so you might need to find out the device refresh rate first and adjust this accordingly. According to MDN:The number of callbacks is usually 60 times per second, but will generally match the display refresh rate in most web browsers as per W3C recommendation.
https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
Here's an example calculation with a box that should move 60 units at 60fps. At 60fps, it moves an intended 60 units. But if the frame rate drops to 40fps, it should not move 40 units. Scale factor compensates for that by scaling up the calculated value.
// At 60fps, a frame takes 16.6ms
const delta = 16.6;
const scale = delta / 16.6; // 1
const boxMoved = 60; // your logic at 60fps calculates 60 units
const officialBoxMoved = boxMoved * scale; // 60
// At 40fps, a frame takes 25ms
const delta = 25;
const scale = delta / 16.6; // 1.5
const boxMoved = 40; // your logic at 40fps calculates 40 units
const officialBoxMoved = boxMoved * scale; // 60Your code would look like:
let lastTime = performance.now();
(function gameLoop(currentTime){
requestAnimationFrame(gameLoop);
const scale = (currentTime - lastTime) / (100 / 6);
lastTime = currentTime;
gameLogic(scale);
gameDraw();
}());In terms of the code you just posted, there isn't much of a difference. But where the difference will be is in how you write your game logic using this value.
Code Snippets
// At 60fps, a frame takes 16.6ms
const delta = 16.6;
const scale = delta / 16.6; // 1
const boxMoved = 60; // your logic at 60fps calculates 60 units
const officialBoxMoved = boxMoved * scale; // 60
// At 40fps, a frame takes 25ms
const delta = 25;
const scale = delta / 16.6; // 1.5
const boxMoved = 40; // your logic at 40fps calculates 40 units
const officialBoxMoved = boxMoved * scale; // 60let lastTime = performance.now();
(function gameLoop(currentTime){
requestAnimationFrame(gameLoop);
const scale = (currentTime - lastTime) / (100 / 6);
lastTime = currentTime;
gameLogic(scale);
gameDraw();
}());Context
StackExchange Code Review Q#160334, answer score: 2
Revisions (0)
No revisions yet.