engine: convert to 'new style' classes
[base2-runner.git] / engine / SeamlessBackground.py
1 #!/usr/bin/python3
2 # (c) Copyright 2013 TJ <hacker@iam.tj>
3 # Licensed on the terms of the GNU General Public License version 3 (see COPYING)
4 #
5 # Game engine: scrolling seamless background image manager
6
7 import os, time, pygame, engine
8
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.
12
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.
16
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.
19  """
20  image_path = None
21  image = None
22  width = None
23
24  def __init__(self, filename, debug=False):
25   """ Constructor.
26    filename:  absolute or relative path to seamless background image file (JPeG, PNG, etc.)
27   """
28   self.debug = debug
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]
33
34   if self.image == None:
35    print("Error: failed to load image", filename)
36
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)
42   """
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)
47    if step > 0:
48     x_pos += resolution[0] - step
49    elif step < 0:
50     x_pos -= step
51    elif step == 0 and x_pos >= 0:
52     # nothing to do if not drawing the initial background
53     return
54
55    # calculate the offset into the background image such that the scrolled
56    # game window and the background image will match
57
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
64    # to the game window
65    patch = pygame.Surface((bk_rect.width, bk_rect.height))
66    patch.blit(self.image, (0, 0), bk_rect)
67
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]))
72
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
75
76    screen.blit(patch, (scr_x_dest, 0))
77   else:
78    print("Warning: SeamlessBackground: No image to draw")
79