Płynność przy dowolnej liczbie klatek na sekundę
Część sekcji Dźwięk i odczucia z gry ścieżki Pygame w Coddy. Lekcja 19 z 23.
x += (target_x - x) * 0.1 pokonuje jedną dziesiątą drogi w każdej klatce. Przy 60 klatkach na sekundę oznacza to 60 kroków na sekundę; na wolnym komputerze, który osiąga tylko 30 klatek, jest to 30 kroków, a okrąg potrzebuje dwa razy więcej czasu, aby dotrzeć na miejsce. Naciśnij F, aby to zobaczyć: gra działa z prędkością 30 klatek na sekundę i wszystko porusza się wolniej.
Rozwiązaniem jest mierzenie czasu. clock.tick() zwraca liczbę milisekund od poprzedniej klatki. Po podzieleniu przez 1000 otrzymujemy dt, czyli długość klatki w sekundach: około 0.017 przy 60 klatkach na sekundę i 0.033 przy 30.
dt = 1 / 60 # przed pętlą
...
step = min(1, 6 * dt)
x += (target_x - x) * step
...
dt = clock.tick(fps) / 1000Dłuższa klatka oznacza większy krok, więc okrąg pokonuje tę samą odległość w tym samym czasie przy dowolnej liczbie klatek na sekundę. Wartość 6 określa prędkość: przy 60 klatkach na sekundę 6 * dt wynosi około 0.1, czyli tyle samo co poprzednio. min(1, ...) zapobiega przeskoczeniu celu przy bardzo długiej klatce.
To samo dotyczy zwykłego ruchu: player_x += 240 * dt oznacza 240 pikseli na sekundę, niezależnie od liczby klatek na sekundę. Większość małych gier ustala stałą liczbę klatek za pomocą tick(60) i nigdy tego nie potrzebuje; używaj dt, gdy liczba klatek może się zmieniać.
Wyzwanie
ŚredniF przełącza grę między 60 a 30 klatkami na sekundę. Spraw, by wygładzanie trwało tyle samo przy obu wartościach:
- Ustaw
dt = 1 / 60przed pętlą. - Na końcu pętli ustaw
dt = clock.tick(fps) / 1000. - Poruszaj się, używając
step = min(1, 6 * dt)zamiast 0.1:x += (target_x - x) * step, i tak samo dlay.
Spróbuj swoich sił
import pygame
pygame.init()
screen = pygame.display.set_mode((480, 360))
pygame.display.set_caption("Any Frame Rate")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 28)
x, y = 240, 180
target_x, target_y = 240, 180
fps = 60
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
target_x, target_y = event.pos
elif event.type == pygame.KEYDOWN and event.key == pygame.K_f:
fps = 30 if fps == 60 else 60
x += (target_x - x) * 0.1
y += (target_y - y) * 0.1
screen.fill((30, 30, 46))
pygame.draw.circle(screen, (80, 200, 220), (x, y), 12)
label = font.render(f"{fps} FPS (F to change)", True, (240, 240, 240))
screen.blit(label, (10, 10))
pygame.display.flip()
clock.tick(fps)
pygame.quit()
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Dźwięk i odczucia z gry
1Efekty dźwiękowe
Wczytywanie dźwiękuDźwięk w reakcji na zdarzenieGłośność dźwiękuDźwięki i przytrzymane klawisze4Wstrząs ekranu i błysk po trafieniu
Wstrząs ekranuBłysk po trafieniuPauza przy trafieniuNie przesadzaj5Płynny ruch
Poruszanie się w kierunku celuPłynna kameraEfekt „pop” przy zebraniuPłynność przy dowolnej liczbie klatek na sekundęPoćwicz samodzielnie: Edytor online Pygame