I'm attempting to create an animation that shows a box bouncing off the edges of the screen. And, I'm attempting to accomplish this using time-based animation and dirty rectangles.
I was able to animate the box; however, the animation is pretty choppy. Here are two videos that illustrate what I'm talking about:
30 FPS: https://www.youtube.com/watch?v=0de8ENxn7GQ
60 FPS: https://www.youtube.com/watch?v=b5sXgeOlgHU
And here is my code:
import sys
import random
import pygame
class Box:
def __init__(self, x, y):
self.width = 38
self.height = 38
self.color = (255, 0, 0)
self.x = x
self.y = y
self.old_x = x
self.old_y = y
self.d_x = 1
self.d_y = -1
self.px_per_second = 200
def move(self):
self.old_x = self.x
self.old_y = self.y
if self.x <= 0:
self.d_x *= -1
if self.x + self.width >= task.width:
self.d_x *= -1
if self.y <= 0:
self.d_y *= -1
if self.y + self.height >= task.height:
self.d_y *= -1
self.x += ((self.px_per_second*self.d_x)*
(task.ms_from_last_frame/1000.0))
self.y += ((self.px_per_second*self.d_y)*
(task.ms_from_last_frame/1000.0))
def draw(self):
self.x_i = int(self.x)
self.y_i = int(self.y)
self.old_x_i = int(self.old_x)
self.old_y_i = int(self.old_y)
_old_rect = (pygame.Rect(self.old_x_i, self.old_y_i,
self.width, self.height))
_new_rect = (pygame.Rect(self.x_i, self.y_i, self.width, self.height))
if _old_rect.colliderect(_new_rect):
task.dirty_rects.append(_old_rect.union(_new_rect))
else:
task.dirty_rects.append(_old_rect)
task.dirty_rects.append(_new_rect)
pygame.draw.rect(task.screen, task.bg_color, _old_rect)
pygame.draw.rect(task.screen, (self.color), _new_rect)
class ObjectTask:
def __init__(self, width, height):
pygame.init()
self.max_fps = 60
self.clock = pygame.time.Clock()
self.width = width
self.height = height
self.bg_color = (255, 255, 255)
self.dirty_rects = []
self.screen = pygame.display.set_mode((self.width, self.height),
pygame.FULLSCREEN)
self.screen.fill(self.bg_color)
pygame.display.update()
def animation_loop(self):
self.box1 = Box(self.width/2, self.height/2)
while 1:
self.ms_from_last_frame = self.clock.tick(self.max_fps)
self.box1.move()
self.box1.draw()
pygame.display.update(self.dirty_rects)
self.dirty_rects = []
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if __name__ == "__main__":
task = ObjectTask(726, 546)
task.animation_loop()
Is there anything I can do to reduce the choppiness? Also, I'm new to Pygame, so if you see anything that I'm doing incorrectly/inefficiently, please let me know.
I'm running the animation on a 64-bit Windows 7, i5-6300u machine with 12 GB of RAM. I'm using Python 2.7.12 and Pygame 1.9.2.
Thanks in advance!