Architektura gier HTML5: Jak utrzymać stałe 60 FPS w przeglądarce przy tysiącach obiektów

· 8 min czytania

Tworzenie gier w przeglądarce za pomocą elementu <canvas> stawia przed programistą wysokie wymagania wydajnościowe. Budżet czasowy jednej klatki przy odświeżaniu 60 Hz wynosi zaledwie 16.66 milisekundy. W tym oknie czasowym silnik musi przetworzyć wejście od gracza, zaktualizować stan fizyki, wykryć kolizje oraz wyrenderować scenę.

1. Wykorzystanie prawidłowej pętli gry (Delta Time Loop)

Nigdy nie należy opierać aktualizacji logiki gry na funkcjach setInterval ani setTimeout. Prawidłowy wzorzec wykorzystuje requestAnimationFrame wraz z obliczaniem delty czasu:

let lastTime = performance.now();

function gameLoop(currentTime) {
  const deltaTime = (currentTime - lastTime) / 1000;
  lastTime = currentTime;

  updatePhysics(deltaTime);
  renderCanvas();

  requestAnimationFrame(gameLoop);
}
requestAnimationFrame(gameLoop);

2. Unikanie alokacji pamięci w pętli renderowania (Garbage Collection Spikes)

W języku JavaScript jednym z największych wrogów płynności gry jest Garbage Collector (GC). Jeśli wewnątrz funkcji rysującej tworzysz setki tymczasowych wektorów lub obiektów cząsteczek, silnik V8 co kilka sekund wstrzyma wykonanie skryptu w celu wyczyszczenia pamięci, powodując gwałtowny spadek z 60 do 20 FPS.

Rozwiązanie: Wzorzec Object Pool (Pula Obiektów)
Zamiast niszczyć i tworzyć obiekty (np. pociski, cząsteczki dymu), zainicjalizuj stałą tablicę obiektów na początku gry i aktywuj/deaktywuj je za pomocą flagi isActive.

3. Technika Double Buffering i OffscreenCanvas

Dla złożonych elementów tła lub powtarzających się grafik kafelkowych (tilemaps) nie należy rysować każdego elementu co klatkę. Narysuj statyczne elementy raz na niewidocznym płótnie w pamięci RAM (OffscreenCanvas), a następnie przenieś cały gotowy obraz jedną błyskawiczną operacją ctx.drawImage().

Zobacz także