Une animation fluide à toute fréquence d’images
Fait partie de la section Son et sensations de jeu du Journey Pygame de Coddy. Leçon 19 sur 23.
x += (target_x - x) * 0.1 parcourt un dixième du chemin à chaque image. À 60 images par seconde, cela fait 60 étapes par seconde ; sur un ordinateur lent qui n’en affiche que 30, il n’y en a que 30, et le cercle met deux fois plus de temps à arriver. Appuie sur F pour le voir : le jeu tourne à 30 images par seconde et tout ralentit.
La solution consiste à mesurer le temps. clock.tick() renvoie le nombre de millisecondes écoulées depuis la dernière image. Divisé par 1000, cela donne dt, la durée de l’image en secondes : environ 0.017 à 60 images par seconde, 0.033 à 30.
dt = 1 / 60 # avant la boucle
...
step = min(1, 6 * dt)
x += (target_x - x) * step
...
dt = clock.tick(fps) / 1000Une image plus longue entraîne un déplacement plus important, de sorte que le cercle parcourt la même distance dans le même temps, quel que soit le nombre d’images par seconde. Le 6 définit la vitesse : à 60 images par seconde, 6 * dt vaut environ 0.1, soit le même dixième qu’avant. min(1, ...) empêche une image très longue de faire dépasser la cible.
Il en va de même pour un déplacement simple : player_x += 240 * dt correspond à 240 pixels par seconde, quel que soit le nombre d’images par seconde. La plupart des petits jeux fixent leur fréquence avec tick(60) et n’ont jamais besoin de cela ; utilise dt lorsque la fréquence peut varier.
Défi
MoyenLa touche F fait passer le jeu de 60 à 30 images par seconde. Fais en sorte que l’interpolation prenne le même temps dans les deux cas :
- Définis
dt = 1 / 60avant la boucle. - À la fin de la boucle, définis
dt = clock.tick(fps) / 1000. - Déplace-toi avec
step = min(1, 6 * dt)au lieu de 0.1 :x += (target_x - x) * step, et fais de même poury.
Essayez vous-même
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()
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Son et sensations de jeu
4Tremblement de l’écran et flash d’impact
Tremblement de l’écranFlash d’impactArrêt sur impactRester subtil5Mouvement fluide
Se déplacer vers une cibleUne caméra fluideSauter lors du ramassageUne animation fluide à toute fréquence d’imagesEntraînez-vous par vous-même : Playground Pygame