2013-09-25 8 views
9

zacznę pętlęJavascript - nie można regulować framerate - 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. Nie można regulować szybkość klatek. To zawsze jest naprawdę szybkie. Dlaczego nie mogę zmienić go na 1 klatkę na sekundę. Chcę to zrobić tylko w celach testowych.
  2. Czy za każdym razem muszę wyczyścić płótno? Wydaje się, że działa dobrze, nie oczyszczając go.

Dzięki.

Oto link do skrzypiec dla kompletnego kodu: complete code

Dzięki

Odpowiedz

9

Raf Zablokowane monitorować Sync, typowo 60 Hz, więc nie możemy ustawić FPS dla niego sama w sobie (przeglądarka może zmniejszyć liczbę klatek na sekundę, gdy karta jest nieaktywna lub na bateriach).

Co próbujesz zmienić, to awaryjne zapełnienie; to znaczy: jeśli rAF nie jest obsługiwany w przeglądarce, to zamiast tego użyje setTimeout. Jednak większość przeglądarek w dzisiejszych czasach do obsługuje rAF (nawet bez prefiksu), więc setTimeout nigdy nie będzie używane.

Można zrobić dwie rzeczy:

  • Wymień RAF w pętli za pomocą setTimeout bezpośrednio (przy testowaniu)

Przykład:

var FPS = 1; 

function testLoop() { 

    ... ordinary code 

    setTimeout(testLoop, 1000/FPS); 
} 
  • przepustnicy RAF za pomocą licznik:

Przykład:

var framesToSkip = 60, 
    counter = 0; 

function loop() { 

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

    /// do regular stuff 

    counter = 0; 
    requestAnimationFrame(loop); 
} 

MODIFIED FIDDLE HERE

Są najprawdopodobniej lepszych sposobów realizacji dławienie, ale staram się po prostu pokazać zasadę podstawową. To będzie nadal działać z pełną prędkością, 60 FPS, ale twój kod wykona minimum operacji i dopiero gdy licznik osiągnie swój licznik, wykona główny kod.

Nie musisz usuwać płótna za każdym razem, jeśli to, co narysujesz dalej, obejmie wcześniej narysowaną treść lub jeśli chcesz ją zachować. Możesz również wyczyścić część, aby w razie potrzeby zoptymalizować ją.

0

requestAnimationFrame będzie działać z maksymalną osiągalną liczbą klatek na sekundę (do 60 klatek na sekundę). Dzieje się tak dlatego, że zawsze da ci następną ramkę animacji.

Parametr, który ustawiłeś, dotyczy tylko polyfill, który będzie aktywny, jeśli Twoja przeglądarka nie ma implementacji requestAnimationFrame.

Jeśli chcesz spróbować malować w jednej sekundzie w celach testowych, spróbuj zamiast tego setInterval.

0

Tak działa requestAnimationFrame. Jeśli chcesz mieć określoną ilość klatek na sekundę, używaj tylko setTimeout.

Zwykle bierzesz parametr, który jest bieżącym czasem. Porównaj go z czasem ostatniej klatki, aby dowiedzieć się, jak daleko powinna się przesunąć animacja.

1

Sposób, w jaki przeglądarki i obsługa javascript utrudnia ustawianie stałej liczby klatek na sekundę. Załóżmy, że chcesz coś zrobić co sekundę, na przykład aktualizowanie i rysowanie. Jednym ze sposobów na to może być wywołanie window.setTimeout() z ustawieniem jednej sekundy. Problem polega jednak na tym, że nie jest to niezawodne, nawet jeśli konfigurujesz wywołanie zwrotne co sekundę, nie możesz być pewien, że wszystkie wywołania zwrotne będą na czas. Na przykład wysokie obciążenie procesora może sprawić, że oddzwonienie dotrze dużo później niż powinno. Nawet jeśli połączenia zwrotne będą wykonywane na czas, nie masz wpływu na to, kiedy nastąpi faktyczne rysowanie na ekranie.

Lepszym sposobem radzenia sobie z tym jest zaakceptowanie faktu, że nie można uzyskać bardzo dokładnego czasu połączeń, a zamiast tego, za każdym razem, gdy otrzymasz połączenie, obliczysz, ile czasu minęło i postępujesz zgodnie z tym . Oznacza to, że pozwalasz systemowi decydować o liczbie klatek na sekundę i po prostu dbasz o aktualizowanie animacji lub gry w zależności od tego, ile czasu minęło.

requestAnimationFrame to nowsza funkcja obsługiwana przez większość przeglądarek, która jest szczególnie przydatna w grach. Będzie on wywoływany za każdym razem, gdy przeglądarka będzie gotowa do rysowania, co jest dobre. Wtedy będziesz wiedział, że aktualizacje i rysunki, które robisz, będą miały miejsce tuż przed wyświetleniem rzeczywistej klatki.

Oto przykład, w jaki sposób można zaktualizować grę, aby uwzględnić różnicę czasu.

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

Nieco późno na imprezę, ale oto jak uzyskać korzyści z RAF, jednocześnie kontrolując klatki/sekundę.

Uwaga: requestAnimationFrame ma teraz lepszy sposób robienia rzeczy niż użycie wzoru kodu w mojej oryginalnej 3-letniej oryginalnej odpowiedzi ... zobacz moją aktualizację poniżej w nowy i ulepszony sposób.

[Aktualizacja: requestAnimationFrame ma teraz lepszy sposób dławienia]

Nowa wersja requestAnimationFrame teraz automatycznie wysyła w bieżącym znacznikiem czasu, które można wykorzystać do udusić swoją wykonanie kodu.

Oto przykładowy kod do wykonania kodu co 1000ms:

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

Brzmi bardzo logicznie i sprytnie. – nerkn

+0

Czy nie należy w jakiś sposób zamienić setTimeout i requestAnimationFrame? W twoim przykładzie aktualizacja i losowanie są wywoływane w zdarzeniu setTimeout, nadal asynchronizowane, gdy ciało gameloop() jest zsynchronizowane (ale nie robi nic poza ustawieniem limitu czasu) –

+0

@DanielAlder. Ten kod ma kilka lat i teraz 'requestAnimationFrame' automatycznie wysyła znacznik czasu, więc' setTimeout' nie jest już potrzebny. Użyj znacznika czasu, aby dławić animację. – markE

2

Należy spojrzeć na to artykuł, który daje właściwe traktowanie podmiotu. http://creativejs.com/resources/requestanimationframe/

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

Oto kod Myślę, że chcesz, ale w oryginalnym artykule wspomniany kiedyś requestAnimationFrame, ale tutaj używam requestAnimFrame. Myślę, że może się to zmieniło i powinieneś teraz użyć requestAnimFrame.requestAnimationFrame nie działa dla mnie, gdy requestAnimFrame to zrobił.

Powiązane problemy