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);
}
Brzmi bardzo logicznie i sprytnie. – nerkn
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) –
@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