示例#1
0
class Invasion:
    def __init__(self):
        pygame.init()
        self.settings = Settings()
        self.bullets = pygame.sprite.Group()
        self.enemies = pygame.sprite.Group()
        self.evil_bullets = pygame.sprite.Group()
        
        self.a_map = World_map()
                
        self.screen = pygame.display.set_mode(
            (self.settings.screen_width,self.settings.screen_height))
        pygame.display.set_caption("Invasion")
               
        self.level = 0
        self.stats = Stats(self)
        
        temp_x, temp_y = 200, 50
        temp_color = (0, 100, 0)
        temp_text_color =(255, 255, 255)
        self.play_button = Button(self, temp_x, temp_y, temp_color, temp_text_color, "PLAY")
        self.play_button.rect.y -= 65
        self.play_button._prep_msg("NEW GAME")
        
        
        temp_x, temp_y = 200, 50
        temp_color = (20, 40, 0)
        temp_text_color =(255, 255, 255)
        self.exit_button = Button(self, temp_x, temp_y, temp_color, temp_text_color, "EXIT")
        self.exit_button.rect.y += 185
        self.exit_button._prep_msg("EXIT")
        
        temp_x, temp_y = 200, 50
        temp_color = (80, 60, 0)
        temp_text_color =(255, 255, 255)
        self.title_button = Button(self, temp_x, temp_y, temp_color, temp_text_color, "TITLE")
        self.title_button.rect.y += 125
        self.title_button._prep_msg("TITLE")
        self.title = Title(self)
        self.title_active = False
        
        temp_x, temp_y = 200, 50
        temp_color = (150, 200, 0)
        temp_text_color =(255, 255, 255)
        self.help_button = Button(self, temp_x, temp_y, temp_color, temp_text_color, "HELP")
        self.help_button.rect.y += 65
        self.help_button._prep_msg("HELP")
        self.help_ = Help(self)
        self.help_active = False
        
        temp_x, temp_y = 200, 50
        temp_color = (150, 200, 0)
        temp_text_color =(255, 255, 255)
        self.back_button = Button(self, temp_x, temp_y, temp_color, temp_text_color, "BACK")
        self.back_button.rect.y += 185
        self.back_button._prep_msg("BACK")

        
        
        temp_x, temp_y = 250, 50
        temp_color = (0, 240, 0)
        temp_text_color =(255, 255, 255)
        self.restart_button = Button(self, temp_x, temp_y, temp_color, temp_text_color, "Restart level")
        
        temp_x, temp_y = 350, 50
        temp_color = (100, 100, 100)
        temp_text_color =(255, 0, 0)
        self.win_button = Button(self, temp_x, temp_y, temp_color, temp_text_color, "YOU ARE A WINNER!")
        
        self.myTank = Ship(self)
        self.myTank.live  = 0
        
        #interface
        self.liveboard = Lives(self)
        self.score = 0
        self.scoreboard = Score(self)

        self.image = pygame.image.load('images/brick_wall3.png')        
        self.rect = self.image.get_rect()
        
        self.aid = pygame.image.load('images/aid.png')   

    def delete_all_bullets(self):
        self.evil_bullets.empty()
        self.bullets.empty()

        
    def level_1(self):
        self.level = 1
        #show lives
        self.liveboard.prepare(self)
        
        # destroyd enemies
        self.score = 0
        self.scoreboard.prepare(self)
        
        self.a_map.create_map() #create a map 1
        self.delete_all_bullets()
        #self.myTank.out_coordinates = []
        self.myTank.create_map() #create a map 
        self.myTank.right_coordinates() # set new coordinates

        #self.myEnemy = Enemy(self)
        #print('LEVEL 111111111111111111111111111111') doNE

        self.enemies_list_coordinate = [] 
        
                
        for i in range(15): #20
            #self.create_an_enemy()
            self.create_an_enemy2()
                    #add coordianates

        self.settings.bgr_color = WHITE 
        self.image = pygame.image.load('images/brick_wall3.png')  
        #self.image = pygame.image.load('images/brick_wall.png')
 
    def level_2(self):
        self.delete_all_bullets()
        self.settings.bgr_color = LIGHTGRAY
        self.image = pygame.image.load('images/brick_wall2.png')
        self.enemies_list_coordinate = [] 
        for i in range(6): # 10 9
            #self.create_an_enemy()
            self.create_an_enemy2()

        
    def level_3(self):
        self.delete_all_bullets()
        
        self.settings.bgr_color = LIGHTGRAY
        self.image = pygame.image.load('images/brick_wall.png')
        self.enemies_list_coordinate = [] 
        for i in range(10): #12
            #self.create_an_enemy()
            self.create_an_enemy2()
            
            
    def level_4(self):
        self.delete_all_bullets()
        self.settings.bgr_color = LIGHTGRAY
        self.image = pygame.image.load('images/brick_wall2.png')
        self.enemies_list_coordinate = [] 
        for i in range(8): #10 15
            #self.create_an_enemy()
            self.create_an_enemy2()

        
    def level_5(self):
        self.delete_all_bullets()
        
        self.settings.bgr_color = LIGHTGRAY
        self.image = pygame.image.load('images/brick_wall.png')
        self.enemies_list_coordinate = [] 
        for i in range(10): #10 17
            #self.create_an_enemy()
            self.create_an_enemy2()
        
    def _check_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
                
            if event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                self._check_play_button(mouse_pos)
                self._check_exit_button(mouse_pos)
                self._check_title_button(mouse_pos)
                self._check_help_button(mouse_pos)
                self._check_restart_button(mouse_pos)
                self._check_back_button(mouse_pos)
                self._check_win_button(mouse_pos)
                
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q:
                    sys.exit()                
                if event.key == pygame.K_RIGHT:
                    #self.myTank.rect.x += self.myTank.ship_speed
                    self.myTank.moving_right = True
                if event.key == pygame.K_LEFT:
                    #self.myTank.rect.x -= self.myTank.ship_speed
                    self.myTank.moving_left = True
                if event.key == pygame.K_UP:
                    #self.myTank.rect.y -= self.myTank.ship_speed
                    self.myTank.moving_up = True
                if event.key == pygame.K_DOWN:
                    #self.myTank.rect.y += self.myTank.ship_speed
                    self.myTank.moving_down = True
                if event.key == pygame.K_SPACE:
                    self.fire_bullets()
                if event.key == pygame.K_BACKSPACE:
                    self._check_enter()
                if event.key == pygame.K_r:
                    self._check_restart()
                    
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_RIGHT:
                    self.myTank.moving_right = False 
                if event.key == pygame.K_LEFT:
                    self.myTank.moving_left = False
                if event.key == pygame.K_UP:
                    self.myTank.moving_up = False 
                if event.key == pygame.K_DOWN:
                    self.myTank.moving_down = False

    def _check_exit_button(self,mouse_pos):
        if self.exit_button.rect.collidepoint(mouse_pos) and self.myTank.live  == 0 and not self.stats.game_active and not self.help_active: # invisible button musnt be worked
            sys.exit()
                    
    def _check_enter(self):
        self.enemies.empty()
        self.stats.game_active = True
        self.myTank.live  = LIVE_OF_TANK
        self.level_1()
        pygame.mouse.set_visible(False)
        
    def _check_restart(self):
        if self.level == 0:
            return 0
        self.enemies.empty()
        self.stats.game_active = True
        self.myTank.live  = LIVE_OF_TANK
        #show lives
        self.liveboard.prepare(self)
        
        # destroyd enemies
        self.score = 0
        self.scoreboard.prepare(self)
        if self.level == 1:
            self.level_1()
        elif self.level == 2:
            self.level_2()
        elif self.level == 3:
            self.level_3()
        elif self.level == 4:
            self.level_4()
        elif self.level == 5:
            self.level_5()
        pygame.mouse.set_visible(False)

    def _check_restart_button(self,mouse_pos):
        if self.restart_button.rect.collidepoint(mouse_pos) and self.myTank.live  == 0 and not self.stats.game_active and not self.help_active: # invisible button musnt be worked
            if self.level == 0:
                return 0
            self.enemies.empty()
            self.stats.game_active = True
            self.myTank.live  = LIVE_OF_TANK
            #show lives
            self.liveboard.prepare(self)
            
            # destroyd enemies
            self.score = 0
            self.scoreboard.prepare(self)
            if self.level == 1:
                self.level_1()
            elif self.level == 2:
                self.level_2()
            elif self.level == 3:
                self.level_3()
            elif self.level == 4:
                self.level_4()
            elif self.level == 5:
                self.level_5()
            pygame.mouse.set_visible(False)
            
    def _check_title_button(self, mouse_pos):
        if self.title_button.rect.collidepoint(mouse_pos) and self.myTank.live  == 0 and not self.stats.game_active and not self.help_active: # invisible button musnt be worked
            self.title_active = True
            pygame.mouse.set_visible(False)
            
    def _check_help_button(self, mouse_pos):
        if self.help_button.rect.collidepoint(mouse_pos) and self.myTank.live  == 0 and not self.stats.game_active and not self.help_active: # invisible button musnt be worked
            self.help_active = True
            
            #pygame.mouse.set_visible(False)
            
    def _check_back_button(self, mouse_pos):
        if self.back_button.rect.collidepoint(mouse_pos) and self.help_active == True and not self.stats.game_active: # invisible button musnt be worked
            self.help_active = False
            #pygame.mouse.set_visible(False)
 
    def _check_play_button(self,mouse_pos):
        if self.play_button.rect.collidepoint(mouse_pos) and self.myTank.live  == 0 and not self.stats.game_active and not self.help_active: # invisible button musnt be worked
            self.enemies.empty()
            self.stats.game_active = True
            self.myTank.live  = LIVE_OF_TANK
            self.level_1()
            pygame.mouse.set_visible(False)
            #print(dir(self.enemies))
            
    def _check_win_button(self,mouse_pos):
        if self.win_button.rect.collidepoint(mouse_pos) and self.myTank.live  > 0 and not self.stats.game_active and not self.help_active: # invisible button musnt be worked
            self.enemies.empty()
            self.stats.game_active = True
            self.myTank.live  = LIVE_OF_TANK
            self.level_1()
            pygame.mouse.set_visible(False)
                    
    def fire_bullets(self):
        if len(self.bullets) <= BULLET_LIMIT: #my fire limit
            new_bullet = Bullet(self, self.myTank.direction,self.level)
            self.bullets.add(new_bullet)
        
    def fire_evil_bullets(self,enemy):
        new_bullet = Evil_bullet(self, enemy.rect.x, enemy.rect.y, enemy.direction,self.level)
        self.evil_bullets.add(new_bullet)
    
    def create_an_enemy2(self): 
        new_enemy = Enemy(self)
        if self.level == 1:
            new_enemy.create_map() #CHANGE a map
            #new_enemy.ship_speed = 0.25 #CHANGE LEVEL DIFICULTY
            #print('ITTTTTTTTTTTTTTTTTTTTT')
            pass
        elif self.level == 2:
            new_enemy.change_map()
        elif self.level == 3:
            new_enemy.change_map_3()
        elif self.level == 4:
            new_enemy.change_map_4()
        elif self.level == 5:
            new_enemy.change_map_5()
            
            #new_enemy.ship_speed = 0.5
        new_enemy.add_coordinates(self.myTank.rect.x, self.myTank.rect.y)
        
        #for temp in self.a_map.aid_list:
            #new_enemy.(temp[0],temp[1])
        
        for x,y in self.enemies_list_coordinate: 
            new_enemy.add_coordinates(x,y)
            
 
            
        #new_enemy.set_zero_coordinates()
        # return False if limit is out
        temp = new_enemy.right_coordinates()
        x = new_enemy.rect.x
        y= new_enemy.rect.y
        if temp != False:
            ###for enemy_update in self.enemies:
                ##enemy_update.add_coordinates(x, y)dd
            self.enemies_list_coordinate.append([x,y])
            #self.add_coordinates(x,y)
            self.enemies.add(new_enemy)
        
    def levels(self):
        if len(self.enemies) == 0 and self.level == 1:
        #print(dir(self.evil_bullets))# == 0:
            #print('WIN WIN')
            self.level = 2
            self.myTank.change_map()
            self.myTank.right_coordinates() # set new coordinates for my tank
            self.a_map.level_2_world_map()
            
            self.level_2()
            
        elif len(self.enemies) == 0 and self.level == 2:
        #print(dir(self.evil_bullets))# == 0:
            #print('WIN WIN')
            self.level = 3
            self.myTank.change_map_3()
            self.myTank.right_coordinates() # set new coordinates for my tank
            self.a_map.level_3_world_map()
            self.level_3()
            
        elif len(self.enemies) == 0 and self.level == 3:
        #print(dir(self.evil_bullets))# == 0:
            #print('WIN WIN')
            self.level = 4
            self.myTank.change_map_4()
            self.myTank.right_coordinates() # set new coordinates for my tank
            self.a_map.level_4_world_map()
            self.level_4()
            
        elif len(self.enemies) == 0 and self.level == 4:
        #print(dir(self.evil_bullets))# == 0:
            #print('WIN WIN')
            self.level = 5
            self.myTank.change_map_5()
            self.myTank.right_coordinates() # set new coordinates for my tank
            self.a_map.level_5_world_map()
            self.level_5()
            
        elif len(self.enemies) == 0 and self.level == 5:
            pass
            #print(dir(self.evil_bullets))
            #print('WIN WIN')
            #self.level_4()
            
     #restart game       
    def lose_or_win(self):
        if self.myTank.live == 0:
            self.stats.game_active = False 
            pygame.mouse.set_visible(True)
            pass
            #del self.myTank
        elif self.myTank.live > 0 and len(self.enemies) == 0 and self.level == 5:     # IF WIN  CHANGE LEVEL
            self.stats.game_active = False # IF WIN
            pygame.mouse.set_visible(True)   # IF WIN
            

    
    def _update_screen(self):
        self.screen.fill(self.settings.bgr_color)
        self.myTank.blitme()
        
        for row in self.a_map.world_map_list: # CAN I update this one?
            for x,y in row:
                self.rect.x = x
                self.rect.y = y
                self.screen.blit(self.image, self.rect)
            #pygame.draw.rect(self.screen, DARKGRAY, (x, y, TILE, TILE),2)

        #for bullet in self.bullets.sprites():
            #bullet.draw_bullet()
            
        #for bullet in self.evil_bullets.sprites():
            #bullet.draw_bullet()
        
        #self.myEnemy.blitme()
        #for enemy in self.enemies.sprites():
            #enemy.blitme()

        if not self.stats.game_active and self.myTank.live == 0 :
            self.play_button.draw_button()
            self.restart_button.draw_button()
            self.help_button.draw_button()
            self.title_button.draw_button()
            self.exit_button.draw_button()

        if self.title_active == True:
            self.title.draw_title()
            pygame.display.flip()   #SHOW ALL update_screen
            time.sleep(2)
            self.title_active = False
            
        if self.help_active == True:
            self.help_.draw_title()
            self.back_button.draw_button()
            pygame.display.flip()   #SHOW ALL update_screen
            #time.sleep(3)
            #self.help_active = False
        else:
            self.liveboard.draw()
            self.scoreboard.draw()
            
            
        if not self.stats.game_active and self.myTank.live > 0 and len(self.enemies) == 0 :
            self.win_button.draw_button()
            
            
        #pygame.display.flip()       
    
    
    def run(self):
        #self.level = 1
        while(True):
            for i in range(100):
                #if not self.stats.game_active:
                self.lose_or_win()
                self._check_events()
                self.myTank.empty_coordinates_others()
                
                #self.liveboard.prepare()
                
                #SHOW ALL update_screen
                self._update_screen()          
                               
                
                #animation of destroy and Delete
                if self.stats.game_active == True: #or self.stats.game_active == True: # self.myTank.live > 0 or not winner
                    #for temp in self.a_map.aid_list:
                        #print(temp[0],temp[1])                            
                    self.levels()
                    
                    
                    for enemy in self.enemies:
                        #update coordinates into enemies and myTank
                        enemy.coordinates_others = []
                        self.myTank.coordinates_others = []
                        
                        #for temp in self.a_map.aid_list:
                            #self.myTank.add_coordinates(temp[0],temp[1])
                            #print(temp[0],temp[1])
                        
                        for enemy_update in self.enemies:
                            enemy.add_coordinates(enemy_update.rect.x, enemy_update.rect.y)
                            enemy.add_coordinates(self.myTank.rect.x, self.myTank.rect.y)
                            
                            for temp in self.a_map.aid_list:
                                enemy.add_coordinates(temp[0],temp[1])
                                
                            self.myTank.add_coordinates(enemy_update.rect.x, enemy_update.rect.y)
                        #live circle of enemy
                        
                        if enemy.live == True and i == 0:
                            pass
                            enemy.rand_direction()
                            #enemy is shoting
                            self.fire_evil_bullets(enemy)
                        if i != 0:
                            if enemy.live == True and i%2  == 0 or i%3  == 0: # speed enemies added or i%3  == 0
                            #  print(f'i= {i}')# speed enemie3s
                                enemy.update()
                        
                        if enemy.live == False and i == 0:
                            self.score += 1
                            self.scoreboard.prepare(self)
                            self.enemies.remove(enemy)
                            
                    #SHOW ALL update_screen
                        enemy.blitme()
                    
                    #for in 
                    if len(self.a_map.aid_list) != 0:
                        myTank_rightTopX = self.myTank.rect.x  + self.myTank.SIZE
                        myTank_lefttBottomY  = self.myTank.rect.y  + self.myTank.SIZE
                        #temp = 0
                        for a in self.a_map.aid_list:
                            x = a[0]
                            y = a[1]
                            self.rect.x = x
                            self.rect.y = y
                            rightTopX = x + 31
                            lefttBottomY = y + 31
                            if (rightTopX >= myTank_rightTopX >= x) and (lefttBottomY >= self.myTank.rect.y >= y) or (rightTopX >= myTank_rightTopX >= x) and (lefttBottomY >= myTank_lefttBottomY >= y) or (rightTopX >= self.myTank.rect.x >= x) and (lefttBottomY >= myTank_lefttBottomY >= y) or (rightTopX >= self.myTank.rect.x >= x) and (lefttBottomY >= self.myTank.rect.y >= y):
                                #temp += 2    ################???????????????????????????
                                self.a_map.aid_list.remove(a)
                                #temp += 2
                                self.myTank.live += 2
                                self.liveboard.prepare(self)
                            #break
                            else:
                                self.screen.blit(self.aid, self.rect)

                    
                    self.myTank.update()
                    #self.bullets.update()
                    
                    for bullet in self.evil_bullets.sprites():
                        if (self.myTank.rect.x + self.myTank.SIZE >= bullet.x >= self.myTank.rect.x) and (self.myTank.rect.y + self.myTank.SIZE >= bullet.y >= self.myTank.rect.y):
                            #enemy.live = False
                                #self.enemies.remove(enemy)
                                print('You has been attacked')
                                self.myTank.live -= 1
                                        #show lives
                                self.liveboard.prepare(self)
                                self.evil_bullets.remove(bullet)
                            
                        #wall
                        if bullet.update():
                            self.evil_bullets.remove(bullet)
                        else:
                            bullet.draw_bullet()      #SHOW ALL update_screen          
                
                    # How to move and delete bullet
                    for bullet in self.bullets.sprites():
                        #FIRE FIRE FIRE to enemies
                        #step = True
                        for enemy in self.enemies:
                            if (enemy.rect.x + enemy.SIZE >= bullet.x >= enemy.rect.x) and (enemy.rect.y + enemy.SIZE >= bullet.y >= enemy.rect.y):
                                #step = False
                                enemy.live = False
                                #self.enemies.remove(enemy)
                                self.bullets.remove(bullet)
                        
                        #wall
                        temp = bullet.update()
                        if temp == True:
                            self.bullets.remove(bullet)
                        else:
                            bullet.draw_bullet()    #SHOW ALL update_screen
                    
                    
                    
                pygame.display.flip()   #SHOW ALL update_screen
