Advertisement
Guest User

mars0

a guest
Apr 20th, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.43 KB | None | 0 0
  1. import math
  2. from time import clock
  3. from random import uniform, randint, choice
  4.  
  5. import pygame
  6.  
  7.  
  8. def init():
  9. pygame.init()
  10. pygame.font.init()
  11.  
  12.  
  13. class MarsLander:
  14. def __init__(self, fps=30, width=1200, height=750):
  15. self.screen = pygame.display.set_mode((width, height))
  16. self.clock = pygame.time.Clock()
  17. self.FPS = fps
  18. self.regular_font = pygame.font.SysFont('Comic Sans MS', 15)
  19. self.alert_font = pygame.font.SysFont('Comic Sans MS', 18)
  20. self.large_font = pygame.font.SysFont('Comic Sans MS', 50)
  21.  
  22. self.score = 0
  23. self.lives = 3
  24.  
  25. self.obstacles = pygame.sprite.Group()
  26. self.meteors = pygame.sprite.Group()
  27. self.landing_pads = pygame.sprite.Group()
  28. self.background = Sprite('mars_background_instr.png', 0, 0)
  29.  
  30. self.lander = Lander(width)
  31. self.height = height
  32.  
  33. # Create sprites for landing pads and add them to the pads group
  34. # TODO have coordinates dependent on actual width and height
  35. Sprite('pad.png', 732, randint(858, 1042)).add(self.landing_pads)
  36. Sprite('pad_tall.png', 620, randint(458, 700)).add(self.landing_pads)
  37. Sprite('pad.png', 650, randint(0, 300)).add(self.landing_pads)
  38.  
  39. self.reset_obstacles()
  40. self.create_new_storm()
  41. self.create_new_alert()
  42.  
  43. @property
  44. def game_over(self):
  45. return self.lives < 1
  46.  
  47. def reset_obstacles(self):
  48. """Create obstacles at a fixed location and add the to the obstacles group"""
  49. # TODO have coordinates dependent on actual width and height
  50.  
  51. self.obstacles.empty()
  52. Sprite('pipe_ramp_NE.png', 540, 90).add(self.obstacles)
  53. Sprite('building_dome.png', 575, 420).add(self.obstacles)
  54. Sprite('satellite_SW.png', 435, 1150).add(self.obstacles)
  55. Sprite('rocks_ore_SW.png', 620, 1080).add(self.obstacles)
  56. Sprite('building_station_SW.png', 640, 850).add(self.obstacles)
  57.  
  58. def create_new_storm(self, number_of_images=4):
  59. """Create meteors and add them to the meteors group"""
  60. # TODO have coordinates dependent on actual width and height
  61.  
  62. now = int(clock())
  63. self.random_storm = randint(now + 3, now + 12)
  64.  
  65. self.meteors.empty()
  66. for i in range(randint(5, 10)):
  67. image_name = 'spaceMeteors_{}.png'.format(randint(1, number_of_images))
  68. Meteor(image_name, -2 * i * self.FPS, randint(300, 900)).add(self.meteors)
  69.  
  70. def create_new_alert(self):
  71. self.random_alert = randint(int(clock() + 5), int(clock() + 15))
  72. self.alert_key = choice((pygame.K_SPACE, pygame.K_LEFT, pygame.K_RIGHT))
  73.  
  74. def draw_text(self, message, position, color=(255, 0, 0)):
  75. text = self.regular_font.render(message, False, color)
  76. self.screen.blit(text, position)
  77.  
  78. def run(self):
  79. meteor_storm = False # Set to True whenever a storm should occur
  80. while not self.game_over:
  81. self.clock.tick(self.FPS)
  82.  
  83. # If the user clicks the 'X' button on the window it quits the program
  84. if any(event.type == pygame.QUIT for event in pygame.event.get()):
  85. return
  86.  
  87. self.screen.fill([255, 255, 255]) # Fill the empty spaces with white color
  88. self.screen.blit(self.background.image, self.background.rect) # Place the background image
  89. self.landing_pads.draw(self.screen)
  90. self.obstacles.draw(self.screen)
  91.  
  92. # Check for collisions with obstacles and remove hit ones
  93. obstacles_hit = pygame.sprite.spritecollide(self.lander, self.obstacles, True)
  94. self.lander.damage += 10 * len(obstacles_hit)
  95.  
  96. pressed_key = pygame.key.get_pressed() # Take pressed key value
  97.  
  98. if not meteor_storm and clock() > self.random_storm:
  99. # As soon as the clock passes the random storm time it causes meteor rain
  100. meteor_storm = True
  101.  
  102. if meteor_storm:
  103. self.meteors.update()
  104. self.meteors.draw(self.screen)
  105.  
  106. # Check for collisions with meteors and remove hit ones
  107. meteors_hit = pygame.sprite.spritecollide(self.lander, self.meteors, True)
  108. self.lander.damage += 25 * len(meteors_hit)
  109.  
  110. if pressed_key[pygame.K_ESCAPE]: # Stop game if the 'Esc' button is pressed
  111. return
  112.  
  113. if self.random_alert < clock() < self.random_alert + 2:
  114. alert_msg = self.alert_font.render('ALERT', False, (0, 0, 255))
  115. self.screen.blit(alert_msg, (190, 80))
  116. thrust = self.lander.handle_inputs(pressed_key, self.alert_key)
  117. else:
  118. thrust = self.lander.handle_inputs(pressed_key)
  119. if thrust:
  120. self.screen.blit(thrust.rot_image, thrust.rect)
  121. self.screen.blit(self.lander.rot_image, self.lander.rect)
  122.  
  123. self.draw_text('{:.1f} s'.format(clock()), (72, 10))
  124. self.draw_text('{:.1f} m/s'.format(self.lander.veloc_y), (280, 56))
  125. self.draw_text('{:.1f} m/s'.format(self.lander.veloc_x), (280, 33))
  126. self.draw_text('{:d} kg'.format(self.lander.fuel), (72, 33))
  127. self.draw_text('{:.0f} m'.format(self.lander.altitude), (280, 10))
  128. self.draw_text('{} %'.format(self.lander.damage), (95, 56))
  129. self.draw_text('{:.0f} pts'.format(self.score), (77, 82))
  130.  
  131. self.lander.free_fall()
  132. pygame.display.update()
  133.  
  134. landing_pad_reached = pygame.sprite.spritecollideany(self.lander, self.landing_pads)
  135. if landing_pad_reached or self.lander.rect.bottom > self.height:
  136. self.create_new_alert()
  137. self.create_new_storm()
  138. self.reset_obstacles()
  139. meteor_storm = False
  140. if landing_pad_reached and self.lander.rect.right < landing_pad_reached.rect.right and \
  141. self.lander.rect.left > landing_pad_reached.rect.left and self.lander.has_landing_position():
  142. self.score += 50
  143. else:
  144. self.lives -= 1
  145. should_exit = self.show_crash()
  146. if should_exit:
  147. return
  148. self.lander.reset_stats()
  149.  
  150. def show_crash(self):
  151. """Display crash message in the middle of the screen and wait for a key press"""
  152. crash_msg = self.large_font.render('You Have Crashed!', False, (255, 0, 0))
  153. self.screen.blit(crash_msg, (420, 300))
  154.  
  155. while True:
  156. for event in pygame.event.get():
  157. if event.type == pygame.QUIT:
  158. # Quit the game if the 'X' button is clicked
  159. return True
  160. if event.type == pygame.KEYDOWN:
  161. # Wait for a key to be pressed and if so resumes the game
  162. return False
  163.  
  164. pygame.display.update()
  165. self.clock.tick(self.FPS)
  166.  
  167.  
  168. class Sprite(pygame.sprite.Sprite):
  169. def __init__(self, image_file, top, left):
  170. super().__init__()
  171. self.image = pygame.image.load(image_file)
  172. self.rect = self.image.get_rect()
  173. self.rect.top = top
  174. self.rect.left = left
  175.  
  176.  
  177. class EngineThrust(Sprite): # class for the thrust image
  178. def __init__(self, lander_rect, lander_angle):
  179. super().__init__('thrust.png', lander_rect.bottom - 10, lander_rect.left + 31)
  180. self.rot_image = pygame.transform.rotate(self.image, lander_angle)
  181.  
  182.  
  183. class Meteor(Sprite):
  184. def __init__(self, image_file, top, left):
  185. super().__init__(image_file, top, left)
  186. self.speed_y = uniform(5, 10)
  187. self.speed_x = uniform(-2, 2)
  188.  
  189. def update(self):
  190. self.rect.x += self.speed_x
  191. self.rect.y += self.speed_y
  192.  
  193.  
  194. class Lander(Sprite):
  195. def __init__(self, width):
  196. super().__init__('lander.png', 0, 0)
  197. self.width = width
  198. self.veloc_y = uniform(0.0, 1.0)
  199. self.veloc_x = uniform(-1.0, 1.0)
  200. self.fuel = 500
  201. self.angle = 0
  202. self.damage = 0
  203. self.rot_image = self.image
  204. self.reset_stats()
  205.  
  206. def reset_stats(self):
  207. self.rect.top = 0
  208. self.rect.left = randint(0, self.width - self.rect.width)
  209. self.veloc_y = uniform(0.0, 1.0)
  210. self.veloc_x = uniform(-1.0, 1.0)
  211. self.fuel = 500
  212. self.angle = 0
  213. self.damage = 0
  214. self.rot_image = self.image
  215.  
  216. def free_fall(self):
  217. self.rect.y += self.veloc_y
  218. self.rect.x += self.veloc_x
  219. self.veloc_y += 0.1
  220.  
  221. if self.rect.top < 0:
  222. self.rect.top = 0
  223. self.veloc_y = uniform(0.0, 1.0)
  224.  
  225. if self.rect.right < 0:
  226. self.rect.left = self.width
  227.  
  228. if self.rect.left > self.width:
  229. self.rect.right = 0
  230.  
  231. def start_engine(self):
  232. self.fuel -= 5
  233. self.veloc_x = self.veloc_x + 0.33 * math.sin(math.radians(-self.angle))
  234. self.veloc_y = self.veloc_y - 0.33 * math.cos(math.radians(self.angle))
  235.  
  236. @property
  237. def altitude(self):
  238. return 1000 - self.rect.top * 1.436
  239.  
  240. @property
  241. def can_land(self):
  242. return self.fuel > 0 and self.damage < 100
  243.  
  244. def has_landing_position(self):
  245. return self.can_land and (self.veloc_y < 5) and (-5 < self.veloc_x < 5) and (-7 <= self.angle <= 7)
  246.  
  247. def handle_inputs(self, pressed_key, alert_key=None):
  248. if not self.can_land:
  249. return
  250. print(self.angle)
  251. thrust = None
  252. rotated = False
  253. if alert_key != pygame.K_SPACE and pressed_key[pygame.K_SPACE]:
  254. # Show thrust image when 'space' is pressed
  255. thrust = EngineThrust(self.rect, self.angle)
  256. self.start_engine()
  257.  
  258. if alert_key != pygame.K_LEFT and pressed_key[pygame.K_LEFT]:
  259. # Rotate lander anticlockwise when 'left' is pressed
  260. self.angle += 1
  261. rotated = True
  262.  
  263. if alert_key != pygame.K_RIGHT and pressed_key[pygame.K_RIGHT]:
  264. # Rotate lander clockwise when 'left' is pressed
  265. self.angle -= 1
  266. rotated = True
  267.  
  268. if rotated:
  269. self.rot_image = pygame.transform.rotate(self.image, self.angle)
  270.  
  271. return thrust
  272.  
  273.  
  274. if _name_ == '_main_':
  275. init()
  276. game = MarsLander()
  277. game run
  278. pygame.quit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement