2 # (c) Copyright 2013 TJ <hacker@iam.tj>
3 # Licensed on the terms of the GNU General Public License version 3 (see COPYING)
5 # Game engine: scrolling seamless background image manager
7 import os, time, pygame, engine
9 class SeamlessBackground(object):
10 """ The game window has a scrolling background image that is seamless, which allows it to be tiled
11 so that as the viewport scrolls the image appears to be continuous in both directions.
13 The game window only scrolls left or right, which means that the background needs to be redrawn
14 at the left or right margins (depending on direction of scroll) or, as a one-off, the entire
15 background image needs drawing at the beginning of the game.
17 The seamless background image provided should be larger (wider) than the intended game window to
18 allow the wrapping of the image to work correctly.
24 def __init__(self, filename, debug=False):
26 filename: absolute or relative path to seamless background image file (JPeG, PNG, etc.)
29 if os.path.exists(filename):
30 self.image_path = filename
31 self.image = pygame.image.load(self.image_path).convert()
32 self.width = self.image.get_size()[0]
34 if self.image == None:
35 print("Error: failed to load image", filename)
37 def draw(self, screen, x_pos, step):
38 """ Redraw damaged areas of the game screen.
39 x_pos: -1 == request the full screen be painted, not just the damaged left/right margins. Otherwise,
40 it is the current game-level's left-edge x coordinate.
41 step: the number of pixels, and direction, the screen has just scrolled (negative, 0, or positive)
43 if self.image != None:
44 # resolution[0] = width, [1] = height
45 resolution = screen.get_size()
46 # adjust x_pos to be x coord of damaged rectangle (left or right side of screen)
48 x_pos += resolution[0] - step
51 elif step == 0 and x_pos >= 0:
52 # nothing to do if not drawing the initial background
55 # calculate the offset into the background image such that the scrolled
56 # game window and the background image will match
58 # if drawing the background for the first time (x_pos==-1) use the entire image
59 # use modulo to get the offset within the image of the first damaged column
60 bk_x_start = x_pos % self.width if x_pos != -1 else 0
61 bk_rect = pygame.Rect(bk_x_start, 0, resolution[0] if x_pos == -1 else abs(step), resolution[1])
62 # When the image wraps there might not be 'step' columns of pixels available from the right side of
63 # the seamless image. Therefore use an intermediate 'patch' image to build the complete image to be drawn
65 patch = pygame.Surface((bk_rect.width, bk_rect.height))
66 patch.blit(self.image, (0, 0), bk_rect)
68 remainder = self.width - bk_x_start
69 if remainder < abs(step):
70 # need more pixel columns because the seamless image just wrapped around
71 patch.blit(self.image, (4,0), pygame.Rect(0, 0, remainder, resolution[1]))
73 # calculate the left coord in the game window where the new background should be drawn
74 scr_x_dest = resolution[0] - step if step > 0 else 0
76 screen.blit(patch, (scr_x_dest, 0))
78 print("Warning: SeamlessBackground: No image to draw")