Rozdział 20 · Tworzenie gier z Pygame

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:

delta_time.py
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().)

Zdezorientowane milisekundy i sekundy
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ą”
Ruch diagonalny szybszy niż ruch osiowy
Jeśli postać porusza się zarówno X, jak i Y z pełną prędkością i obiema prędkościami (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.
Praktyka: ruch niezależny od FPS
Zeskanowanie bezpośrednio w przeglądarce – nie wymaga instalacji Pygame
Otwórz praktykę →