Closed toddmedema closed 2 months ago
From a quick search, I believe this is a good link which goes over the problem and solutions. https://gafferongames.com/post/fix_your_timestep/
Got any others you know of or like on this topic?
That approach sounds good to me! I was just thinking of reducing the timeout between frames, but it's a good idea to also simulate between frames on slow machines. And we know that our simulation logic is about 10x faster than our render logic, so simulating multiple frames between renders will help slower machines catch up.
This would make our logic something like:
export const TICK_MS = { // updated to account for real simulate/render time
// PAUSED: 250, - now, the tick function may run every 250ms, but no game frames should happen
SLOW: 180,
NORMAL: 60,
FAST: 20,
};
let currentTime = performance.now();
tick: () => {
let newTime = performance.now();
let delta = newTime - currentTime;
currentTime = newTime;
while (delta > TICK_MS[state.speed]) {
simulateFrame();
delta -= TICK_MS[state.speed];
}
return state;
}
For MVP, I set the game speed based on timeout between ticks in CONSTANTS.tsx
But this will lead to an inconsistent experience across devices. Ideally these times would represent time per frame, and the timeout would be set based on how long the previous frame took to calculate+render.
For reference, on an M1 Macbook Pro, each render on Facilities page took 16ms, and simulation steps took between 1-18ms depending on if it was generating a new month — and would presumably be much slower on a slower device.
Example calculation: 100ms frame timing on slow - 17ms to render and calculate = timer set for 83ms