Delta time: ruch niezależnie od FPS
Prędkość w "pikselach na klatkę" zależy od czyjegoś sprzętu. Prędkość w "pikselach na sekundę" pomnożona przez delta time już nie.
W mini-projekcie sekcji 20.5 piłka poruszała się tak: x += dx Każda klatka. Działa — ale tylko tak długo, jak FPS jest stałe. To podejście ma ukrytą
Problem, który prędzej czy później ujawnia się na prawdziwych urządzeniach.
Problem: ruch ograniczony klatką
Jeśli dx to „piksele na klatkę” drugi bezpośrednio zależy od tego, ile klatek faktycznie zdąży
przejść na sekundę, a nie od tego, o co prosiliście clock.tick().
clock.tick(60) z sekcji 20.5 określa jedynie góra
Limit – 60 FPS, nie więcej – ale nie można nic zrobić, jeśli urządzenie
Nie radzi sobie z tym również. Na laptopie gamingowym dewelopera gra konsekwentnie mieści wszystkie 60 FPS;
Na słabym lub przegrzanym urządzeniu (Rozdział 20.13) kod jednej klatki może nie być
a rzeczywista częstotliwość spada do, powiedzmy, 30 FPS. Z kodem "piksele na jedno"
frame" oznacza, że kula takiego gracza porusza się dwa razy wolniej niż piłka wytwórcy,
Z dokładnie tym samym kodem gra, która dobrze się czuje na tym samym urządzeniu, może
Bądź zauważalnie wolniejszy lub szybszy na innym.
Rozwiązanie: delta time
Delta time (w skrócie dt) — czas, prawdziwy
minęło od poprzedniej klatki w sekundach. clock.tick(FPS) nie
Ogranicza liczbę klatek na klatkę, ale także zwroty liczbę milisekund, które minęły od tego czasu
poprzednie wezwanie clock.tick()— czyli całkowity czas klatki,
W tym czekanie, jeśli w ogóle występuje:
clock = pygame.time.Clock()
while rabotaet:
dt_ms = clock.tick(FPS) # ile milisekund minęło od ostatniej klatki
dt = dt_ms / 1000 # przelicz na sekundy
x += skorost_x * dt #skorost_x teraz w pikselach na SEKUNDĘ, a nie na klatkę
Teraz skorost_x oznacza „piksele na sekundę”
Ważne jest, że tick() raporty dokładnie pełne czasie klatki, oraz
Nie o to, jak długo czekało. Jeśli urządzenie nie poradzi sobie, nie musi wcale czekać — i
potem tick(60) zwróci nie 16, ale, powiedzmy, 30 milisekund: dokładnie tyle, ile zajęło wykonanie klatki. Dlatego właśnie delta time ratuje na słabym urządzeniu: im wolniejsza klatka, tym więcej dt i im większy stopień.
(Osobno, czas poświęcony wyłącznie użytecznej pracy, bez oczekiwania, jest dostępny przez
clock.get_rawtime().)
clock.tick(FPS) zwraca czas w milisekund, nie w sekundy. Jeśli zapomnisz podzielić przez 1000, prędkość w kodzie zostanie przeszacowana dokładnie tysiąckrotnie — postać wylatuje z ekranu w jednej klatce. To jeden z najczęstszych błędów przy pierwszym przejściu na delta time, a objaw zawsze jest ten sam: ruch nagle staje się „teleportacją”x += v * dt oraz y += v * dt jednocześnie), a następnie faktycznie porusza się po przekątnej √2 ≈ 1,41 razy szybciej niż dokładnie jedna oś — oba składniki sumują się geometrycznie. Poprawnym rozwiązaniem jest normalizacja wektora kierunku (zmniejszenie jego długości do 1) przed pomnożeniem przez prędkość, tak aby całkowita prędkość pozostała taka sama w obu kierunkach.