示例#2
0
class AlienInvasion:
    """Overall class to manage game assets and behavior."""
    def __init__(self):
        """Initialize the game, and create game resources."""
        pygame.init()
        self.settings = Settings()
        self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
        self.settings.screen_width = self.screen.get_rect().width
        self.settings.screen_height = self.screen.get_rect().height
        pygame.display.set_caption("Bun Blaster")

        #create and instance to store game stats and create scoreboard
        self.stats = GameStats(self)
        self.sb = Scoreboard(self)

        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()
        self.buns = pygame.sprite.Group()
        self.stars = pygame.sprite.Group()

        self._create_batch()
        self._create_star_sky()

        #make the the Play button
        self.play_button = Button(self)
        self.play_button._prep_msg("Play")

        # get the screen dimensions to be used to place buttons
        self.screen_rect = self.screen.get_rect()

        #make the easy button
        self.easy_button = Button(self)
        self.easy_button.button_color = (0, 0, 255)  #blue
        self.easy_button.rect.centerx = (self.screen_rect.centerx -
                                         self.easy_button.width - 50)
        self.easy_button._prep_msg("Easy")

        #make the normal button
        self.normal_button = Button(self)
        self.normal_button.button_color = (0, 255, 0)  #green
        self.normal_button.rect.center = self.screen_rect.center
        self.normal_button._prep_msg("Normal")

        #make the hard button
        self.hard_button = Button(self)
        self.hard_button.button_color = (255, 0, 0)  #red
        self.hard_button.rect.centerx = (self.screen_rect.centerx +
                                         self.hard_button.width + 50)
        self.hard_button._prep_msg("Hard")

        #make the title
        self.title_box = Button(self)
        self.title_box.width = 700
        self.title_box.button_color = (0, 0, 0)  #red
        self.title_box.rect.centery = (self.screen_rect.centery -
                                       self.title_box.height - 25)
        self.title_box.font = pygame.font.SysFont(None, 36)
        self.title_box._prep_msg("Click to choose a difficulty level:")

        #initialize sound effects
        self.explode = pygame.mixer.Sound('sounds/explosion_medium.wav')
        self.fire = pygame.mixer.Sound(
            'sounds/leisure_video_game_retro_laser_gun_fire_004.wav')
        self.click = pygame.mixer.Sound('sounds/button_click.wav')
        self.level_up = pygame.mixer.Sound('sounds/level_up.wav')
        self.crash = pygame.mixer.Sound('sounds/crash.wav')
        self.end = pygame.mixer.Sound('sounds/fail_theme.wav')

    def run_game(self):
        """Start the main loop for the game."""
        mixer.music.load("sounds/open_tune.wav")
        mixer.music.play(-1)

        while True:
            # Watch for keyboard and mouse events.
            self._check_events()
            if self.stats.game_active:
                self.ship.update()
                self._update_bullets()
                self._update_buns()

            self._update_screen()

    def _check_events(self):
        # respond to keyboard and mouse events.
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

            elif event.type == pygame.KEYDOWN:
                self._check_keydown_events(event)

            elif event.type == pygame.KEYUP:
                self._check_keyup_events(event)

            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()

                self._check_play_button(mouse_pos)

    def _check_keydown_events(self, event):
        """Respond to keypresses. """
        if event.key == pygame.K_RIGHT:
            # Move the ship to the right.
            self.ship.moving_right = True
        elif event.key == pygame.K_LEFT:
            # Move the ship to the left.
            self.ship.moving_left = True
        elif event.key == pygame.K_q:
            #Press q to quit
            self.sb.save_high_score()
            sys.exit()
        elif event.key == pygame.K_SPACE:
            #fire bullets on spacebar
            self._fire_bullet()
        elif event.key == pygame.K_p:
            #Press p to start
            if not self.stats.game_active:
                self._start_game()

    def _check_keyup_events(self, event):
        """ respond to key releases."""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = False
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = False

    def _start_game(self):
        #Make game active and reset the game stats
        self.stats.reset_stats()
        self.stats.game_active = True

        #get rid of any remaining any buns and bullets
        self.buns.empty()
        self.bullets.empty()

        #create a new batch and center the ship
        self._create_batch()
        self.ship.center_ship()

        # Hide the mouse cursor.
        pygame.mouse.set_visible(False)

    def _check_play_button(self, mouse_pos):
        """ Start a new game when the player clicks one of the difficulty buttons."""
        normal_button_clicked = self.normal_button.rect.collidepoint(mouse_pos)
        easy_button_clicked = self.easy_button.rect.collidepoint(mouse_pos)
        hard_button_clicked = self.hard_button.rect.collidepoint(mouse_pos)

        if normal_button_clicked and not self.stats.game_active:
            #reset the game settings
            self.click.play()
            self.settings.initialize_normal_settings()
            self.start_sequence()

        elif hard_button_clicked and not self.stats.game_active:
            self.click.play()
            self.settings.initialize_hard_settings()
            self.start_sequence()

        elif easy_button_clicked and not self.stats.game_active:
            self.click.play()
            self.settings.initialize_easy_settings()
            self.start_sequence()

    def start_sequence(self):
        """ calls the functions that start the game post level selections"""
        self._start_game()
        self.sb.prep_score()
        self.sb.prep_level()
        self.sb.prep_ships()
        mixer.music.load("sounds/attack_music.wav")
        mixer.music.play(-1)

    def _fire_bullet(self):
        """ Create a new bullet and add it to the bullets group"""
        if len(self.bullets) < self.settings.bullets_allowed:
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)
            self.fire.play()

    def _update_bullets(self):
        """ updated bullet position and gets rid of old bullets"""
        #update bullet positons.
        self.bullets.update()
        # get rid of bullets that have dissapeared
        for bullet in self.bullets.copy():
            if bullet.rect.bottom <= 0:
                self.bullets.remove(bullet)

        self._check_bullet_bun_collision()

    def _check_bullet_bun_collision(self):
        """ Respond to bullet bun collions"""

        # Check for any bullets that have hit buns and if so, get rid of the bullet and the bun.
        collisions = pygame.sprite.groupcollide(self.bullets, self.buns, True,
                                                True)

        # Increment the score and check if it is a high score
        for buns in collisions.values():
            self.stats.score += self.settings.bun_points * len(buns)
            self.sb.prep_score()
            self.sb.check_high_score()
            self.explode.play()

        #if no buns are left - start a new level
        if not self.buns:
            self.start_new_level()

    def start_new_level(self):
        """ method to start a new level """
        # Destroy remaining bullets, create new batch and increase speed.
        self.bullets.empty()
        self._create_batch()
        self.settings.increase_speed()
        self.level_up.play()

        #increment level counter and update scoreboard level counter
        self.stats.level += 1
        self.sb.prep_level()

    def _ship_hit(self):
        """Respond to the ship being hit by a bun"""

        #stop them music - play crash
        pygame.mixer.music.stop()
        self.crash.play(maxtime=2000)

        if self.stats.ships_left > 0:

            #Decrement ships left, and update scoreboard
            self.stats.ships_left -= 1
            self.sb.prep_ships()

            #get rid of any remaining buns and bullets
            self.buns.empty()
            self.bullets.empty()

            #create a new batch and center the ship
            self._create_batch()
            self.ship.center_ship()

            #Pause
            sleep(2.5)
            mixer.music.load("sounds/attack_music.wav")
            mixer.music.play(-1)

        else:
            sleep(2.5)
            pygame.mixer.Channel(0).queue(self.end)
            self.stats.game_active = False
            pygame.mouse.set_visible(True)
            mixer.music.load("sounds/open_tune.wav")
            mixer.music.play(-1)

    def _create_batch(self):
        """ Create a batch of buns"""
        #Make a bun and find the number of buns in a row
        #spacing between each bun is equal to one bun width

        bun = Bun(self)
        bun_width, bun_height = bun.rect.size
        available_space_x = self.settings.screen_width - (2 * bun_width)
        number_buns_x = available_space_x // (2 * bun_width)

        #determine the number of rows of buns that fit onto the screen.
        ship_height = self.ship.rect.height
        available_space_y = (self.settings.screen_height - (3 * bun_height) -
                             ship_height)
        number_rows = available_space_y // (2 * bun_height)

        # Create the full batch of buns.
        for row_number in range(number_rows):
            for bun_number in range(number_buns_x):
                self._create_bun(bun_number, row_number)

    def _create_bun(self, bun_number, row_number):
        #Create a bun and place it in the row
        bun = Bun(self)
        bun_width, bun_height = bun.rect.size
        bun.x = bun_width + 2 * bun_width * bun_number
        bun.rect.x = bun.x
        bun.rect.y = bun.rect.height + 2 * bun.rect.height * row_number
        self.buns.add(bun)

    def _update_buns(self):
        """ Check is the batch is at an edge, then update the position of all the buns in the batch"""
        self._check_batch_edges()
        self.buns.update()

        # Look for bun / ship collisions
        if pygame.sprite.spritecollideany(self.ship, self.buns):
            self._ship_hit()

        #look for buns hitting the bottom of the screen
        self._check_buns_bottom()

    def _check_batch_edges(self):
        """Respond appropriately if any buns have reached an edge."""
        for bun in self.buns.sprites():
            if bun.check_edges():
                self._change_batch_direction()
                break

    def _check_buns_bottom(self):
        """check if any buns have reached the bottom of the screen."""
        screen_rect = self.screen.get_rect()
        for bun in self.buns.sprites():
            if bun.rect.bottom >= screen_rect.bottom:
                #treat this the same as if the ship got hit
                self._ship_hit()
                break

    def _change_batch_direction(self):
        """ Drop the entire batch and change the batch direction. """
        for bun in self.buns.sprites():
            bun.rect.y += self.settings.batch_drop_speed
        self.settings.batch_direction *= -1

    def _create_star_sky(self):
        """ Create a sky full of stars"""
        #Make a star and find the number of stars in a row
        #spacing between each star is equal to one star width
        star = Star(self)
        star_width, star_height = star.rect.size
        available_space_x = self.settings.screen_width
        number_stars_x = available_space_x // star_width // 2

        #determine the number of rows of stars that fit onto the screen.
        available_space_y = self.settings.screen_height
        number_rows = available_space_y // star_height

        # Create the full batch of stars.
        for row_number in range(number_rows):
            random_stars_x = randint(2, 14)
            for star_number in range(random_stars_x):
                self._create_star(star_number, row_number)

    def _create_star(self, star_number, row_number):
        #Create a star and place it in the row
        star = Star(self)
        star_width, star_height = star.rect.size
        random_x = randint(0, self.settings.screen_width)
        random_y = randint(0, self.settings.screen_height)
        star.rect.x = random_x
        star.rect.y = random_y
        self.stars.add(star)

    def _update_screen(self):
        """Update images on the screen, and flip to the new screen."""
        self.screen.fill(self.settings.bg_color)
        self.stars.draw(self.screen)
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()
        self.buns.draw(self.screen)

        #Draw the score information
        self.sb.show_score()

        #Draw the play button if the game is inactive.
        if not self.stats.game_active:
            self.title_box.draw_msg()
            self.easy_button.draw_button()
            self.normal_button.draw_button()
            self.hard_button.draw_button()

        pygame.display.flip()