Bei jeder Bildrate flüssig
Teil des Abschnitts Sound und Spielgefühl der Pygame-Journey von Coddy. Lektion 19 von 23.
x += (target_x - x) * 0.1 bewegt sich pro Frame ein Zehntel der Strecke. Bei 60 Frames pro Sekunde sind das 60 Schritte pro Sekunde; auf einem langsamen Computer, der nur 30 schafft, sind es 30 Schritte, und der Kreis braucht doppelt so lange, bis er ankommt. Drücke F, um es zu sehen: Das Spiel läuft mit 30, und alles bewegt sich langsamer zum Ziel.
Die Lösung besteht darin, die Zeit zu messen. clock.tick() gibt die Millisekunden seit dem letzten Frame zurück. Durch 1000 geteilt ergibt das dt, die Länge des Frames in Sekunden: etwa 0.017 bei 60 Frames pro Sekunde, 0.033 bei 30.
dt = 1 / 60 # vor der Schleife
...
step = min(1, 6 * dt)
x += (target_x - x) * step
...
dt = clock.tick(fps) / 1000Ein längerer Frame bedeutet einen größeren Schritt, sodass der Kreis bei jeder Bildrate in derselben Zeit dieselbe Strecke zurücklegt. Die 6 legt die Geschwindigkeit fest: Bei 60 Frames pro Sekunde ist 6 * dt etwa 0.1, dasselbe Zehntel wie zuvor. min(1, ...) verhindert, dass ein sehr langer Frame über das Ziel hinausschießt.
Dasselbe gilt für einfache Bewegungen: player_x += 240 * dt ergibt bei jeder Bildrate 240 Pixel pro Sekunde. Die meisten kleinen Spiele legen ihre Bildrate mit tick(60) fest und brauchen das nie; verwende dt, wenn sich die Bildrate ändern kann.
Aufgabe
MittelMit F wechselst du im Spiel zwischen 60 und 30 Bildern pro Sekunde. Sorge dafür, dass die Beschleunigung bei beiden Bildraten gleich lange dauert:
- Setze vor der Schleife
dt = 1 / 60. - Setze am Ende der Schleife
dt = clock.tick(fps) / 1000. - Bewege dich mit
step = min(1, 6 * dt)statt mit 0.1:x += (target_x - x) * stepund genauso füry.
Probier es selbst
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()
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Sound und Spielgefühl
5Flüssige Bewegung
Auf ein Ziel zubewegenEine flüssige KamerabewegungBeim Aufsammeln aufspringenBei jeder Bildrate flüssigÜbe selbstständig: Pygame-Playground