Способ работы браузеров и javascript затрудняет настройку фиксированной частоты кадров. Скажите, что вы хотите делать что-то каждую секунду, например, обновление и рисование. Одним из способов сделать это может быть вызов window.setTimeout()
с настройкой в одну секунду. Но проблема в том, что это не так надежно, даже если вы настраиваете обратный вызов каждую секунду, вы не можете быть уверены, что все обратные вызовы будут выполнены. Например, высокая загрузка процессора может привести к тому, что обратные вызовы будут поступать намного позже, чем нужно. И даже если обратные вызовы будут вовремя, вы не сможете контролировать, когда произойдет фактический рисунок на экране.
Лучший способ справиться с этим - принять тот факт, что вы не можете получить точное время ваших звонков, а вместо этого, когда вы звоните, вы подсчитываете, сколько времени прошло и действует в соответствии с этим , Это означает, что вы позволите системе решить частоту кадров, и вы просто позаботитесь об обновлении анимации или игры в зависимости от того, сколько времени прошло.
requestAnimationFrame - это более новая функциональность, поддерживаемая большинством браузеров, особенно полезная для игр. Он будет вызываться каждый раз, когда браузер готов рисовать, что хорошо. Затем вы узнаете, что обновления и чертежи, которые вы делаете, произойдут прямо перед тем, как фактический кадр будет выведен на экран.
Вот пример того, как вы можете обновить свой gameLoop, чтобы учитывать разницу во времени.
var lastTimestamp = +new Date;
function gameLoop(timestamp) {
var now = +new Date;
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);
}
Звучит очень логично и умно. – nerkn
Разве вы не должны менять SetTimeout и requestAnimationFrame каким-то образом? В вашем примере обновление и рисование вызываются в событии setTimeout, все еще асинхронно, в то время как тело gameloop() синхронизируется (но не делает ничего, кроме установки таймаута) –
@DanielAlder. Этот код пару лет, и теперь 'requestAnimationFrame' автоматически отправляет в метку времени, поэтому' setTimeout' больше не требуется. Используйте метку времени для дросселирования анимации. – markE