Quick answer: Pass vsync=1 to pygame.display.set_mode((W, H), vsync=1). Then display.flip() blocks until the next vsync. Use clock.tick(0) or skip the tick cap.
Frame rate hits 1000 fps even with Clock.tick(60). Tick caps at 60 but doesn’t align with the monitor; you get tearing. vsync=1 fixes both.
The Symptom
Visible screen tearing or frame rate exceeding monitor refresh. Clock.tick alone doesn’t prevent.
The Fix
import pygame
pygame.init()
screen = pygame.display.set_mode(
(1920, 1080),
pygame.SCALED | pygame.RESIZABLE,
vsync=1
)
clock = pygame.time.Clock()
while running:
# draw
pygame.display.flip() # blocks until vsync
clock.tick(0) # no extra cap
Vsync handles timing. Clock.tick(0) yields delta time without capping.
Verifying
Frame rate matches monitor refresh (60, 120, 144). No tearing. Without vsync: tearing or uncapped fps.
“vsync=1. flip blocks. Clock.tick(0).”
Related Issues
For Clock.tick busy loop, see tick CPU. For window icon, see window icon.
Vsync. Refresh-locked. No tearing.