Prędkość postaci nie powinna zależeć od monitora

Jeżeli przy każdym narysowaniu obrazu przesuwasz bohatera o dwa piksele, urządzenie wyświetlające więcej klatek przyspieszy całą rozgrywkę. Przeciwnicy, skoki i czas reakcji będą działać inaczej na różnych ekranach. Zacznij więc od rozdzielenia jednostek: odległość w świecie, czas symulacji i częstotliwość prezentacji. Rysowanie pokazuje wynik obliczeń, lecz nie powinno samo określać zasad. To szczególnie ważne w grze zręcznościowej, w której odległość skoku decyduje o możliwości ukończenia poziomu.

Najprostszy ruch można uzależnić od rzeczywiście upływającego czasu, ale nie rozwiązuje to wszystkich problemów fizyki. Bardzo duży odstęp między aktualizacjami może spowodować przeskoczenie przeszkody albo niestabilną reakcję. Dlatego wybór modelu czasu powinien wynikać z mechaniki, a nie z kopiowania dowolnej pętli z przykładu. Gra turowa może reagować głównie na działania gracza, podczas gdy symulacja ruchu wymaga regularnych kroków obliczeń.

Stały krok porządkuje obliczenia świata

W modelu stałego kroku symulacja otrzymuje odcinki czasu o jednakowej długości. Pętla gromadzi upływ czasu i wykonuje tyle kroków, ile jest potrzebne do nadrobienia zaległości. Rysowanie może odbywać się z inną częstotliwością. Dzięki temu reguły ruchu nie zmieniają podstawowego kroku przy każdym drobnym wahaniu wydajności. Nie oznacza to automatycznie pełnego determinizmu między wszystkimi platformami; znaczenie mają również obliczenia, losowość i kolejność operacji.

Wybierz krok na podstawie szybkości obiektów i wymaganej dokładności, a potem sprawdź koszt. Mniejszy krok daje więcej obliczeń, nie darmową poprawę jakości. Oddziel funkcję aktualizacji świata od funkcji jego prezentacji. Ta druga nie powinna naliczać obrażeń ani przyznawać punktów. W przeciwnym razie pominięcie rysowania klatki może zmienić wynik gry. W testach warto uruchamiać samą symulację bez grafiki, aby sprawdzać reguły niezależnie od urządzenia.

Nadrabianie zaległości musi mieć granicę

Gdy obliczenie jednego kroku trwa dłużej niż odpowiadający mu czas, gra zaczyna zalegać coraz bardziej. Próba wykonania nieograniczonej liczby kroków może zablokować interfejs. Ustal limit nadrabiania i świadomą strategię przeciążenia. W małej grze jednoosobowej można ograniczyć upływ symulowanego czasu po dużej przerwie. Nie udawaj jednak, że takie rozwiązanie nadaje się bez zmian do rozgrywki współdzielącej stan z serwerem.

Zmierz najdroższe elementy aktualizacji: kolizje, decyzje przeciwników, generowanie obiektów i alokacje pamięci. Nie zmniejszaj losowo liczby kroków fizyki, zanim nie rozpoznasz przyczyny. Część zadań, na przykład odświeżenie dalekiego przeciwnika, może działać rzadziej niż ruch bohatera. Ustal ich własny harmonogram. Równe traktowanie każdej drobnej funkcji w każdej klatce bywa niepotrzebnym kosztem, który ujawnia się dopiero na słabszym telefonie.

Wejście gracza trzeba przypisać do symulacji

Wciśnięty klawisz i pojedyncze naciśnięcie to różne informacje. Ruch może korzystać ze stanu „trzymane”, lecz skok powinien zostać wykonany raz dla konkretnego zdarzenia. Jeżeli w jednej klatce obrazu wykonasz kilka kroków symulacji, nie możesz bezmyślnie powtórzyć skoku w każdym z nich. Zdefiniuj bufor zdarzeń i moment ich zużycia. Wtedy opóźnienie rysowania nie zamieni jednej akcji użytkownika w serię niezamierzonych działań.

Po utracie fokusu wyczyść stany przycisków, które mogły pozostać wciśnięte bez zdarzenia zwolnienia. Powrót do karty nie powinien powodować samoczynnego biegu bohatera. Dla pauzy ustal osobny stan aplikacji: nie wszystkie animacje menu muszą zatrzymywać się razem z fizyką. Przycisk wznowienia powinien uruchamiać jeden kontrolowany proces, a nie dodawać kolejną niezależną pętlę przy każdym kliknięciu. Podwójna pętla łatwo wygląda jak tajemnicze przyspieszenie gry.

Obraz może być płynny między krokami

Przy rozdzielonej symulacji można interpolować prezentowaną pozycję między znanymi stanami. To technika wygładzenia obrazu, nie dodatkowy krok zasad. Dane użyte do rysowania nie powinny wracać jako nowa prawda do obliczeń kolizji. W przeciwnym razie kosmetyczna poprawa wpłynie na ruch. Zapisz też wyjątki: teleportacja lub odrodzenie postaci nie powinny być animowane jak zwykłe przejście przez całą mapę pomiędzy dawną i nową pozycją.

Do planowania odrysowania w przeglądarce służy requestAnimationFrame, ale jego wywołania nie są obietnicą stałej liczby klatek. Karta w tle może działać inaczej niż aktywna. Po wznowieniu przelicz punkt odniesienia czasu zgodnie z zasadą pauzy, zamiast symulować kilka minut w jednym przebiegu. Elementy interfejsu opisujące czas rzeczywisty i zegar rozgrywki muszą być rozdzielone. To, że minęła minuta zegarowa, nie znaczy, że bohater przez minutę wykonywał zadania.

Odbiór porównuje zachowanie, nie tylko licznik FPS

Przeprowadź identyczną sekwencję wejść przy różnych limitach rysowania. Porównaj przebytą odległość, długość skoku i wynik kolizji. Dodaj sztuczne spowolnienie oraz przełącz kartę na kilkanaście sekund. Sprawdź, czy powrót nie kończy się natychmiastową przegraną. Licznik FPS może wyglądać dobrze, gdy reguły nadal zależą od renderowania. Dlatego potrzebujesz pomiaru stanu świata i zdarzeń, a nie wyłącznie płynności wizualnej.

Przygotuj również wykres czasu aktualizacji i maksymalnej liczby kroków w pojedynczym przebiegu. Średnia ukrywa sporadyczne zacięcia, które psują sterowanie. Ustal, co gra zrobi, gdy urządzenie stale nie nadąża: obniży dekoracyjną jakość, pokaże informację czy odmówi uruchomienia wymagającego trybu. Jawna granica jest lepsza niż nieprzewidywalne zasady. Dobra pętla gry zapewnia spójność ruchu i możliwość diagnozy, pozostawiając przeglądarce czas na obsługę użytkownika.

Czytaj dalej