2013-09-25 5 views
9

я начинаю циклJavascript - не может регулировать частоту кадров - requestanimationframe

function gameLoop(){ 
    update(); 
    draw(); 
    requestAnimFrame(gameLoop); 
} 

var requestAnimFrame = window.requestAnimationFrame || 
        window.webkitRequestAnimationFrame || 
        window.mozRequestAnimationFrame || 
        window.oRequestAnimationFrame || 
        window.msRequestAnimationFrame || 
        function(callback) { 
         window.setTimeout(callback, 1000/1); 
        }; 
  1. Я не могу настроить частоту кадров. Это всегда очень быстро. Почему я не могу изменить его на 1 кадр в секунду. Я хочу сделать это только для целей тестирования.
  2. Должен ли я каждый раз очищать холст? Кажется, он работает хорошо, не очищая его.

Спасибо.

Вот ссылка на скрипку для полного кода: complete code

Благодаря

ответ

9

RAF закрыта для мониторинга синхронизации, как правило, 60 Гц, поэтому мы не можем настроить FPS для него само по себе (браузер может уменьшить FPS, если вкладка неактивна или на батареях).

Кроме того, то, что вы пытаетесь изменить, - это резерв для полиполнения; то есть: если rAF не поддерживается в браузере, вместо этого он будет использовать setTimeout. Тем не менее, большинство браузеров в настоящее время do поддержка rAF (даже без префикса), поэтому setTimeout никогда не будет использоваться.

Вы можете сделать две вещи:

  • Заменить RAF в цикле с помощью setTimeout непосредственно (при тестировании)

Пример:

var FPS = 1; 

function testLoop() { 

    ... ordinary code 

    setTimeout(testLoop, 1000/FPS); 
} 
  • дроссельной Raf с помощью счетчик:

Пример:

var framesToSkip = 60, 
    counter = 0; 

function loop() { 

    if (counter < framesToSkip) { 
     counter++; 
     requestAnimationFrame(loop); 
     return; 
    } 

    /// do regular stuff 

    counter = 0; 
    requestAnimationFrame(loop); 
} 

MODIFIED FIDDLE HERE

Есть, скорее всего, более эффективные способы реализации удушения, но я стараюсь, чтобы просто показать основной принцип. Это будет работать на полной скорости, 60 FPS, но ваш код будет выполнять минимальные операции, и только когда счетчик достигнет своего счета, он выполнит основной код.

Вам не нужно очищать полотно каждый раз, если то, что вы рисуете дальше, будет охватывать ранее нарисованный контент, или если вы хотите сохранить его, конечно. Вы также можете очистить часть для дальнейшей оптимизации, если это необходимо.

0

requestAnimationFrame будет работать с максимальной достижимой частотой кадров (до 60 кадров в секунду). Это связано с тем, что он всегда даст вам следующий анимационный фрейм.

Параметр, который вы отредактировали, предназначен только для полизаполнения, которое будет активным, если ваш браузер не имеет реализации requestAnimationFrame.

Если вы хотите попробовать рисовать в течение одной секунды для целей тестирования, вместо этого попробуйте setInterval.

0

Вот так requestAnimationFrame работ. Если вам нужна определенная частота кадров, используйте только setTimeout.

Обычно вы принимаете параметр, который является текущим временем. Сравните его с временем последнего кадра, чтобы узнать, как далеко двигаться по анимации.

1

Способ работы браузеров и 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); 
} 
6

Немного опоздал на вечеринку, но вот как получить преимущество RAF, а также управлять кадрами/секундой.

Примечание: requestAnimationFrame теперь имеет лучший способ сделать что-то, чем использовать шаблон кода в моем первоначальном 3-летнем оригинальном ответе ... см. Мое обновление ниже для нового и улучшенного способа.

[Update: requestAnimationFrame теперь есть лучший способ дросселирования]

Новая версия requestAnimationFrame теперь автоматически отправляет в текущей временной метки, которые вы можете использовать, чтобы задушить выполнение Вашего кода.

Вот пример кода, чтобы выполнить код каждые 1000 мс:

var nextTime=0; 
var delay=1000; 

function gameLoop(currentTime){ 
    if(currentTime<nextTime){requestAnimationFrame(gameLoop); return;} 
    nextTime=currentTime+delay; 
    // do stuff every 1000ms 
    requestAnimationFrame(looper); 
} 

}

+0

Звучит очень логично и умно. – nerkn

+0

Разве вы не должны менять SetTimeout и requestAnimationFrame каким-то образом? В вашем примере обновление и рисование вызываются в событии setTimeout, все еще асинхронно, в то время как тело gameloop() синхронизируется (но не делает ничего, кроме установки таймаута) –

+0

@DanielAlder. Этот код пару лет, и теперь 'requestAnimationFrame' автоматически отправляет в метку времени, поэтому' setTimeout' больше не требуется. Используйте метку времени для дросселирования анимации. – markE

2

Вы должны смотреть на это статья, которая дает правильное отношение к предмету. http://creativejs.com/resources/requestanimationframe/

var fps = 15; 
function draw() { 
    setTimeout(function() { 
     requestAnimFrame(draw); 
     // Drawing code goes here 
    }, 1000/fps); 
} 

Вот код, который я думаю, что вы хотите, но в оригинальной статье используется указанный requestAnimationFrame, но здесь я использую requestAnimFrame. Я думаю, возможно, это изменилось, и теперь вы должны использовать requestAnimFrame.requestAnimationFrame не работал для меня, а requestAnimFrame.

Смежные вопросы