Menu
CoddyTech

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) / 1000

Dł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ć.

challenge icon

Wyzwanie

Średni

F przełącza grę między 60 a 30 klatkami na sekundę. Spraw, by wygładzanie trwało tyle samo przy obu wartościach:

  1. Ustaw dt = 1 / 60 przed pętlą.
  2. Na końcu pętli ustaw dt = clock.tick(fps) / 1000.
  3. Poruszaj się, używając step = min(1, 6 * dt) zamiast 0.1: x += (target_x - x) * step, i tak samo dla y.

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()
quiz iconSprawdź się

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

Poćwicz samodzielnie: Edytor online Pygame