Reputation: 586
I am looking to write a better game loop in Python using pygame.time.Clock()
, and I understand the concept of keeping time and de-coupling rendering from the main game loop in order to better utilise the ticks. I also understand about passing time lag into the rendering so that it renders the correct amount of movement, but the only examples I've found are written in C# and although I first thought it fairly simple to convert to Python, it's not behaving.
I've figured out that Pygame's Clock()
already works out the milliseconds between the last 2 calls to .tick, and I've tried to adapt the sample code I found, but I really need to see a working example written in Python. Here's what I've come up with so far:
FPS = 60
MS_PER_UPDATE = 1000 / FPS
lag = 0.0
clock = pygame.time.Clock()
running = True
# Do an initial tick so the loop has 2 previous ticks.
clock.tick(FPS)
while running:
clock.tick(FPS)
lag += clock.get_time()
user_input()
while lag >= MS_PER_UPDATE:
update()
lag -= MS_PER_UPDATE
render(lag / MS_PER_UPDATE)
I'm not sure if this is all worth it in Pygame, or if it's already taken care of in some of it's time
functions already? My game runs slower on the laptop (expected) but I thought doing this might even out the FPS a bit between my main PC and laptop by de-coupling the rendering. Does anyone have experience doing these advanced game loops in Pygame? I just want it to be as good as it can be...
Upvotes: 3
Views: 3649
Reputation: 101042
Just take the time it took to render the last frame (called delta time) and pass it to your game objects so they can decide what to do (e.g. move more or less).
Here's a super simple example:
import pygame
class Actor(pygame.sprite.Sprite):
def __init__(self, *args):
super().__init__(*args)
self.image = pygame.Surface((32, 32))
self.rect = pygame.display.get_surface().get_rect()
self.image.fill(pygame.Color('dodgerblue'))
def update(self, events, dt):
self.rect.move_ip((1 * dt / 5, 2 * dt / 5))
if self.rect.x > 500: self.rect.x = 0
if self.rect.y > 500: self.rect.y = 0
def main():
pygame.init()
screen = pygame.display.set_mode((500, 500))
sprites = pygame.sprite.Group()
Actor(sprites)
clock = pygame.time.Clock()
dt = 0
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
sprites.update(events, dt)
screen.fill((30, 30, 30))
sprites.draw(screen)
pygame.display.update()
dt = clock.tick(60)
if __name__ == '__main__':
main()
If your game slows down below 60 (or whatever) FPS, dt
gets bigger, and Actor
moves more to make up for the lost time.
Upvotes: 3