base2-runner: fix typos causing syntax errors
[base2-runner.git] / base2-runner.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 # 2D platform scrolling game that teaches binary logic
6
7 import sys, os, time, random, math, pygame
8 import engine, circuits
9
10 # Use conditionals in the code to print useful information to the console using the form:
11 # if self.debug: engine.debug_pr("some_var=%d, another_var=%s" % (some_var, another_var), somevalue, another_value)
12
13 class Base2Runner(object):
14  background_image = None
15  stepping = 8 # pixels scrolled each flip
16  delay = 0.01  # main loop sleep (100 milliseconds)
17  background_colour = (0, 0, 0)
18  background_image = None
19  icon_image = None
20  flags = pygame.OPENGL & pygame.DOUBLEBUF
21  depth = 0
22  screen = None # the pygame Screen for the game window
23
24  def __init__(self, width, height, title, resources={}, debug=False):
25   os.environ['SDL_VIDEO_CENTERED'] = '1' 
26   pygame.init()
27   self.debug = debug
28   self.myGame = engine.Game(width, height, title, resources, debug=self.debug)
29   if self.myGame.config['sound'] == 1:
30    self.myGame.soundtrack.playlist(self.myGame.resources['soundtrack'])
31
32   self.background_colour = (20, 20, 64)
33   if 'icon' in self.myGame.resources:
34    if self.debug: engine.debug_pr("pygame.image.get_extended()=%r" % pygame.image.get_extended())
35    self.icon_image = pygame.image.load(self.myGame.resources['icon'])
36    pygame.display.set_icon(self.icon_image)
37
38  def play(self):
39   error_code = 0
40   self.screen = pygame.display.set_mode(self.myGame.resolution, self.flags, self.depth)
41   self.screen.fill(self.background_colour)
42   pygame.display.set_caption(self.myGame.config['title'])
43   resolution = self.screen.get_size()
44
45   # background image
46   self.background_image = engine.SeamlessBackground(self.myGame.resources['background'], debug=self.debug)
47   self.background_image.draw(self.screen, -1, 0) # -1 flags initial background drawing
48   pygame.display.update()
49
50   # scrolling object
51   blip = pygame.Surface((abs(self.stepping), abs(self.stepping)), pygame.HWSURFACE)
52   blip_colour = (128, 128, 128)
53   blip.fill(blip_colour)
54
55   # starting position
56   y = resolution[1] / 2
57
58   self.myGame.config['auto_scroll'] = False
59   movement = 0 # represents number of pixels, and direction, of next scroll
60   x_pos = 0 # coordinate of left side of viewport
61
62   self.myGame.play = True # start the game
63   while (self.myGame.play):
64
65    if not self.myGame.paused:
66     # update game state
67     if x_pos + movement >= 0:
68      x_pos += movement
69     else:
70      movement = 0
71
72     # change colour randomly
73     d_red = random.randrange(-1,2) *8
74     d_green = random.randrange(-1,2) *8
75     d_blue = random.randrange(-1,2) *8
76     # build a modified colour tuple, ensuring all values are valid
77     blip_colour = tuple( b+d if b+d < 256 and b+d >=0 else b for b, d in zip(blip_colour, (d_red, d_green, d_blue)) )
78     blip.fill(blip_colour)
79
80     # change blip position up or down randomly by one step
81     dy = random.randrange(-1,2) * abs(self.stepping)
82     if((y + dy) < resolution[1] and (y + dy) >= 0):
83      # TODO: no longer need to redraw background colour if using a background image
84      # screen.fill(background_colour, pygame.Rect(resolution[0] - abs(stepping), y, abs(stepping), abs(stepping) ))
85      y += dy
86
87     # redraw the display
88     self.screen.scroll(-movement, 0)
89     self.background_image.draw(self.screen, x_pos, movement)
90     self.screen.blit(blip, (resolution[0] - abs(self.stepping), y))
91     pygame.display.update()
92    
93    # manage the frame-rate
94    time.sleep(self.delay)
95
96    # process events
97    for event in pygame.event.get():
98     if event.type == pygame.QUIT or (event.type == pygame.KEYUP and event.key == pygame.K_q):
99      self.myGame.play = False
100     if event.type ==  pygame.ACTIVEEVENT:
101      if self.debug: engine.debug_pr("active=%d, pygame.ACTIVEEVENT:" % pygame.display.get_active(), event)
102     if event.type == pygame.KEYUP:
103      k = event.key
104      if k == pygame.K_p:
105       time.sleep(10)
106      elif k == pygame.K_7:
107       self.myGame.soundtrack.pause()
108      elif k == pygame.K_l:
109       self.myGame.config['auto_scroll'] = True if self.myGame.config['auto_scroll'] == False else False
110      elif k >= pygame.K_F1 and k <= pygame.K_F12:
111       self.stepping = k - (pygame.K_F1 - 1)
112       if self.myGame.config['auto_scroll']:
113        movement = int(math.copysign(self.stepping, movement))
114       if self.debug: engine.debug_pr("Keypress=%d, movement=%d" % (k, movement))
115
116     if event.type == pygame.USEREVENT:
117      if self.debug: engine.debug_pr("pygame.USEREVENT received; calling playlist_next()")
118      self.myGame.soundtrack.playlist_next()
119
120    if not self.myGame.config['auto_scroll']:
121     # reset if not auto-scrolling
122     movement = 0
123
124    # detect which keys are held down
125    keys_pressed = pygame.key.get_pressed()
126    if sum(keys_pressed):
127     if keys_pressed[pygame.K_6]:
128      # volume down
129      self.myGame.soundtrack.volume_down()
130     elif keys_pressed[pygame.K_8]:
131      # volume up
132      self.myGame.soundtrack.volume_up()
133     elif keys_pressed[pygame.K_d]:
134      # move right
135      movement = self.stepping
136     elif keys_pressed[pygame.K_a]:
137      # move left
138      movement = -self.stepping
139
140   # end of game
141   self.myGame.soundtrack.fadeout(5000)
142   time.sleep(5)
143   pygame.display.quit()
144   return error_code
145
146
147  def main(self, args, env):
148   """ entry point for starting the game """
149   time.sleep(10) # keep splash screen up for a little longer
150   return self.play()
151
152
153 if __name__ == '__main__':
154  # define some basic resources
155  resources = {}
156  resources['path'] = 'resources'
157  resources['icon'] = 'base2runner-icon.png'
158  resources['background'] = 'binary-1024x1024.jpg'
159  resources['splash'] = 'base2runner.jpg'
160  resources['copyright'] = '© Copyright 2013 TJ <hacker@iam.tj>'
161  resources['soundtrack'] = 'Music'
162  resources['soundtrack.copyright'] = 'Rolemusic @ The Free Music Archive'
163  resources['soundtrack.license'] = 'Creative Commons Attribution Non-Commercial Share-Alike'
164  resources['soundtrack.url'] = 'http://freemusicarchive.org/music/Rolemusic/'
165
166  # instantiate the program, which will also initialise the display and show a splash screen
167  app = Base2Runner(width=900, height=600, title="Base² Runner", resources=resources, debug=True)
168  # start the program with any command-line arguments and environment and exit using any error code it returns
169  exit( app.main(sys.argv[1:], os.environ) )