From 13abc847f7fd9cd9f4187864f88aeffc3717466f Mon Sep 17 00:00:00 2001 From: James Cameron Date: Tue, 01 Oct 2013 10:43:26 +0000 Subject: optimise drawing Change to update only the parts of the screen that have been affected by drawin gin the preceeding frame. This cuts average CPU usage from 30% to 5% on OLPC XO-1.5 during the moving of the balls part of the game. --- diff --git a/main_game.py b/main_game.py index d8ad3b0..54e696d 100644 --- a/main_game.py +++ b/main_game.py @@ -50,6 +50,7 @@ class Game: Constructor. """ self._initialized = False + self.s = self.p = [] def _lazy_init(self): """ @@ -167,6 +168,19 @@ class Game: y_good = point[1] >= rect[1] and point[1] <= rect[1] + rect[3] return x_good and y_good + def _update(self): + """ + Update the screen rectangles that have been changed by drawing + actions since the last update (self.s), including rectangles + that were cleared the previous update (self.p), then clear the + current rectangles (self.s) in preparation for the next cycle. + """ + pygame.display.update(self.s + self.p) + self.p = self.s + for r in self.s: + self._screen.fill(self._GAME_BACKGROUND, r) + self.s = [] + def _play_game(self, time_seconds, operations_config): """ The main game routine time_seconds : time limit in seconds => integer @@ -175,7 +189,7 @@ class Game: OperationConfig. """ self._screen.fill(self._MENU_BACKGROUND) - pygame.display.update() + self._update() game_state = GameState.NORMAL @@ -210,13 +224,12 @@ class Game: while True: while Gtk.events_pending(): Gtk.main_iteration() - pygame.display.update() - self._screen.fill(self._GAME_BACKGROUND) - paint_result_bar(result_bar, self._screen) - paint_time_bar(time_bar, self._screen) + self._update() + self.s += paint_result_bar(result_bar, self._screen) + self.s += paint_time_bar(time_bar, self._screen) if game_state == GameState.NORMAL: for ball in the_balls: - paint_ball(ball, self._screen) + self.s += paint_ball(ball, self._screen) for event in pygame.event.get(): if event.type == QUIT: @@ -245,7 +258,7 @@ class Game: balls_collision.manage_colliding_balls(the_balls) self._clock.tick(self._FPS) else: - paint_results(balls_area, the_balls, self._screen) + self.s += paint_results(balls_area, the_balls, self._screen) # Blinks the status text. if show_status: if game_state == GameState.WON: @@ -255,7 +268,7 @@ class Game: end_txt_surface = self._end_font.render(end_txt, True, self._BLUE, self._RED) - self._screen.blit(end_txt_surface, self._END_TXT_POS) + self.s.append(self._screen.blit(end_txt_surface, self._END_TXT_POS)) for event in pygame.event.get(): if event.type == QUIT: @@ -273,25 +286,29 @@ class Game: Manages the main menu. """ self._lazy_init() + self.s = [] + self.s.append(self._screen.fill(self._MENU_BACKGROUND)) + self._update() while True: - self._screen.fill(self._MENU_BACKGROUND) + while Gtk.events_pending(): + Gtk.main_iteration() + self._update() for box_index in range(len(self._levels)): box_value = self._levels_rect[box_index] - pygame.draw.rect( + s = pygame.draw.rect( self._screen, self._MENU_LEVELS_RECTS_BG_COLOR, box_value) + self.s.append(s) txt = _("Level ") + str(box_index + 1) txt_surface = self._menu_font.render(txt, True, self._MENU_LEVELS_RECTS_TXT_COLOR) - self._screen.blit(txt_surface, + s = self._screen.blit(txt_surface, (self._levels_rect[box_index][0] + self._MENU_LEVELS_RECTS_TXT_OFFSET[0], self._levels_rect[box_index][1] + self._MENU_LEVELS_RECTS_TXT_OFFSET[1] )) - pygame.display.update() - while Gtk.events_pending(): - Gtk.main_iteration() + self.s.append(s) for event in pygame.event.get(): if event.type == QUIT: -- cgit v0.9.1