Simple Pygame Animation Stuttering
I have a simple bouncing box window that was drawn with 'Pygame'. Everything seems to work properly, except for a little annoyance. It stutters constantly! I have no idea what coul
Solution 1:
This is a rewrite of your code that uses opengl instead for the rendering. The major changes are as follows:
- I used opengl immediate mode, which is out-of-date and deprecated, but is a lot easier to understand at first. Most of the gl calls are either in the player.draw() method or in the main loop.
I fixed the way the timer is done. Rather than doing just clock.tick(fps), I manually keep track of the amount of time that it takes to do all of the processing to the frame and add the appropriate millisecond delay to reach 60 fps. You can try that modification with your existing pygame code before migrating to opengl as that might be sufficient to remove most of the stutter.
import pygame import time from OpenGL.GL import * classPlayer: def__init__(self, screen, width, height, color): self.x = 0 self.y = 0 self.speed = 3 self.direction_x = 1 self.direction_y = 1 self.screen = screen self.width = width self.height = height self.color = color defset_pos(self, x, y): self.x = x self.y = y defadvance_pos(self): screen_width, screen_height = screen.get_size() if self.x + self.width > screen_width or self.x < 0: self.direction_x *= -1 self.speed = 3elif self.y + self.height > screen_height or self.y < 0: self.direction_y *= -1 self.speed = 3else: self.speed -= 0.001 self.x += self.speed * self.direction_x self.y += self.speed * self.direction_y defdraw(self): glMatrixMode(GL_MODELVIEW) glLoadIdentity() glTranslate(self.x, self.y, 0) glBegin(GL_QUADS) glColor(*self.color) glVertex(0, 0, 0) glVertex(self.width, 0, 0) glVertex(self.width, self.height, 0) glVertex(0, self.height, 0) glEnd() if __name__ == "__main__": pygame.init() size = width, height = (550, 400) screen = pygame.display.set_mode(size, pygame.RESIZABLE | pygame.DOUBLEBUF | pygame.OPENGL) fps = 60 black = (0,0,0,255) white = (255,255,255,255) player1 = Player(screen, 50, 50, white) player1.set_pos(50,50) done = False previous = time.time() * 1000 glClearColor(*black) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0, width, height, 0, -1, 1) clock = pygame.time.Clock() whilenot done: current = time.time() * 1000 elapsed = current - previous previous = current delay = 1000.0/fps - elapsed delay = max(int(delay), 0) for event in pygame.event.get(): if event.type == pygame.QUIT: done = Truebreakif event.type == pygame.VIDEORESIZE: size = width, height = event.w, event.h screen = pygame.display.set_mode(size, pygame.RESIZABLE | pygame.DOUBLEBUF | pygame.OPENGL) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0, width, height, 0, -1, 1) glViewport(0, 0, width, height) #reset player movement and position to avoid glitches where player is trapped outside new window borders player1.set_pos(50, 50) player1.direction_x = 1 player1.direction_y = 1 player1.advance_pos() glClear(GL_COLOR_BUFFER_BIT) glClear(GL_DEPTH_BUFFER_BIT) player1.draw() pygame.display.flip() pygame.time.delay(delay)
Solution 2:
I created a clock object befor entering the "while not done" loop and had no more lags
#--- initialize pygame window ---#import pygame
import time
pygame.init()
size = (1200,500)
screen = pygame.display.set_mode(size, pygame.RESIZABLE)
fps = 60#--- define color palette ---#
black = (0,0,0)
white = (255,255,255)
#--- define the player ---#classplayer:
def__init__(self,screen,surface, color):
self.speed = 3
self.direction_x = 1
self.direction_y = 1
self.screen = screen
self.surface = surface
self.rect = self.surface.get_rect()
self.color = color
defset_pos(self, x,y):
self.rect.x = x
self.rect.y = y
defadvance_pos(self):
screen_width, screen_height = screen.get_size()
if self.rect.x + self.rect.width > screen_width or player1.rect.x < 0:
player1.direction_x *= -1
player1.speed = 3elif player1.rect.y + player1.rect.height > screen_height or player1.rect.y < 0:
player1.direction_y *= -1
player1.speed = 3else:
player1.speed -= 0.001
self.rect.x += self.speed * self.direction_x
self.rect.y += self.speed * self.direction_y
defdraw(self):
pygame.draw.rect(self.surface, self.color, [0,0,self.rect.width,self.rect.height])
defblit(self):
screen.blit(self.surface, self.rect)
player1 = player(screen, pygame.Surface((50,50)), white)
player1.set_pos(50,50)
player1.draw()
#--- define game variables ---#
previous = time.time() * 1000
lag = 0.0
background = black
done = False
clock=pygame.time.Clock()
#--- game ---#whilenot done:
#--- update time step ---#
current = time.time() * 1000
elapsed = current - previous
lag += elapsed
previous = current
#--- process events ---#for event in pygame.event.get():
if event.type == pygame.QUIT:
done = Truebreakif event.type == pygame.VIDEORESIZE:
screen = pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE)
#--- update logic ---#whileTrue:
player1.advance_pos()
lag -= fps
if lag <= fps:
break#--- draw to screen ---#
screen.fill(background)
player1.blit()
pygame.display.update()
clock.tick(fps)
pygame.quit()
Post a Comment for "Simple Pygame Animation Stuttering"