Beispiel #1
0
class Game:
	def __init__(self):
		# pygame initializations
		pygame.init()
		self.screen = pygame.display.set_mode(s.SCREEN_SIZE)
		pygame.display.set_caption('Blasteroids')
		self.clock = pygame.time.Clock()
		self.volume = .1
		Sounds.set_se_volume(self.volume)
		self.wave_font = pygame.font.SysFont('arialblack', 35)
		self.score_font = pygame.font.SysFont('arialblack', 17)

		# background and cursor surfaces
		self.surfaces = {'background': pygame.image.load('assets/background.png').convert(),
		                 'cursor': pygame.image.load('assets/cursor.png').convert_alpha(),
		                 'tower': pygame.image.load('assets/tower.png').convert_alpha(),
		                 'hp_outline': pygame.image.load('assets/health_bar_outline.png').convert_alpha()}

		# game's main variables
		self.health = 100
		self.inv = Inventory()
		self.current_weapon = self.inv.armory['cannon']
		self.wave = Wave()
		self.score = 0

		self.firing = False
		self.auto_fire = False

	def play(self):
		# Show title splash screen, start main game loop once title is closed
		title_splash = TitleScreen(self.screen)
		title_splash.play_screen()
		Sounds.play_music(Sounds.MAIN_MUSIC)
		# main loop
		while 1:
			for event in pygame.event.get():
				if event.type == pygame.QUIT:
					pygame.quit()
					quit()
				# Shoot stuff (toggle auto-fire):
				elif event.type == pygame.MOUSEBUTTONDOWN:
					self.firing = True
				elif event.type == pygame.MOUSEBUTTONUP:
					self.firing = False
				# Keyboard press events:
				elif event.type is pygame.KEYDOWN:
					if event.key == pygame.K_ESCAPE:
						pygame.quit()
						quit()
					# Toggle full screen with 'f' key:
					elif event.key == pygame.K_f:
						self._toggle_full_screen()
					# Toggle sound effects with ''n' key:
					elif event.key == pygame.K_n:
						if Sounds.get_se_volume() == 0:
							Sounds.set_se_volume(self.volume)
						else:
							Sounds.set_se_volume(0)
					# Toggle music with 'm' key:
					elif event.key == pygame.K_m:
						if Sounds.get_music_volume() == 0:
							Sounds.set_music_volume(self.volume)
						else:
							Sounds.set_music_volume(0)
					# Toggle auto fire with 'r' key:
					elif event.key == pygame.K_r:
						if not self.auto_fire:
							self.auto_fire = True
						else:
							self.auto_fire = False
					# Switch weapons with '1' or '2' keys:
					elif event.key == pygame.K_1:
						self.switch_weapons('cannon')
					elif event.key == pygame.K_2:
						self.switch_weapons('laser gun')

			# check for game over instance
			if self.health <= 0:
				Sounds.stop_music()
				pygame.mouse.set_visible(True)
				go = GameOverScreen(self.screen)
				go.play_screen()
				self._reset()

			# enable rapid fire when holding down the mouse:
			if self.firing or self.auto_fire:
				self.current_weapon.fire(pygame.mouse.get_pos())

			# blit most background images and update their positions
			self.display_and_update()

			# collision handlers
			self.collision_handler()
			self.remove_excess_sprites()
			self.check_damage_dealt()
			self.blit_health()

			# wave mechanics
			if self.wave.is_wave_intermission():
				# if new wave just started (5 seconds ago or less), just show wave text:
				self.blit_wave_text()
			elif not self.wave.wave_is_over():
				# wave ongoing, add asteroids:
				self.wave.add_asteroids()
			else:   # wave ended, start new wave
				self.wave.start_new_wave()

			pygame.display.update()
			self.clock.tick(s.FPS)

	def switch_weapons(self, new_weapon):
		if self.current_weapon != self.inv.armory[new_weapon]:
			self.inv.armory[new_weapon].projectile_group.add(
				self.current_weapon.projectile_group
			)
			self.current_weapon.projectile_group.empty()
			self.current_weapon = self.inv.armory[new_weapon]

	# blit backgrounds, projectiles, asteroids, score
	# update asteroid and projectile positions
	def display_and_update(self):
		self.screen.blit(self.surfaces['background'], (0, 0))
		self.blit_projectiles()
		self.screen.blit(self.surfaces['tower'], s.TOWER_POS)
		self.blit_asteroids()
		score_text = self.score_font.render(str(self.score), 1, s.WHITE)
		self.screen.blit(score_text, s.SCORE_TEXT_POS)

		# display cross hair as mouse cursor
		x, y = pygame.mouse.get_pos()
		self.screen.blit(self.surfaces['cursor'], (x - 9, y - 9))

	def collision_handler(self):
		for shot in self.current_weapon.projectile_group:
			for asteroid in self.wave.asteroid_group:
				# upon collision, destroy projectile and subtract asteroid health
				if pygame.sprite.collide_mask(shot, asteroid):
					self.current_weapon.projectile_group.remove(shot)
					asteroid.health -= self.current_weapon.damage
					if asteroid.health <= 0:    # destroy asteroid
						if asteroid.type == 'large':
							self.wave.asteroid_group.add(asteroid.spawn_children())
						self.score += asteroid.score
						self.wave.asteroid_group.remove(asteroid)
						Sounds.EXPLOSION.play()
					return

	def remove_excess_sprites(self):
		# remove projectiles falling outside of screen
		for p in self.current_weapon.projectile_group:
			if (p.position[0] < 0 or p.position[0] > s.SCREEN_WIDTH
						or p.position[1] < 0 or p.position[1] > s.SCREEN_HEIGHT):
				self.current_weapon.projectile_group.remove(p)

	def check_damage_dealt(self):
		# if an asteroid reaches its destination, deal damage to player and remove
		for a in self.wave.asteroid_group:
			if a.position[1] >= a.destination[1]:
				self.health -= a.damage
				self.wave.asteroid_group.remove(a)
				Sounds.HEALTH_LOSS.play()

	def blit_projectiles(self):
			self.current_weapon.projectile_group.update()
			self.current_weapon.projectile_group.draw(self.screen)

	def blit_asteroids(self):
			self.wave.asteroid_group.update()
			self.wave.asteroid_group.draw(self.screen)

	def blit_wave_text(self):
		wave_text = self.wave_font.render('W A V E  ' + str(self.wave.wave_number + 1), 1, s.YELLOW)
		self.screen.blit(wave_text, s.WAVE_TEXT_POS)

	def blit_health(self):
		self.screen.blit(self.surfaces['hp_outline'], s.HEALTH_BAR_OUTLINE)
		remaining_health = self.health / 100.0
		if self.health > 0:
			pygame.draw.rect(self.screen, s.RED,
			                 (s.HP_BAR_X, s.HP_BAR_Y, s.HP_BAR_LENGTH * remaining_health, s.HP_BAR_HEIGHT))

	def _toggle_full_screen(self):
		if pygame.display.get_driver() == 'x11':
			pygame.display.toggle_fullscreen()
		else:
			if s.FULL_SCREEN:
				self.screen = pygame.display.set_mode(s.SCREEN_SIZE)
			else:
				self.screen = pygame.display.set_mode(s.SCREEN_SIZE, pygame.FULLSCREEN)
				s.FULL_SCREEN = not s.FULL_SCREEN
				self.screen.blit(self.screen.copy(), (0, 0))
				pygame.display.update()

	def _reset(self):
		self.health = 100
		self.inv = Inventory()
		self.current_weapon = self.inv.armory['cannon']
		self.wave = Wave()
		self.score = 0