Suave em Qualquer Taxa de Quadros
Parte da seção Som e sensação de jogo do Journey de Pygame da Coddy. Lição 19 de 23.
x += (target_x - x) * 0.1 percorre um décimo do caminho por quadro. A 60 quadros por segundo, são 60 passos por segundo; em um computador lento que só consegue executar 30, são 30 passos, e o círculo leva o dobro do tempo para chegar. Pressione F para ver: o jogo roda a 30 e tudo desacelera.
A solução é medir o tempo. clock.tick() retorna os milissegundos desde o último quadro. Dividido por 1000, isso é dt, a duração do quadro em segundos: cerca de 0.017 a 60 quadros por segundo, 0.033 a 30.
dt = 1 / 60 # antes do loop
...
step = min(1, 6 * dt)
x += (target_x - x) * step
...
dt = clock.tick(fps) / 1000Um quadro mais longo dá um passo maior, então o círculo percorre a mesma distância no mesmo tempo, em qualquer taxa de quadros. O 6 define a velocidade: a 60 quadros por segundo, 6 * dt é cerca de 0.1, o mesmo décimo de antes. min(1, ...) impede que um quadro muito longo ultrapasse o alvo.
O mesmo vale para o movimento simples: player_x += 240 * dt corresponde a 240 pixels por segundo, seja qual for a taxa de quadros. A maioria dos jogos pequenos fixa a taxa com tick(60) e nunca precisa disso; use dt quando a taxa puder mudar.
Desafio
MédioF alterna o jogo entre 60 e 30 quadros por segundo. Faça a suavização levar o mesmo tempo em ambas as taxas:
- Defina
dt = 1 / 60antes do loop. - No final do loop, defina
dt = clock.tick(fps) / 1000. - Mova usando
step = min(1, 6 * dt)em vez de 0.1:x += (target_x - x) * step, e faça o mesmo paray.
Experimente você mesmo
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()
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Som e sensação de jogo
4Vibração da Tela e Flash de Impacto
Vibração da TelaFlash de ImpactoPausa no ImpactoMantenha a Discrição5Movimento Suave
Mova-se em Direção a um AlvoUma Câmera SuaveSalto ao ColetarSuave em Qualquer Taxa de QuadrosPratique por conta própria: Playground de Pygame