Exemple #1
0
class AlienInvasion:
    def __init__(self):
        pygame.init()  #intializing components of game

        self.settings = Settings()  #create an instance of Settings class
        self.screen = pygame.display.set_mode(
            (self.settings.height,
             self.settings.width))  #set the size of regular window

        #Fullscreen 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("Alien Invasion")  #set the name of game

        self.stats = GameStats(self)

        self.ship = Ship(self)  #passing the current instance of AlienInvasion

        self.bullets = pygame.sprite.Group(
        )  #create instance of sprite.Group class

        self.aliens = pygame.sprite.Group()

        self.sb = ScoreBoard(self)

        self._create_fleet()

        self.crash_sound = pygame.mixer.Sound(
            "Explosion+1.wav")  #save audion in self.crash_sound
        self.laser_sound = pygame.mixer.Sound("Laser.wav")
        self.ship_hit_sound = pygame.mixer.Sound("Explosion+5.wav")

        #Make play button
        self.play_button = Button(self, "Play")

    def run_game(self):
        while True:  #while game is running
            self._check_events()

            if self.stats.game_active:
                self.ship.update()

                self._update_bullets()

                self._update_aliens()

            self._update_screen()

    def _check_events(self):
        for event in pygame.event.get():  #keyboard and mouse events

            if event.type == pygame.QUIT:  #if clicked on the close window button
                pygame.quit()
                sys.exit()  # then exit the game

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

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

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

    def _check_key_down(self, event):
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True

        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = True

        elif event.key == pygame.K_q:
            with open("High_Score.txt", 'w') as hs:
                hs.write((str(self.stats.high_score)))

            pygame.quit()
            sys.exit()

        elif event.key == pygame.K_SPACE:

            self._fire_bullet()

    def _check_key_up(self, event):
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = False
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = False

    def _fire_bullet(self):
        #Create new bullet and add it to bullets group
        if len(self.bullets
               ) < self.settings.bullets_allowed:  #check the number of bullets
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)
            pygame.mixer.Sound.play(self.laser_sound)  #play audio at crash
            pygame.mixer.music.stop()  #stop audio

    def _update_bullets(self):
        self.bullets.update()  #move bullets on screen
        for bullet in self.bullets.copy(
        ):  #check bullet position in copy of bullet
            if bullet.rect.bottom <= 0:  #check if bottom of bullet is at zero y-coordinate
                self.bullets.remove(bullet)  #remove the bullet from list
        #print(len(self.bullets)) #print length of list of bullets

        self._check_bullet_alien_collision()

    def _check_bullet_alien_collision(self):
        #Check collision of bullets and alien
        collisions = pygame.sprite.groupcollide(self.bullets, self.aliens,
                                                True, True)

        #True and True means that both the bulleta and alien would disappear
        #from screen after collsion

        if collisions:
            pygame.mixer.Sound.play(self.crash_sound)  #play audio at crash
            pygame.mixer.music.stop()  #stop audio
            for aliens in collisions.values():  #collision is a dictionary
                self.stats.score += self.settings.alien_points * len(aliens)
            self.sb.prep_score()
            self.sb.check_high_score()

        #When the fleet has been destroyed
        if not self.aliens:
            self.bullets.empty()  #remove the existing bullets
            self._create_fleet()  #create new fleet
            self.settings.increase_speed()
            # Increase level.
            self.stats.level += 1
            self.sb.prep_level()

    def _create_fleet(self):
        alien = Alien(self)  #make an instance of alien

        alien_width = alien.rect.width  #get the width of alien.bmp
        alien_height = alien.rect.height  #get the alien.bmp height
        #print("Alien width is " + str(alien_width))

        available_space_x = self.settings.width - (2 * alien_width)
        #print(available_space_x)#subtract margins
        number_aliens_x = available_space_x // (2 * alien_width
                                                )  #calculate no. of aliens
        #print(number_aliens_x)

        ship_height = self.ship.rect.height
        available_space_y = self.settings.height - (3 * alien_height) - (
            ship_height)
        number_rows = available_space_y // (3 * alien_height)

        for row in range(number_rows):
            for alien_number in range(
                    number_aliens_x):  #loop through no. of aliens
                self._create_alien(alien_number, row)

    def _create_alien(self, alien_number, row):
        alien = Alien(self)  # create alien

        alien_width, alien_height = alien.rect.size

        alien.x = alien_width + (2 * alien_width * alien_number)
        alien.rect.x = alien.x

        alien.rect.y = alien.rect.height + 2 * alien.rect.height * row

        self.aliens.add(alien)  #add it to sprite list

    def _update_aliens(self):
        self.aliens.update()  #call this method to move aliens on screen
        self._check_fleet_edges()

        #Check for alien and ship collision
        if pygame.sprite.spritecollideany(self.ship, self.aliens):
            self._ship_hit()

        #Check whether alien has hit the bottom
        self._check_aliens_bottom()

    def _check_fleet_edges(self):
        #loop through sprites list of alien
        for alien in self.aliens.sprites():
            if alien.check_edges():
                #print('aaaa')
                self.change_fleet_direction()
                break

    def change_fleet_direction(self):
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1

    def _ship_hit(self):
        #Decrement ship
        if self.stats.ship_left > 0:

            pygame.mixer.Sound.play(self.ship_hit_sound)  #play audio at crash
            pygame.mixer.music.stop()  #stop audio

            self.stats.ship_left -= 1
            self.sb.prep_ships()

            #Get rid of aliens and bullets
            self.bullets.empty()
            self.aliens.empty()

            #Create a new fleet
            self._create_fleet()
            self.ship.center_ship()

            #Pause
            sleep(0.5)

        else:

            pygame.mixer.Sound.play(self.ship_hit_sound)  #play audio at crash
            pygame.mixer.music.stop()  #stop audio

            self.stats.game_active = False
            pygame.mouse.set_visible(True)

    def _check_aliens_bottom(self):
        screen_rect = self.screen.get_rect()
        for alien in self.aliens.sprites():
            if alien.rect.bottom >= screen_rect.bottom:
                self._ship_hit()
                break

    def _check_play_button(self, mouse_pos):
        #start a new game when player clicks Play
        button_clicked = self.play_button.rect.collidepoint(mouse_pos)

        if button_clicked and not self.stats.game_active:
            self.settings.intialize_dynamic_settings()
            self.stats.reset_stats()
            self.stats.game_active = True
            self.sb.prep_score()
            self.sb.prep_level()
            self.sb.prep_ships()

            #get rid of aliens
            self.aliens.empty()
            self.bullets.empty()

            # Create a new fleet and center the ship.
            self._create_fleet()
            self.ship.center_ship()

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

    def _update_screen(self):
        self.screen.fill(self.settings.bg_color)

        self.ship.blitme()  #draw ship

        for bullet in self.bullets.sprites():  #draw bullets
            bullet.draw_bullet()

        self.aliens.draw(self.screen)  #draw aliens

        self.sb.show_score()  # draw scoreboard

        #draw button
        if not self.stats.game_active:
            self.play_button.draw_button()

        pygame.display.flip()  #display window
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
        self.screen = pygame.display.set_mode((self.settings.screen_width, self.settings.screen_height))
        pygame.display.set_caption("Alien Invasion")
        icon = pygame.image.load("images/alien2.png")
        # background = self.settings.bg
        pygame.display.set_icon(icon)

        # Create an instance to store game statistics, and create score board.
        self.stats = GameStats(self)
        self.sb = ScoreBoard(self)

        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()
        self.aliens = pygame.sprite.Group()

        self._create_fleet()
        # Make the play button.
        self.play_button = Button(self, "Play")

    def runGame(self):
        # start the main loop for the game
        while True:
            self._check_events()

            if self.stats.game_active:
                self.ship.update()
                self._update_bullets()
                self._update_aliens()

            self._update_screen()

    def _check_events(self):
        """Respond to key presses 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_play_button(self, mouse_pos):
        """Start a new game when the player clicks play."""
        button_clicked = self.play_button.rect.collidepoint(mouse_pos)
        if button_clicked and not self.stats.game_active:
            # Reset the game settings.
            self.settings.initialize_dynamic_settings()
            self.stats.reset_stats()
            self.stats.game_active = True
            self.sb.prep_score()
            self.sb.prep_level()
            self.sb.prep_ships()

            # Get rid of any remaining aliens and bullets.
            self.aliens.empty()
            self.bullets.empty()

            # Create a new fleet and center the ship.
            self._create_fleet()
            self.ship.center_ship()

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

    def _check_keydown_events(self, event):
        """Respond to key presses."""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = True
        elif event.key == pygame.K_q:
            sys.exit()
        elif event.key == pygame.K_SPACE:
            self._fire_bullet()

    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 _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)

    def _update_bullets(self):
        """Update position of bullets and get rid of old bullets."""
        # Update bullet positions.
        self.bullets.update()

        #  get rid of bullets that have disappeared.
        for bullet in self.bullets.copy():
            if bullet.rect.bottom <= 0:
                self.bullets.remove(bullet)
        self._check_bullet_alien_collisions()

    def _check_bullet_alien_collisions(self):
        """Respond to bullet-alien collisions"""
        # Remove any bullets and aliens that have collided.
        collisions = pygame.sprite.groupcollide(self.bullets, self.aliens, True, True)

        if collisions:
            for aliens in collisions.values():
                self.stats.score += self.settings.alien_points * len(aliens)
            self.sb.prep_score()
            self.sb.check_high_score()

        if not self.aliens:
            # Destroy existing bullets and create a new fleet.
            self.bullets.empty()
            self._create_fleet()
            self.settings.increase_speed()

            # Increase level.
            self.stats.level += 1
            self.sb.prep_level()

    def _update_aliens(self):
        """Check if the fleet is at an edge, then Update the positions of all aliens in the fleet."""
        self._check_fleet_edges()
        self.aliens.update()
        # Look for alien-ship collisions.
        if pygame.sprite.spritecollideany(self.ship, self.aliens):
            self._ship_hit()
        # look for aliens hitting the bottom of the screen
        self._check_aliens_bottom()

    def _create_fleet(self):
        """Create the fleet of aliens"""
        # Create an alien and find the number of aliens in a row.
        # Spacing between each alien is equal to on alien width.
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        available_space_x = self.settings.screen_width - (2 * alien_width)
        number_aliens_x = available_space_x // (2 * alien_width)

        # Determine the number of rows of aliens that fit on the screen.
        ship_height = self.ship.rect.height
        available_space_y = (self.settings.screen_height - (3 * alien_height) - ship_height)
        number_rows = available_space_y // (2 * alien_height)

        # Create the full fleet of aliens.
        for row_number in range(number_rows):
            for alien_number in range(number_aliens_x):
                self._create_alien(alien_number, row_number)

    def _create_alien(self, alien_number, row_number):
        # Create an alien and place it in the row.
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        alien.x = alien_width + 2 * alien_width * alien_number
        alien.rect.x = alien.x
        alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
        self.aliens.add(alien)

    def _check_fleet_edges(self):
        """Respond appropriately if any aliens have reached an edge"""
        for alien in self.aliens.sprites():
            if alien.check_edges():
                self._change_fleet_direction()
                break

    def _change_fleet_direction(self):
        """Drop the entire fleet and change the fleet's direction."""
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1

    def _ship_hit(self):
        """Respond to the ship being hit by an alien."""
        if self.stats.ships_left > 0:
            # Decrement ships_left
            self.stats.ships_left -= 1
            self.sb.prep_ships()

            # Get rid of any remaining aliens and bullets.
            self.aliens.empty()
            self.bullets.empty()

            # Create a new fleet and center the ship.
            self._create_fleet()
            self.ship.center_ship()

            # Pause.
            sleep(0.5)
        else:
            self.stats.game_active = False
            pygame.mouse.set_visible(True)

    def _check_aliens_bottom(self):
        """Check if any aliens have reached the bottom of the screen."""
        screen_rect = self.screen.get_rect()
        for alien in self.aliens.sprites():
            if alien.rect.bottom >= screen_rect.bottom:
                # Treat this the same as if the ship got hit.
                self._ship_hit()
                break

    def _update_screen(self):
        """Update images on the screen, and flip to the new screen."""
        self.screen.fill(self.settings.bg_color)
        self.ship.blitMe()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()
        self.aliens.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.play_button.draw_button()

        # Make the most recently drawn screen visible
        pygame.display.flip()
Exemple #3
0
class AlienInvasion:
    """Overall class to manage game asserts and behavior."""
    def __init__(self):
        """Initialize the game, and create game resources."""
        self._init_pygame()

        self.settings = Settings()
        self.screen = pg.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height))
        self.ship = Ship(self)
        self.stats = GameStats(self)
        self.score_board = ScoreBoard(self)
        self.fleet = Fleet(self)
        self.play_button = Button(self)
        self.info_tag = Tag(self)

        # Sprite groups.
        self.aliens = self.fleet.aliens
        self.bullets = pg.sprite.Group()
        self.explosions = pg.sprite.Group()

        # Sounds.
        self.shooting_sound = Sound(SHOOT_WAV)
        self.ship_hit_sound = Sound(SHIP_HIT_WAV)
        self.alien_shot_sound = Sound(SHOT_ALIEN_WAV)
        self._update_sounds()

        self.clock = pg.time.Clock()

    @staticmethod
    def _init_pygame():
        """Initialize pygame and caption the game window."""
        pg.init()
        pg.display.set_caption("Alien Invaders")

    def check_events(self):
        """Respond to key presses and mouse events."""
        for event in pg.event.get():
            # Write high-score to file then Exit.
            if self._quit_game(event):
                self.stats.write_highscore()
                sys.exit()

            # Reset the game.
            if self._start_game(event) and not self.stats.game_active:
                self.settings.initialize_dynamic_settings()
                self._setup_new_game()

            if event.type == KEYDOWN:
                self._check_keydown_events(event)
            elif event.type == KEYUP:
                self._check_keyup_events(event)

    @staticmethod
    def _quit_game(event: pg.event.Event) -> bool:
        """Check if the user wants to exit the game."""
        return event.type == QUIT or (event.type == KEYDOWN
                                      and event.key == K_ESCAPE)

    def _start_game(self, event: pg.event.Event) -> bool:
        """Start a new game when the clicks Play or hits Enter."""
        if event.type == MOUSEBUTTONDOWN:
            return self.play_button.rect.collidepoint(pg.mouse.get_pos())
        return event.type == KEYDOWN and event.key == K_RETURN

    def _check_keydown_events(self, event: pg.event.Event):
        """Respond to key presses."""
        if event.key == K_RIGHT:
            self.ship.moving_right = True
        elif event.key == K_LEFT:
            self.ship.moving_left = True
        elif event.key == K_SPACE:
            self._fire_bullet()
        elif event.key == K_m:
            self._update_sounds()

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

    def _setup_new_game(self):
        """Reset the game statistics and create a new board."""
        self.stats.reset_stats()
        self.stats.game_active = True
        self.score_board.prep_images()
        self.ship.center_ship()
        self._reset_all_sprites()
        # Hide the mouse cursor.
        pg.mouse.set_visible(False)

    def _reset_all_sprites(self):
        """Remove old bullets and aliens, create a new ship and alien fleet."""
        self.aliens.empty()
        self.bullets.empty()
        self.fleet.create_fleet()

    def _reset(self):
        """Reset game when a life is lost."""
        if self.stats.ships_left < 1:  # no more lives left
            self.stats.game_active = False
            pg.mouse.set_visible(True)

        # Decrement ships left, update score-board, and reset game.
        self.stats.ships_left -= 1
        self.score_board.prep_ships()
        self._reset_all_sprites()
        sleep(0.3)

    def _fire_bullet(self):
        """Create a new bullet and add it to the bullets group."""
        if len(self.bullets) < self.settings.bullets_limit:
            new_bullets = self.ship.shoot()
            if new_bullets:
                self.bullets.add(new_bullets)
                self.shooting_sound.play()

    def _collisions(self):
        """Respond to alien-ship collisions, and aliens hitting the screen bottom."""
        # Ship collision: play sound, make explosion.
        explosion = Explosion(self.ship.rect.center)
        self.explosions.add(explosion)
        self.ship_hit_sound.play()

    def _alien_ship_collision(self) -> bool:
        """Return True if ship is hit by an alien."""
        ship_hit = pg.sprite.spritecollide(self.ship, self.aliens, True)
        if ship_hit:
            for _ in ship_hit:
                self._collisions()
                return True

    def _alien_ground_collision(self) -> bool:
        """Return True if any aliens have reached the bottom of the screen."""
        screen_rect = self.screen.get_rect()
        for alien in self.aliens.sprites():
            if alien.rect.bottom >= screen_rect.bottom:
                # Check if AT LEAST one alien reaches the ground.
                self._collisions()
                return True

    def _alien_bullet_collision(self):
        """Respond to bullet-alien collision."""
        collisions = pg.sprite.groupcollide(self.bullets, self.aliens, True,
                                            True)
        if collisions:
            for aliens in collisions.values():
                self.stats.score += self.settings.alien_points * len(aliens)
                self.score_board.prep_score()
                # For each collision, play sound, make explosion.
                for alien in aliens:
                    explosion = Explosion(alien.rect.center)
                    self.explosions.add(explosion)
                    self.alien_shot_sound.play()
            self.score_board.check_high_score()

        if not self.aliens:
            if not self.explosions:
                # Destroy sprites left; create new fleet; increase game speed and level.
                self.bullets.empty()
                self.fleet.create_fleet()
                self.settings.increase_level()
                self.stats.level += 1
                self.score_board.prep_level()

    def update_bullets(self):
        """Update position of bullets and get rid of old bullets."""
        self.bullets.update()
        self._alien_bullet_collision()

    def update_aliens(self):
        """Update the position of all aliens in the fleet."""
        self.fleet.check_fleet_edges()
        alien_collisions: bool = self._alien_ship_collision(
        ) or self._alien_ground_collision()
        self.aliens.update()
        self.explosions.update()
        if alien_collisions:
            self._reset()

    def _update_sounds(self):
        """Plays sounds if play = 1, stops sounds if play = -1."""
        # Defaults to 1, sounds enabled.
        self.settings.sound_playing *= -1
        for _sound in (
                self.shooting_sound,
                self.ship_hit_sound,
                self.alien_shot_sound,
        ):
            if self.settings.sound_playing == 1:
                _sound.set_volume(0.2)
            elif self.settings.sound_playing == -1:
                _sound.set_volume(0)

    def update_screen(self):
        """Update images on the screen, and flip to the new screen."""
        background = pg.image.load(BACKGROUND_IMG).convert()
        bg_image = pg.transform.scale(
            background,
            (self.settings.screen_width, self.settings.screen_height))
        self.screen.blit(bg_image, (0, 0))

        # Draw sprites.
        self.ship.draw()
        self.explosions.draw(self.screen)
        self.aliens.draw(self.screen)
        self.bullets.draw(self.screen)

        # Draw the score information
        self.score_board.show_score()
        # Draw the play button if the game is inactive.
        if not self.stats.game_active:
            # Button and Tag
            self.info_tag.prep_msg(
                "Press Esc to exit. Press M to (un)mute game sounds.")
            self.info_tag.draw_button()
            self.play_button.prep_msg("Click here or press Enter to play.")
            self.play_button.draw_button()

        pg.display.flip()
        self.clock.tick(60)
class AlienInvasion:
    def __init__(self):

        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("Alien Invasion")

        self.stats = GameStats(self)
        self.sb = ScoreBoard(self)

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

        self.aliens = pygame.sprite.Group()
        self._create_fleet()

        self.stars = pygame.sprite.Group()
        self._create_stars_grid()

        self.easy_button = Button(self, 850, 250, (102, 255, 0), "Easy")
        self.normal_button = Button(self, 850, 450, (255, 216, 0), "Normal")
        self.hard_button = Button(self, 850, 650, (255, 36, 0), "Hard")
        self.zerout_record_button = Button(self, 850, 850, (0, 0, 0),
                                           "Zero out a record")

    def run_game(self):
        """Запускает основной цикл игры"""

        while True:
            self._check_events()
            self.sb.read_high_score()
            if self.stats.game_active:
                self.ship.update()
                self._update_bullets()
                self._update_aliens()

            self._update_screen()

    def _check_events(self):
        """Обрабатывает события клавиш и мыши"""

        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._difficulty_buttons(mouse_pos)
                self._check_play_button(mouse_pos)
                self._zerout_record(mouse_pos)

    def _check_keydown_events(self, event):
        """Реакция на нажите клавиш"""

        if event.key == pygame.K_d:
            self.ship.moving_right = True
        elif event.key == pygame.K_a:
            self.ship.moving_left = True
        elif event.key == pygame.K_ESCAPE:
            self.sb.write_high_score()
            sys.exit()
        elif event.key == pygame.K_SPACE:
            if self.stats.game_active:
                self._fire_bullet()

    def _check_keyup_events(self, event):
        """Реакция на отпускание клавиш"""

        if event.key == pygame.K_d:
            self.ship.moving_right = False
        elif event.key == pygame.K_a:
            self.ship.moving_left = False

    def _zerout_record(self, mouse_pos):
        """Обнуляет рекорд при нажатии кнопки"""

        button_clicked = self.zerout_record_button.rect.collidepoint(mouse_pos)

        if button_clicked and not self.stats.game_active:

            os.system(
                'python D:\\Programming\\Python\\alien_invasion\\start.py')
            sys.exit()

    def _check_play_button(self, mouse_pos):
        """Запускает новую игру при нажатии кнопки play"""

        easy_button_clicked = self.easy_button.rect.collidepoint(mouse_pos)
        normal_button_clicked = self.normal_button.rect.collidepoint(mouse_pos)
        hard_button_clicked = self.hard_button.rect.collidepoint(mouse_pos)

        if easy_button_clicked or normal_button_clicked or hard_button_clicked and not self.stats.game_active:
            # Cброс статистики
            self.stats.reset_status()
            self.stats.game_active = True
            self.sb.prep_level()
            self.sb.prep_ships()
            self.aliens.empty()
            self.bullets.empty()

            self._create_fleet()
            self.ship.center_ship()

            pygame.mouse.set_visible(False)

    def _difficulty_buttons(self, mouse_pos):
        easy_button_clicked = self.easy_button.rect.collidepoint(mouse_pos)
        normal_button_clicked = self.normal_button.rect.collidepoint(mouse_pos)
        hard_button_clicked = self.hard_button.rect.collidepoint(mouse_pos)

        if easy_button_clicked or normal_button_clicked or hard_button_clicked and not self.stats.game_active:
            pygame.mixer.music.load(
                'alien_invasion/other_files/for_levels.mp3')
            pygame.mixer.music.set_volume(50)
            pygame.mixer.music.play(-1)
            if easy_button_clicked:
                self.settings.dynamic_settings()
                self.settings.alien_speed = 0.7
                self.settings.ship_speed = 1.8
                self.settings.bullet_speed = 1.9
                self._check_play_button(mouse_pos)
            if normal_button_clicked:
                self.settings.dynamic_settings()
                self.settings.alien_speed = 1.0
                self.settings.ship_speed = 1.5
                self.settings.bullet_speed = 1.5
                self._check_play_button(mouse_pos)
            if hard_button_clicked:
                self.settings.dynamic_settings()
                self.settings.alien_speed = 1.8
                self.settings.ship_speed = 0.8
                self.settings.bullet_speed = 0.7
                self._check_play_button(mouse_pos)

    def _fire_bullet(self):
        """Создание нового снаряда и включение его в группу"""

        if len(self.bullets) < self.settings.bullet_allowed:
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)
            fire_sound = pygame.mixer.Sound(
                "alien_invasion/other_files/shot.wav")
            fire_sound.play()

    def _update_bullets(self):
        """Обновляет позиции снарядов и уничтожает старые снаряды"""

        self.bullets.update()

        for bullet in self.bullets.copy():
            if bullet.rect.bottom <= 0:
                self.bullets.remove(bullet)

        self._check_bullet_alien_collisions()

    def _check_bullet_alien_collisions(self):
        if not self.aliens:
            # Уничтожение существующих снарядов и создание нового флота
            self.bullets.empty()
            self._create_fleet()
            self.settings.inscrease_speed()

            # Увеличение уровня
            self.stats.level += 1
            self.sb.prep_level()
        # проверка попаданий в пришельцев.При попадании удаляет снаряд и пришельца
        collisions = pygame.sprite.groupcollide(self.bullets, self.aliens,
                                                True, True)

        if collisions:
            for aliens in collisions.values():
                self.stats.score += self.settings.alien_points * len(aliens)

            hit_sound = pygame.mixer.Sound(
                'alien_invasion/other_files/ufo.wav')
            hit_sound.play()

            self.sb.prep_score()
            self.sb.check_high_score()

    def _create_fleet(self):
        """Создание флота пришельцев"""

        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        avaible_space_x = self.settings.screen_width - (2 * alien_width)
        number_aliens_x = avaible_space_x // (2 * alien_width)
        """Определяет количество рядов, помещающихся на экране"""

        ship_height = self.ship.rect.height
        avaible_space_y = (self.settings.screen_height - (3 * alien_height) -
                           ship_height)
        number_rows = avaible_space_y // (2 * alien_height)

        # Создание флота
        for row_number in range(number_rows):
            for alien_number in range(number_aliens_x):
                self._create_alien(alien_number, row_number)

    def _create_alien(self, alien_number, row_number):
        """Создание пришельца и размещение его в ряду"""

        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        alien.x = alien_width + 2 * alien_width * alien_number
        alien.rect.x = alien.x
        alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
        self.aliens.add(alien)

    def _check_fleet_edges(self):
        """Реакция на достижение края экрана"""

        for alien in self.aliens.sprites():
            if alien.check_edges():
                self._change_fleet_direction()
                break

    def _change_fleet_direction(self):
        """Опускает флот и меняет направление"""

        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1

    def _check_aliens_bottom(self):
        """Проверяет, добрались ли пришельцы до нижнего края экрана"""

        screen_rect = self.screen.get_rect()
        for alien in self.aliens.sprites():
            if alien.rect.bottom >= screen_rect.bottom:
                self._ship_hit()
                break

    def _update_aliens(self):
        """Обновляет позиции всех прищельцев"""

        self._check_fleet_edges()
        self.aliens.update()

        # Проверка коллизий пришельца с кораблём
        if pygame.sprite.spritecollide(self.ship, self.aliens, True):
            self._ship_hit()

        # Проверяет, добрались ли пришельцы до нижнего края экрана
        self._check_aliens_bottom()

    def _create_stars_grid(self):
        """Создание сетки звёзд"""

        # Создание одной звезды
        star = Star(self)

        avaible_star_space_x = self.settings.screen_width
        avaible_star_space_y = self.settings.screen_height

        star_height = star.rect.y
        star_width = star.rect.x

        i = 0

        star_x = [0]
        star_y = [0]
        for i in range(60):
            cur_pos_x = randrange(0, 1900, 50)
            cur_pos_y = randrange(0, 1080, 45)
            for x in star_x:
                if cur_pos_x == x:
                    cur_pos_x = randrange(0, 1900, 50)
                    star_x.append(cur_pos_x)
                    break
                else:
                    star_x.append(cur_pos_x)
                    break

            for y in star_y:
                if cur_pos_y == y:
                    cur_pos_y = randrange(0, 1080, 45)
                    star_y.append(cur_pos_y)
                    break
                else:
                    star_y.append(cur_pos_y)
                    break
            if star_x[i] == 0 and star_y[i] == 0:
                star.remove()

            else:
                self._create_star(star_x[i], star_y[i])

    def _create_star(self, x, y):
        star = Star(self)

        star.rect.x = x
        star.rect.y = y

        self.stars.add(star)

    def _ship_hit(self):
        """Обрабатывает столкновения корабля с пришельцами"""
        if self.stats.ships_left > 0:
            # Уменьшение ships_left
            self.stats.ships_left -= 1

            #Проигравание звука при потере жизни
            ship_hit_sound = pygame.mixer.Sound(
                'alien_invasion/other_files/minus_hp.wav')
            ship_hit_sound.play()

            self.sb.prep_ships()

            # Очистка списков пришельцев и пуль
            self.aliens.empty()
            self.bullets.empty()

            # Созание нового флота и размещение корабля в центре
            self._create_fleet()
            self.ship.center_ship()

            # Пауза
            sleep(0.5)
        else:
            self.stats.game_active = False
            pygame.mixer.music.stop()
            pygame.mouse.set_visible(True)

    def _update_screen(self):
        """Обновляет изображение на экране"""
        self.screen.fill(self.settings.bg_color)

        self.stars.draw(self.screen)
        self.sb.show_score()
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()

        self.aliens.draw(self.screen)

        if not self.stats.game_active:
            self.easy_button.draw_button()
            self.normal_button.draw_button()
            self.hard_button.draw_button()
            self.zerout_record_button.draw_button()
        pygame.display.flip()
class AlienInvasion:
    def __init__(self):
        pygame.init()
        self.settings = Settings()

        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height))
        pygame.display.set_caption("Alien Invasion")

        self.stats = GameStats(self)
        self.sb = ScoreBoard(self)

        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()
        self.aliens = pygame.sprite.Group()

        self._creat_fleet()

        self.play_button = Button(self, 'Play')

        self.sound = pygame.mixer.Sound(
            get_resource_path('music/exicting_music.mp3'))

    def run_game(self):
        while True:
            self._check_events()

            if self.stats.game_active:
                self.ship.update()
                self._update_bullets()
                self._update_aliens()

            self._update_screen()

    def play_sound(self, path):
        self.sounds = pygame.mixer.Sound(get_resource_path(path))
        self.sounds.play()

    def _ship_hit(self):
        if self.stats.ships_left > 0:
            self.play_sound('music/hit_sound.mp3')

            self.stats.ships_left -= 1
            self.sb.prep_ships()

            self.aliens.empty()
            self.bullets.empty()

            self._creat_fleet()
            self.ship.center_ship()
        else:
            self.stats.game_active = False
            self.play_sound('music/hit_sound.mp3')
            self.play_sound('music/lose.mp3')
            self.sound.stop()
            pygame.mouse.set_visible(True)

        sleep(0.5)

    def _creat_fleet(self):
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        available_space_x = self.settings.screen_width - 2 * alien_width
        number_alien_x = available_space_x // (2 * alien_width)

        ship_height = self.ship.rect.height
        available_space_y = (self.settings.screen_height - (3 * alien_height) -
                             ship_height)
        number_rows = available_space_y // (2 * alien_height)

        for row_number in range(number_rows):
            for alien_number in range(number_alien_x):
                self._creat_alien(alien_number, row_number)

    def _creat_alien(self, alien_number, row_number):
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        alien.x = alien_width + 2 * alien_width * alien_number
        alien.rect.x = alien.x
        alien.rect.y = alien.rect.height + 2 * alien_height * row_number
        self.aliens.add(alien)

    def _change_fleet_direction(self):
        """将整群外星人下移 并改变方向"""
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1

    def _check_fleet_edges(self):
        for alien in self.aliens.sprites():
            if alien.check_edges():
                self._change_fleet_direction()
                break

    def _check_events(self):
        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_play_button(self, mouse_pos):
        button_clicked = self.play_button.rect.collidepoint(mouse_pos)
        if button_clicked and not self.stats.game_active:
            self.settings.initialize_dynamic_settings()
            self.stats.reset_stats()
            self.stats.game_active = True
            self.sb.prep_score()
            self.sb.prep_level()
            self.sb.prep_ships()

            self.aliens.empty()
            self.bullets.empty()

            self._creat_fleet()
            self.ship.center_ship()

            pygame.mouse.set_visible(False)
            self.sound.play(-1)

    def _check_keydown_events(self, event):
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = True
        elif event.key == pygame.K_q:
            sys.exit()
        elif event.key == pygame.K_SPACE:
            self._fire_bullet()

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

    def _check_bullet_alien_collisions(self):
        collisions = pygame.sprite.groupcollide(self.bullets, self.aliens,
                                                True, True)

        if collisions:
            self.play_sound('music/hit_sound.mp3')

            for aliens in collisions.values():
                self.stats.score += self.settings.alien_points * len(aliens)
                self.sb.prep_score()
                self.sb.check_high_score()

        if not self.aliens:
            self.bullets.empty()
            self._creat_fleet()
            self.settings.increase_speed()

            self.stats.level += 1
            self.sb.prep_level()
            self.play_sound('music/level_up.mp3')

    def _check_aliens_bottom(self):
        screen_rect = self.screen.get_rect()
        for alien in self.aliens.sprites():
            if alien.rect.bottom >= screen_rect.bottom:
                self._ship_hit()
                break

    def _fire_bullet(self):
        if len(self.bullets) < self.settings.bullet_allowed:
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)

    def _update_bullets(self):
        self.bullets.update()

        for bullet in self.bullets.copy():  # copy() 很重要
            if bullet.rect.bottom <= 0:
                self.bullets.remove(bullet)

        self._check_bullet_alien_collisions()

    def _update_aliens(self):
        self._check_fleet_edges()
        self.aliens.update()

        if pygame.sprite.spritecollideany(self.ship, self.aliens):
            self._ship_hit()

        self._check_aliens_bottom()

    def _update_screen(self):
        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()
        self.aliens.draw(self.screen)

        self.sb.show_score()

        if not self.stats.game_active:
            self.play_button.draw_button()

        pygame.display.flip()  # 翻转 更新屏幕
class AlienInvasion:
    def __init__(self):
        pygame.init()
        self.my_setting = Settings()

        self.screen = pygame.display.set_mode(
            (self.my_setting.screen_width, self.my_setting.screen_height))
        pygame.display.set_caption('Alien Invasion')
        self.color = self.my_setting.bg_color
        '''放在初始化完成下面'''
        self.ship = Ship(self)
        '''子弹'''
        self.bullets = pygame.sprite.Group()
        self.is_bulleting = False
        '''外星人'''
        self.aliens = pygame.sprite.Group()
        self._build_aliens()
        '''游戏状态'''
        self.status = GameStatus(self)
        '''play按钮'''
        self.play_button = Button(self, 'Play')
        '''分数按钮'''
        self.sb = ScoreBoard(self)

    def run_game(self):
        self._auto_fire()
        while True:
            self._check_event()
            if self.status.game_active:
                self.ship.update()
                self._update_bullets()
                self._update_aliens()
            self._update_screen()

    '''--------------------------'''

    def _build_aliens(self):
        alien_sample = Alien(self)

        alien_width = alien_sample.rect.width
        alien_height = alien_sample.rect.height
        '''可用宽度'''
        available_space_x = self.screen.get_rect().width - 2 * alien_width
        available_number_x = available_space_x // (2 * alien_width)
        '''可用高度'''
        available_space_y = self.screen.get_rect().height - 3 * alien_width
        available_number_y = available_space_y // (2 * alien_height)

        for num_y in range(available_number_y):
            for num_x in range(available_number_x):
                alien = self._create_alien(num_x, num_y)
                self.aliens.add(alien)

    def _create_alien(self, num_x, num_y):
        alien = Alien(self)
        alien.x = alien.rect.width + num_x * (2 * alien.rect.width)
        alien.rect.x = alien.x

        alien.y = alien.rect.height + num_y * (2 * alien.rect.width)
        alien.rect.y = alien.y
        return alien

    def _update_bullets(self):
        self.bullets.update()
        for bullet in self.bullets.copy():
            if bullet.rect.bottom <= 0:
                self.bullets.remove(bullet)

        self._check_bullet_alien_collide()

    def _check_bullet_alien_collide(self):
        collisions = pygame.sprite.groupcollide(self.bullets, self.aliens,
                                                True, True)
        '''增加得分'''
        if collisions:
            for aliens in collisions.values():
                for alien in aliens:
                    self.status.score += self.my_setting.per_alien_score
            self.sb.prep_score()
            self.sb.check_high_score()

        if not self.aliens:
            self.bullets.empty()
            self.my_setting._increase_speed()
            self.status.level += 1
            self.sb.prep_level()
            self._build_aliens()

    def _update_aliens(self):
        self._check_alien_edge()
        self.aliens.update()

        if pygame.sprite.spritecollideany(self.ship, self.aliens):
            self._ship_hit()

        self._check_alien_bottom()

    def _ship_hit(self):
        self._reset_scene_status()
        self.status.minus_ship()
        self.sb.prep_ships()
        sleep(1)

    def _check_alien_bottom(self):
        screen_rect = self.screen.get_rect()
        for alien in self.aliens.sprites():
            if alien.rect.bottom >= screen_rect.bottom:
                self._ship_hit()
                break

    def _check_alien_edge(self):
        for alien in self.aliens.sprites():
            if alien.check_edge():
                self._change_alien_direction(alien)
                break

    def _change_alien_direction(self, alien):
        self.my_setting.alien_direction = self.my_setting.alien_direction * (
            -1)
        for alien in self.aliens.sprites():
            alien.y += self.my_setting.alien_spped_y
            alien.rect.y = alien.y

    def _check_event(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.status.save_high_score()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_key_down(event)
            elif event.type == pygame.KEYUP:
                self._check_key_up(event)
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                self._check_mouse_down(mouse_pos)

    def _check_key_down(self, event):
        if event.key == pygame.K_RIGHT:
            self.ship.right_moving = True
        elif event.key == pygame.K_LEFT:
            self.ship.left_moving = True
        elif event.key == pygame.K_q:
            self.status.save_high_score()
            sys.exit()
        elif event.key == pygame.K_SPACE:
            # self._fire_bullet()
            self.fire_job.resume()
        elif event.key == pygame.K_p:
            self._start_game()

    def _check_key_up(self, event):
        if event.key == pygame.K_RIGHT:
            self.ship.right_moving = False
        elif event.key == pygame.K_LEFT:
            self.ship.left_moving = False
        elif event.key == pygame.K_SPACE:
            # self._fire_bullet()
            self.fire_job.pause()

    def _check_mouse_down(self, pos):
        if self.play_button.rect.collidepoint(pos):
            self._start_game()

    def _start_game(self):
        if not self.status.game_active:
            self.status.reset()
            self.sb.prep_score()
            self.sb.prep_high_score()
            self.sb.prep_level()
            self.sb.prep_ships()
            self.status.game_active = True
            self._reset_scene_status()
            self.my_setting._init_dynamic_setting()
            pygame.mouse.set_visible(False)

    def _reset_scene_status(self):
        self.aliens.empty()
        self.bullets.empty()
        self._build_aliens()
        self.ship.center_place()

    def _auto_fire(self):
        scheduler = BackgroundScheduler()
        self.fire_job = scheduler.add_job(self._fire_bullet,
                                          'interval',
                                          seconds=0.1)
        scheduler.start()
        self.fire_job.pause()

    def _update_screen(self):
        self.screen.fill(self.color)

        self.ship.blitme()
        '''绘制子弹'''
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()

        self.aliens.draw(self.screen)
        if not self.status.game_active:
            self.play_button.draw_button()

        self.sb.draw_score()
        pygame.display.flip()

    def _fire_bullet(self):
        if self.status.game_active:
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)
Exemple #7
0
class AlienInvasion:
    """Overall class to manage game assets and behaviour"""
    def __init__(self):
        """Initialize the game, and create game resources"""
        pygame.init()
        #pop_sound = mixer.music.Sound('sounds/bang_02.mp3')

        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("Polandball and the Prussian Invasion")

        self.stats = GameStats(self)
        self.sb = ScoreBoard(self)

        #Set the background color
        self.bg_color = (255, 255, 255)
        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()
        self.aliens = pygame.sprite.Group()

        self._create_fleet()
        self.play_button = Button(self, "Play")

    def run_game(self):
        """Start the main loop for the game."""
        while True:
            self._check_events()
            if self.stats.game_active:
                self.ship.update()
                self._update_bullets()
                self._update_aliens()
            self._update_screen()

    def _check_events(self):
        """Response to keypresses and mouse events"""
        # Watch for 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_play_button(self, mouse_pos):
        """Start a new game when the player clicks play"""
        button_clicked = self.play_button.rect.collidepoint(mouse_pos)
        if button_clicked and not self.stats.game_active:
            self.settings.initialize_dynamic_settings()
            self.stats.reset_stats()
            self.stats.game_active = True
            self.sb.prep_score()
            self.sb.prep_level()
            self.sb.prep_ships()

            self.aliens.empty()
            self.bullets.empty()

            self._create_fleet()
            self.ship.center_ship()

            pygame.mouse.set_visible(False)

    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
        if event.key == pygame.K_LEFT:
            self.ship.moving_left = True
        if event.key == pygame.K_q:
            sys.exit()
        if event.key == pygame.K_SPACE:
            self._fire_bullet()
            #pop_sound.play()

    def _check_keyup_events(self, event):
        """Respond to keyreleases"""
        if event.key == pygame.K_RIGHT:
            # Move the ship to the right
            self.ship.moving_right = False
        if event.key == pygame.K_LEFT:
            self.ship.moving_left = False

    def _fire_bullet(self):
        """Create a new bullet and add it to the bullets group"""
        new_bullet = Bullet(self)
        self.bullets.add(new_bullet)

    def _update_bullets(self):
        self.bullets.update()

        for bullet in self.bullets.copy():
            if bullet.rect.bottom <= 0:
                self.bullets.remove(bullet)

        self._check_bullet_alien_collisions()

    def _ship_hit(self):
        """Respomd to the shit being hit by an alien"""
        if self.stats.ships_left > 0:
            self.stats.ships_left -= 1
            self.sb.prep_ships()

            self.aliens.empty()
            self.bullets.empty()

            self._create_fleet()
            self.ship.center_ship()

            sleep(0.5)
        else:
            self.stats.game_active = False
            pygame.mouse.set_visible(True)

    def _create_fleet(self):
        """Create the fleet of aliens"""
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        available_space_x = self.settings.screen_width - (2 * alien_width)
        number_aliens_x = available_space_x // (2 * alien_width)

        ship_height = self.ship.rect.height
        available_space_y = (self.settings.screen_height - (3 * alien_height) -
                             ship_height)
        number_rows = available_space_y // (2 * alien_height)
        for row_number in range(number_rows):
            for alien_number in range(number_aliens_x):
                self._create_alien(alien_number, row_number)

    def _create_alien(self, alien_number, row_number):
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        alien.x = alien_width + 2 * alien_width * alien_number
        alien.rect.x = alien.x
        alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
        self.aliens.add(alien)

    def _check_fleet_edges(self):
        """Respond appropriately if any aliens have reached an edge"""
        for alien in self.aliens.sprites():
            if alien.check_edges():
                self._change_fleet_direction()
                break

    def _check_bullet_alien_collisions(self):
        """Respond to bullet-alien collisions"""
        collisions = pygame.sprite.groupcollide(self.bullets, self.aliens,
                                                True, True)

        if collisions:
            self.stats.score += self.settings.alien_points
            self.sb.prep_score()
            self.sb.check_high_score()

        if not self.aliens:
            self.settings.initialize_dynamic_settings()
            self.bullets.empty()
            self._create_fleet()
            self.settings.increase_speed()

            self.stats.level += 1
            self.sb.prep_level()

    def _change_fleet_direction(self):
        """Drop the entire fleet and change the fleet's direction"""
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1

    def _check_aliens_bottom(self):
        """Check if any aliens have reached the bottom of the screen"""
        screen_rect = self.screen.get_rect()
        for alien in self.aliens.sprites():
            if alien.rect.bottom >= screen_rect.bottom:
                self._ship_hit()
                break

    def _update_aliens(self):
        """Update the posistions of all aliens in the fleet"""
        self._check_fleet_edges()
        self.aliens.update()

        if pygame.sprite.spritecollideany(self.ship, self.aliens):
            self._ship_hit()

        self._check_aliens_bottom()

    def _update_screen(self):
        """Update images on the screen, and flip to the new screen"""
        # Redraw the screen during each pass through the loop
        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()
        self.aliens.draw(self.screen)

        self.sb.show_score()

        if not self.stats.game_active:
            self.play_button.draw_button()

        # Make the most recently drawn screen visible
        pygame.display.flip()
Exemple #8
0
class AlienInvasion:
    def __init__(self):
        pygame.init()
        self.settings = Settings()
        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_heigth))
        pygame.display.set_caption("Alien INVASION by s0medude")
        self.stats = GameStats(self)
        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()
        self.aliens = pygame.sprite.Group()
        self._create_fleet()
        self.play_button = Button(self)
        self.levels_button = Button(self)
        self.button_levels_list = []
        self.scoreboard = ScoreBoard(self)

    def _check_keydown_events(self, event):
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = True
        elif event.key == pygame.K_q:
            self._save_high_score()
            sys.exit()
        elif event.key == pygame.K_SPACE:
            self._fire_bullet()
        elif event.key == pygame.K_p:
            if not self.stats.game_active:
                self.settings.initialize_dynamic_settings()
                self._start_game()
        elif event.key == pygame.K_r:
            self.stats.game_active = False
            self._reset_stats()
            pygame.mouse.set_visible(True)

    def _check_keyup_events(self, event):
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = False
        if event.key == pygame.K_LEFT:
            self.ship.moving_left = False

    def _check_mouse_events(self):
        mouse_pos = pygame.mouse.get_pos()
        if not self.levels_button.clicked:
            self._check_play_button(mouse_pos)
            self._check_main_levels_button(mouse_pos)
        else:
            self._check_level_button(mouse_pos)

    def _check_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self._save_high_score()
                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:
                self._check_mouse_events()

    def _save_high_score(self):
        filename = 'high_score.json'
        with open(filename, 'w') as f:
            json.dump(self.stats.high_score, f)
            f.close()

    def _draw_bullet(self):
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()

    def _fire_bullet(self):
        if len(self.bullets) < self.settings.bullets_allowed:
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)

    def _check_bullet_alien_collision(self):
        collisions = pygame.sprite.groupcollide(self.bullets, self.aliens,
                                                True, True)
        if collisions:
            for aliens in collisions.values():
                self.stats.score += self.settings.alien_points * len(aliens)
            self.scoreboard.prep_score()
            self.scoreboard.check_high_score()
        self._start_new_level()

    def _start_new_level(self):
        if not self.aliens:
            self.bullets.empty()
            self._create_fleet()
            self.settings.increase_speed()
            self.stats.level += 1
            self.scoreboard.prep_level()

    def _update_bullet(self):
        self.bullets.update()
        for bullet in self.bullets.copy():
            if bullet.rect.bottom <= 0:
                self.bullets.remove(bullet)
        self._check_bullet_alien_collision()

    def _create_alien(self, alien_number, row_number):
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        alien.x = alien_width + (2 * alien_width * alien_number)
        alien.rect.x = alien.x
        alien.rect.y = alien_height + (2 * alien_height * row_number)
        self.aliens.add(alien)

    def _create_fleet(self):
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        ship_height = self.ship.rect.height
        available_space_x = self.settings.screen_width - (2 * alien_width)
        available_space_y = (self.settings.screen_heigth - (3 * alien_height) -
                             ship_height)
        number_aliens_x = available_space_x // (2 * alien_width)
        number_rows = available_space_y // (2 * alien_height)
        for row_number in range(number_rows + 1):
            for alien_number in range(number_aliens_x + 1):
                self._create_alien(alien_number, row_number)

    def _check_fleet_edges(self):
        for alien in self.aliens.sprites():
            if alien.check_edges():
                self._change_fleet_directions()
                break

    def _change_fleet_directions(self):
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_alien_speed
        self.settings.fleet_direction *= -1

    def _ship_hit(self):
        if self.stats.ship_left > 0:
            self.stats.ship_left -= 1
            self.scoreboard.prep_ships()
            self.aliens.empty()
            self.bullets.empty()
            self._create_fleet()
            self.ship.center_ship()
            sleep(0.5)
        else:
            self.stats.game_active = False
            self._reset_stats()
            pygame.mouse.set_visible(True)

    def _check_ship_hit(self):
        if pygame.sprite.spritecollideany(self.ship, self.aliens):
            self._ship_hit()

    def _check_aliens_bottom(self):
        screen_rect = self.screen.get_rect()
        for alien in self.aliens.sprites():
            if alien.rect.bottom >= screen_rect.bottom:
                self._ship_hit()
                break

    def _update_aliens(self):
        self._check_fleet_edges()
        self.aliens.update()
        self._check_ship_hit()
        self._check_aliens_bottom()

    def _draw_main_buttons(self):
        if not self.stats.game_active and not self.levels_button.clicked:
            self.play_button.draw_button("START", 450, 360)
            self.levels_button.draw_button("LEVELS", 750, 360)
        elif not self.stats.game_active and self.levels_button.clicked:
            self._draw_level_buttons()

    def _draw_level_buttons(self):
        number_buttons_x, number_rows_y = 3, 3
        number = 1
        for row in range(number_rows_y):
            row += 1
            for level in range(number_buttons_x):
                level += 1
                button = Button(self)
                button.rect.width, button.rect.height = 150, 50
                button.draw_button(f"Level {str(number)}", 300 * level,
                                   180 * row)
                number += 1
                self.button_levels_list.append(button)

    def _check_play_button(self, mouse_pos):
        if self.play_button.check_button(
                mouse_pos) and not self.stats.game_active:
            self._reset_stats()
            self._start_game()

    def _check_main_levels_button(self, mouse_pos):
        if self.levels_button.check_button(
                mouse_pos) and not self.stats.game_active:
            self._update_screen()

    def _check_level_button(self, mouse_pos):
        for button in self.button_levels_list:
            if button.check_button(mouse_pos) and not self.stats.game_active:
                i = self.button_levels_list.index(button)
                self.stats.level += i
                self.settings.increase_speed(self.stats.level)
                self._start_game()
                self.levels_button.clicked = False

    def _reset_stats(self):
        self.settings.initialize_dynamic_settings()
        self.stats.reset_stats()
        self.levels_button.clicked = False

    def _start_game(self):
        self.stats.game_active = True
        self.scoreboard.prep_images()
        self.bullets.empty()
        self.aliens.empty()
        self._create_fleet()
        self.ship.center_ship()
        pygame.mouse.set_visible(False)

    def _update_screen(self):
        self.screen.fill(self.settings.bg_color)
        self.screen.blit(self.settings.bg_image, self.settings.bg_image_rect)
        self.ship.blitme()
        self._draw_bullet()
        self.aliens.draw(self.screen)
        self.scoreboard.show_score()
        self._draw_main_buttons()
        pygame.display.flip()

    def run_game(self):
        while True:
            self._check_events()
            if self.stats.game_active:
                self.ship.update()
                self._update_bullet()
                self._update_aliens()
            self._update_screen()
Exemple #9
0
class AlienInvasion:

    def __init__(self):
        pygame.init()
        pygame.display.set_caption("Alien Invasion")

        self.settings = Settings()
        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height))

        # 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

        self.stats = GameStats(self)
        self.scoreboard = ScoreBoard(self)

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

        self.aliens = pygame.sprite.Group()
        self._create_fleet()
        self.play_button = Button(self, "Easy", "Medium", "Hard")

        self._initialize_sounds()

    def run_game(self):
        while True:
            self._check_event()
            if self.stats.game_flag:
                self.ship.update()
                self._update_bullets()
                self._update_aliens()
            self._update_screen()

            #print(len(self.bullets))

    def _start_game(self):
        if not self.stats.game_flag:
            self.stats.reset_stats()
            self.stats.game_flag = True
            self.bullets.empty()
            self.aliens.empty()
            self._create_fleet()
            self.ship.center_ship()

            pygame.mouse.set_visible(False)
            
    def _write_high_score(self):
        high_score_file = self.settings.high_score_file
        high_score = self.stats.high_score

        with open(high_score_file, 'w') as file_object:
            json.dump(high_score, file_object)

    def _check_event(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self._write_high_score()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_position = pygame.mouse.get_pos()
                self._check_play_button(mouse_position)

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

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

    def _check_play_button(self, mouse_position):
        easy_button = self.play_button.rect_easy.collidepoint(mouse_position)
        medium_button = self.play_button.rect_medium.collidepoint(mouse_position)
        hard_button = self.play_button.rect_hard.collidepoint(mouse_position)

        if easy_button:
            self.settings.initialize_dynamic_settings()
            self._initialize_game()

        elif medium_button:
            self.settings.medium_game_settings()
            self._initialize_game()
        elif hard_button:
            self.settings.hard_game_settings()
            self._initialize_game()

    def _initialize_game(self):
        self._start_game()
        self.scoreboard.prep_score()
        self.scoreboard.prep_level()
        self.scoreboard.prep_ships()
    
    def _initialize_sounds(self):
        pygame.mixer.music.load(self.settings.game_music)
        pygame.mixer.music.play(-1)
        self.bullet_sound = pygame.mixer.Sound(self.settings.bullet_sound)
        self.collide_sound = pygame.mixer.Sound(self.settings.collide_sound)

    def _check_keydown_events(self, event):
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = True
        elif event.key == pygame.K_p:
            self._start_game()
        elif event.key == pygame.K_q:
            self._write_high_score()
            sys.exit()
        elif event.key == pygame.K_SPACE and self.stats.game_flag == True:
            self.bullet_sound.play()
            self._fire_bullet()

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

    def _fire_bullet(self):
        if len(self.bullets) < self.settings.bullet_allowed:
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)

    def _update_bullets(self):
        self.bullets.update()
        for bullet in self.bullets.copy():
            if bullet.rect.bottom <= 0:
                 self.bullets.remove(bullet)

        self._check_bullet_alien_collisions()

    def _check_bullet_alien_collisions(self):
        collisions = pygame.sprite.groupcollide(
            self.bullets, self.aliens, True, True)

        if not self.aliens:
            self.bullets.empty()
            self._create_fleet()
            self.settings.increase_speed()
            self.stats.level +=1
            self.scoreboard.prep_level()
        
        if collisions:
            for aliens in collisions.values():
                self.stats.score += self.settings.alien_points * len(aliens)
                self.collide_sound.play()

            self.scoreboard.prep_score()
            self.scoreboard.check_high_score()

    def _check_fleet_edges(self):
        for alien in self.aliens.sprites():
            if alien.check_edges():
                self._change_fleet_direction()
                break
    
    def _change_fleet_direction(self):
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_drop_speed
        
        self.settings.fleet_direction *= -1

    def _ship_hit(self):
        if self.stats.ship_left > 0:
            self.stats.ship_left -= 1
            self.scoreboard.prep_ships()
            self.aliens.empty()
            self.bullets.empty()

            self._create_fleet()
            self.ship.center_ship()

            sleep(0.5)
        else:
            self.stats.game_flag = False
            pygame.mouse.set_visible(True)

    def _check_alien_bottom(self):
        screen_rect = self.screen.get_rect()
        for alien in self.aliens.sprites():
            if alien.rect.bottom >= screen_rect.bottom:
                self._ship_hit()
                break

    def _update_aliens(self):
        self._check_fleet_edges()
        self.aliens.update()

        if pygame.sprite.spritecollideany(self.ship, self.aliens):
            self._ship_hit()
        
        self._check_alien_bottom()

    def _create_fleet(self):
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        available_space_x = self.settings.screen_width - (2 * alien_width)
        number_alien_x = available_space_x // (2 * alien_width)

        ship_height = self.ship.rect.height
        available_space_y = (self.settings.screen_height - 
                        (3 * alien_height) - ship_height)

        number_rows = available_space_y // (2 * alien_height)
        for row_number in range(number_rows):
            for alien_number in range(number_alien_x):
                self._create_alien(alien_number, row_number)

    def _create_alien(self, alien_number, row_number):
            alien = Alien(self)
            alien_width, alien_height = alien.rect.size
            alien.x = alien_width + 2 * alien_width * alien_number
            alien.rect.x = alien.x
            alien.y = alien_height + 2 * alien_height * row_number
            alien.rect.y = alien.y

            self.aliens.add(alien)

    def _update_screen(self):
        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()
        self.aliens.draw(self.screen)
        self.scoreboard.show_score()

        if not self.stats.game_flag:
            self.play_button.draw_button()

        pygame.display.flip()
Exemple #10
0
class AlienInvasion(object):
    """
    Класс для управления ресурсами и поведением игры.
    """
    def __init__(self):
        """Инициализирует игру и создает игровые ресурсы."""
        pygame.init()
        pygame.display.set_caption('Alien Invasion')

        self.settings = Settings()

        self.background_color = self.settings.background_color

        if self.settings.fullscreen:
            self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)

        else:
            self.screen = pygame.display.set_mode(
                (self.settings.screen_width, self.settings.screen_height))

        self.stats = GameStats(self)
        self.score = ScoreBoard(self)
        self.play_button = PlayButton(self, 'Play')

        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()
        self.mega_bullets = pygame.sprite.Group()
        self.aliens = pygame.sprite.Group()

        self._create_fleet()

    def _check_events(self):
        """Обрабатывает нажатия клавиш и события мыши."""
        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:
                self._check_play_button(pygame.mouse.get_pos())

    def _check_keydown_events(self, event):

        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True

        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = True

        elif event.key == pygame.K_q or event.key == pygame.K_ESCAPE:
            sys.exit()

        elif event.key == pygame.K_SPACE:
            self._fire_bullet()

        elif event.key == pygame.K_z:
            self._fire_mega_bullet()

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

    def _check_play_button(self, position):
        """Запускает новую игру при нажатии кнопки Play."""
        if self.play_button.rect.collidepoint(
                position) and not self.stats.game_active:
            self.stats.reset_stats()
            self.settings.init_dynamic_settings()
            self.stats.game_active = True

            self.score.prep_score()
            self.score.prep_level()
            self.score.prep_ships()

            self.aliens.empty()
            self.bullets.empty()

            self._create_fleet()
            self.ship.center_ship()

            pygame.mouse.set_visible(False)

    def _check_bullet_alien_collisions(self):

        # Проверка попаданий в пришельцев.
        collisions = pygame.sprite.groupcollide(
            self.bullets,
            self.aliens,
            True,
            True,
        )

        if collisions:
            for aliens in collisions.values():
                self.stats.score += self.settings.alien_points * len(aliens)
            self.score.prep_score()
            self.score.check_high_score()

        self._using_mega_bullets()

        if not self.aliens:
            self.bullets.empty()
            self.mega_bullets.empty()
            self._create_fleet()

            self.settings.increase_speed()
            self.stats.level += 1
            self.score.prep_level()

    def _check_fleet_edges(self):
        """Реагирует на достижение пришельцем края экрана."""
        for alien in self.aliens.sprites():
            if alien.check_edges():
                self._change_fleet_direction()
                break

    def _check_aliens_bottom(self):
        """Проверяет, добрались ли пришельцы до нижнего края экрана."""
        screen_rect = self.screen.get_rect()
        for alien in self.aliens.sprites():
            if alien.rect.bottom >= screen_rect.bottom:
                self._ship_hit()
                break

    def _update_bullets(self):
        """Обновляет позиции снарядов."""
        self.bullets.update()

        # Удаление снарядов, вышедших за край экрана.
        for bullet in self.bullets.copy():
            if bullet.rect.bottom <= 0:
                self.bullets.remove(bullet)

        self._check_bullet_alien_collisions()

    def _update_aliens(self):
        """Обновляет позиции всех пришельцев во флоте."""
        self._check_fleet_edges()
        self.aliens.update()

        # Проверка коллизий "пришелец — корабль".
        if pygame.sprite.spritecollideany(self.ship, self.aliens):
            self._ship_hit()

        self._check_aliens_bottom()

    def _update_screen(self):
        """Обновляет изображения на экране и отображает новый экран."""
        self.screen.fill(self.background_color)
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()
        for mega_bullet in self.mega_bullets.sprites():
            mega_bullet.draw_bullet()
        self.aliens.draw(self.screen)

        # Вывод информации о счете.
        self.score.show_score()

        if not self.stats.game_active:
            self.play_button.draw_button()

        pygame.display.flip()

    def _fire_bullet(self):
        """Создание нового снаряда и включение его в группу bullets."""
        if len(self.bullets) < self.settings.max_bullets:
            self.bullets.add(Bullet(self))

    def _fire_mega_bullet(self):
        self.mega_bullets.add(MegaBullet(self))

    def _create_alien(self, alien_number, row_number):
        """Создание пришельца и размещение его в ряду."""
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        alien.x = alien_width + 2 * alien_width * alien_number
        alien.rect.x = alien.x
        alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
        self.aliens.add(alien)

    def _create_fleet(self):
        """Создание флота вторжения."""
        # Создание одного пришельца, не включенного во флот,
        # для расчета максимального количествыа пришельцев в ряду
        # TODO: оптипизировать
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        available_space_x = self.settings.screen_width - (2 * alien_width)
        number_of_aliens_x = available_space_x // (2 * alien_width)
        available_space_y = (self.settings.screen_height - (3 * alien_height) -
                             self.ship.rect.height)
        number_of_rows_y = available_space_y // (2 * alien_height)

        # Создание флота пришельцев.
        for row_number in range(number_of_rows_y):
            for alien_number in range(number_of_aliens_x):
                self._create_alien(alien_number, row_number)

    def _change_fleet_direction(self):
        """Опускает весь флот и меняет направление флота."""
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_speed
        self.settings.fleet_direction *= -1

    def _using_mega_bullets(self):
        # Обработка читерских пуль
        self.mega_bullets.update()

        for mega_bullet in self.mega_bullets.copy():
            if mega_bullet.rect.bottom <= 0:
                self.mega_bullets.remove(mega_bullet)

        pygame.sprite.groupcollide(
            self.mega_bullets,
            self.aliens,
            False,
            True,
        )

    def _ship_hit(self):
        """Обрабатывает столкновение корабля с пришельцем."""
        self.stats.ships_left -= 1
        self.score.prep_ships()
        if self.stats.ships_left > 0:

            self.aliens.empty()
            self.bullets.empty()

            self._create_fleet()
            self.ship.center_ship()

            time.sleep(2)

        else:
            self.stats.game_active = False
            pygame.mouse.set_visible(True)

    def run_game(self):
        """Запуск основного цикла игры."""
        while True:
            self._check_events()

            if self.stats.game_active:
                self.ship.update()
                self._update_bullets()
                self._update_aliens()

            self._update_screen()
Exemple #11
0
class AlienInvasion:
    """Overall class to manage game assets and behavior."""

    def __init__(self):
         """Initialize the game, and create game resources."""
         pygame.init()  # init of pygame which allows us to use various commands of pygame
         self.settings = Settings()  # default settings are inside Settings class
         self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)  # width and height
         self.settings.screen_width = self.screen.get_rect().width
         self.settings.screen_height = self.screen.get_rect().height
         pygame.display.set_caption("Alien Invasion")  # title
         self.stats = GameStats(self)
         self.sb = ScoreBoard(self)
         self.ship = Ship(self)  # passing current instance of AlienInvasion class to Ship class
         self.bullets = pygame.sprite.Group()  # creates empty group for bullets
         self.aliens = pygame.sprite.Group()  # creates empty group for aliens
         self._create_fleet()
         self.easy_button = Button(self, 'Easy', (0, 255, 0))
         self.medium_button = Button(self, 'Medium', (255, 255, 0))
         self.hard_button = Button(self, 'Hard', (255, 0, 0))

    def run_game(self):
         """Start the main loop for the game."""
         while True:  # this loop runs continuously
             self._check_events()
             if self.stats.game_active:
                 self.ship.update()
                 self._update_bullets()
                 self._update_aliens()
             self._update_screen()

    def _check_events(self):  # helper method starts with underscore
         """Respond to keypresses and mouse events"""
         for event in pygame.event.get():  # watch for the keyboard and mouse events
             if event.type == pygame.QUIT:  # checks if cross button is clicked
                 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_button(mouse_pos)

    def _check_button(self, mouse_pos):
         """Starts a new game when player clicks Play"""
         easy_button_clicked = self.easy_button.rect.collidepoint(mouse_pos)
         medium_button_clicked = self.medium_button.rect.collidepoint(mouse_pos)
         hard_button_clicked = self.hard_button.rect.collidepoint(mouse_pos)

         if easy_button_clicked and not self.stats.game_active:
             self.settings.initialize_dynamic_settings(1.0)
             self._start_game()

         elif medium_button_clicked and not self.stats.game_active:
             self.settings.initialize_dynamic_settings(1.5)
             self._start_game()

         elif hard_button_clicked and not self.stats.game_active:
             self.settings.initialize_dynamic_settings(2.0)
             self._start_game()

    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)

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

    def _check_keydown_events(self, event):
         if event.key == pygame.K_RIGHT:
             self.ship.moving_right = True
         elif event.key == pygame.K_LEFT:
             self.ship.moving_left = True
         elif event.key == pygame.K_q:
             sys.exit()
         elif event.key == pygame.K_SPACE:
             self._fire_bullet()
         # elif event.key == pygame.K_p:
         # self._start_game()

    def _start_game(self):
         self.stats.reset_stats()
         self.stats.game_active = True
         self.sb.prep_score()
         self.sb.prep_level()
         self.sb.prep_ships()
         self.aliens.empty()
         self.bullets.empty()
         self._create_fleet()
         self.ship.center_ship()
         # Hide the mouse cursor.
         pygame.mouse.set_visible(False)

    def _update_bullets(self):
         """Update position of bullets and get rid of old bullets."""
         # Update bullet positions.
         self.bullets.update()
         # Getting rid of the bullets that disappered
         for bullet in self.bullets.copy():
             if bullet.rect.top <= 0:
                 self.bullets.remove(bullet)
         self._check_bullet_alien_collisions()

    def _check_bullet_alien_collisions(self):
         # Check for any bullets that have hit aliens.
         # If so, get rid of the bullet and the alien.
         collisions = pygame.sprite.groupcollide(
             self.bullets, self.aliens, False, True)
         if collisions:
             for aliens in collisions.values():
                 self.stats.score += self.settings.alien_points * len(aliens)
             self.sb.prep_score()
             self.sb.check_high_score()

         if not self.aliens:
             self.bullets.empty()
             self._create_fleet()
             self.settings.increase_speed()
             self.stats.level += 1
             self.sb.prep_level()

    def _create_fleet(self):
         """Create the fleet of aliens."""
         # Create an alien and find the number of aliens in the row
         # Spacing between two aliens is one alien width
         alien = Alien(self)
         alien_width, alien_height = alien.rect.size
         available_width_x = self.settings.screen_width - 2 * alien_width
         number_alien_x = available_width_x // (2 * alien_width)

         ship_height = self.ship.rect.height
         available_height_y = self.settings.screen_height - 3 * alien_height - ship_height
         number_rows = available_height_y // (2 * alien_height)

         # Create the first row of aliens
         for row_number in range(number_rows):
             for alien_number in range(number_alien_x):
                 self._create_alien(alien_number, row_number)

    def _create_alien(self, alien_number, row_number):
         alien = Alien(self)
         alien_width, alien_height = alien.rect.size
         alien.x = alien_width + 2 * alien_width * alien_number
         alien.rect.x = alien.x
         alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
         self.aliens.add(alien)

    def _check_fleet_edges(self):
         """Respond appropriately if any aliens have reached an edge."""
         for alien in self.aliens.sprites():
             if alien.check_edges():
                 self._change_fleet_direction()
                 break

    def _change_fleet_direction(self):
         """Drop the entire fleet and change the fleet's direction."""
         for alien in self.aliens.sprites():
             alien.rect.y += self.settings.fleet_drop_speed
         self.settings.fleet_direction *= -1

    def _update_aliens(self):
         """
         Check if the fleet is at an edge,
         then update the positions of all aliens in the fleet.
         """
         self._check_fleet_edges()
         self.aliens.update()
         if pygame.sprite.spritecollideany(self.ship, self.aliens):
             self._ship_hit()
         self._check_aliens_bottom()

    def _ship_hit(self):
         if self.stats.ships_left > 0:
             self.stats.ships_left -= 1
             self.sb.prep_ships()
             self.bullets.empty()
             self.aliens.empty()
             self._create_fleet()
             self.ship.center_ship()
             sleep(0.5)
         else:
             self.stats.game_active = False
             pygame.mouse.set_visible(True)

    def _check_aliens_bottom(self):
         """If any alien reaches the bottom of the screen"""
         screen_rect = self.screen.get_rect()
         for alien in self.aliens.sprites():
             if alien.rect.bottom >= screen_rect.bottom:
                 self._ship_hit()
                 break

    def _update_screen(self):
         """Update images on the screen, and flip to the new screen."""
         self.screen.fill(self.settings.bg_color)  # sets the bg color
         self.ship.blitme()
         for bullet in self.bullets.sprites():
             bullet.draw_bullet()
         self.aliens.draw(self.screen)
         self.sb.show_score()
         # Draw the play button if the game is inactive.
         if not self.stats.game_active:
             self.easy_button.draw_button('easy')
             self.medium_button.draw_button('medium')
             self.hard_button.draw_button('hard')
         pygame.display.flip()  # Make the most recently drawn screen visible.
Exemple #12
0
class AlienInvasion:
    """初始化游戏资源和行为的类"""
    def __init__(self):
        """初始化游戏并创建游戏资源"""
        pygame.init()  # 初始化背景设置,让 Pygame 能正常工作
        self.settings = Settings()  # 创建Settings实例并用它来访问设置
        # 创建一个显示窗口。参数是元组,单位为像素,返回对象是surface(屏幕的一部分,用于显示游戏元素,这里表示整个游戏窗口)
        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height))
        self.stats = GameStats(self)  # 创建存储游戏统计信息的实例
        self.scoreboard = ScoreBoard(self)  # 创建记分牌
        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()  # 创建用于存储子弹的编组
        self.aliens = pygame.sprite.Group()  # 创建用于存储外星人的编组
        self.play_button = Button(self, "Play")  # 创建 Play 按钮
        self._create_fleet()
        pygame.display.set_caption("Alien Invasion")

    def run_game(self):
        """开始游戏的主循环"""
        while True:  # 通过辅助方法将事务管理与游戏的其他方面(如更新屏幕)分离——重构,使循环变得简单
            self._check_events()
            if self.stats.game_active:
                self.ship.update()
                self._update_bullets()
                self._update_aliens()

            # 每次循环时都重绘屏幕
            self._update_screen()

    def _check_events(self):
        """响应按键和鼠标事件"""
        for event in pygame.event.get():  # 得到一个监听键盘和鼠标事件列表(上一次被调用后发生的所有事件)
            if event.type == pygame.QUIT:  # 玩家单击游戏窗口的关闭按钮时,将检测到 pygame.QUIT事件
                sys.exit()  # 退出游戏
            elif event.type == pygame.KEYDOWN:  # 玩家每次按键都被注册为一个KEYDOWN事件
                self._check_keydown_events(event)
            elif event.type == pygame.KEYUP:
                self._check_keyup_events(event)
            elif event.type == pygame.MOUSEBUTTONDOWN:  # 玩家点击 Play 按钮
                mouse_pos = pygame.mouse.get_pos()
                self._check_play_button(mouse_pos)

    def _check_keydown_events(self, event):
        """响应按键"""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = True
        elif event.key == pygame.K_SPACE:
            self._fire_bullet()
        elif event.key == pygame.K_q:
            sys.exit()

    def _create_fleet(self):
        """创建外星人群"""
        # 创建第一个外星人并计算一行可容纳多少个外星人
        alien = Alien(self)
        alien_width = alien.rect.width
        alien_height = alien.rect.height
        available_space_x = self.settings.screen_width - alien_width
        available_space_y = self.settings.screen_height - 3 * alien_height - self.ship.rect.height
        num_aliens_x = available_space_x // (2 * alien_width)
        num_aliens_rows = available_space_y // (2 * alien_height)

        # 创建外星人群
        for row_number in range(num_aliens_rows):
            for alien_number in range(num_aliens_x):
                self._create_alien(alien_number, row_number, alien_width,
                                   alien_height)

    def _create_alien(self, alien_number, row_number, alien_width,
                      alien_height):
        """创建一个外星人群"""
        alien = Alien(self)
        alien.x = alien_width + alien_number * alien_width * 2
        alien.y = alien_height + 10 + row_number * alien_height * 2
        alien.rect.x = alien.x
        alien.rect.y = alien.y
        self.aliens.add(alien)

    def _fire_bullet(self):
        """创建一颗子弹,并将其加入编组bullets中"""
        if len(self.bullets) < self.settings.bullet_allowed:
            new_bullet = Bullet(self)  # !! 别忘了传入 ai_game
            self.bullets.add(new_bullet)

    def _update_bullets(self):
        """更新子弹的位置并删除消失的子弹"""
        self.bullets.update()  # 对编组调用update()时,编组自动对其中的每个精灵调用 update()

        # 删除消失的子弹
        for bullet in self.bullets.copy():
            if bullet.rect.bottom <= 0:
                self.bullets.remove(bullet)
        # print(len(self.bullets))

        self._check_bullet_alien_collisions()  # 射杀外星人

    def _check_bullet_alien_collisions(self):
        """检查子弹和为行人的碰撞"""
        # 检查是否有子弹击中了外星人,若有则删除相应的子弹和外星人
        collisions = pygame.sprite.groupcollide(self.bullets, self.aliens,
                                                True, True)
        if collisions:  # 记分
            for aliens in collisions.values():  # 保证消灭的每个外星人都计入得分,aliens是个列表
                self.stats.score += self.settings.alien_points * len(aliens)
            self.scoreboard.prep_score()
            self.scoreboard.check_high_score()

        # 若外星人群被消灭,则删除现有的子弹并新建一群外星人,并加快游戏的节奏,提升玩家等级
        if not self.aliens:
            self.bullets.empty()
            self._create_fleet()
            self.settings.increase_speed()
            self.stats.level += 1
            self.scoreboard.prep_level()

    def _update_aliens(self):
        """检查是否有外星人位于屏幕边缘,并更新外星人群中所有外星人的位置"""
        self._check_fleet_edge()
        self.aliens.update()

        # 检测外星人和飞船之间的碰撞
        if pygame.sprite.spritecollideany(self.ship, self.aliens):
            self._ship_hit()

        # 检查是否有外星人到达屏幕底端
        self._check_aliens_bottom()

    def _check_fleet_edge(self):
        """有外星人到达边缘时采取相应的措施"""
        for alien in self.aliens.sprites():
            if alien.check_edge():
                self._change_fleet_direction()
                break

    def _change_fleet_direction(self):
        """将整群外星人下移,并改变方向"""
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1

    def _ship_hit(self):
        """飞船被外星人撞到"""

        if self.stats.ships_left > 0:
            # 将ship_left - 1
            self.stats.ships_left -= 1
            # 更新记分牌
            self.scoreboard.prep_ships()

            # 清空剩余的外星人和子弹
            self.aliens.empty()
            self.bullets.empty()

            # 创建一群新的外星人,并将飞船放在屏幕底部中央
            self._create_fleet()
            self.ship.center_ship()

            # 暂停半秒钟
            sleep(0.5)
        else:
            self.stats.game_active = False  # 游戏结束
            pygame.mouse.set_visible(True)  # 显示隐藏的光标

    def _check_aliens_bottom(self):
        """检查是否有外星人到达了屏幕底端"""
        for alien in self.aliens.sprites():
            if alien.rect.bottom >= self.screen.get_rect().bottom:
                self._ship_hit()  # 像飞船被撞到一样处理
                break

    def _check_play_button(self, mouse_pos):
        """在玩家单击 Play 按钮时开始新游戏"""
        button_checked = self.play_button.rect.collidepoint(mouse_pos)
        if button_checked and not self.stats.game_active:  # 防止用户在游戏过程中点击了按钮所在区域时,游戏重新开始
            # 隐藏鼠标光标
            pygame.mouse.set_visible(False)

            # 重置游戏设置
            self.settings.initialize_dynamic_settings()

            # 重置游戏统计信息
            self.stats.reset_stats()
            self.stats.game_active = True
            self.scoreboard.prep_score()  # 分数要改变
            self.scoreboard.prep_level()  # 等级要改变
            self.scoreboard.prep_ships()  # 余下飞船数要改变

            # 清空余下的外星人和子弹
            self.aliens.empty()
            self.bullets.empty()

            # 创建一群新的外星人,并将飞船放在屏幕底部中央
            self._create_fleet()
            self.ship.center_ship()

    def _check_keyup_events(self, event):
        """响应松开"""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = False
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = False

    def _update_screen(self):
        """更新屏幕上的图像,并切换到新屏幕"""
        self.screen.fill(
            self.settings.bg_color)  # 颜色,fill()方法用于处理surface,只接受一个实参——一种颜色
        self.ship.blitme()  # 绘制飞船
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()
        self.aliens.draw(self.screen)

        # 如果游戏处于非活动状态,就绘制Play按钮
        if not self.stats.game_active:
            self.play_button.draw_button()

        self.scoreboard.show_score_level_ships()  # 显示得分、等级和飞船条数
        pygame.display.flip()  # 让最近绘制的屏幕可见
class AlienAttack:
    """Overall class to manage game assests and characterstics of game"""
    def __init__(self):
        """Initialize the game , and create game resources"""
        pygame.init()
        self.setting = Setting()
        self.bullets = pygame.sprite.Group(
        )  # use for collecting similar type of object
        self.screen = pygame.display.set_mode(
            (0, 0), pygame.FULLSCREEN
        )  # 0 width and 0 length expresses the full screen
        self.setting.screen_width = self.screen.get_rect().width
        self.setting.screen_height = self.screen.get_rect().height
        # pygame.display.set_caption("Alien Invasion")
        self.ship = Ship(self)
        self.enemy = pygame.sprite.Group()
        self.stats = GameStats(self)
        self.score_board = ScoreBoard(self)  #create a score board
        self._create_fleet()
        # as we need only one button then we need to call it once
        self.play_button = Button(self, "Play")

    def _create_fleet(self):
        """Create a fleet of alien"""

        new_enemy = Enemy(self)
        enemy_width, enemy_height = new_enemy.rect.size
        available_space_x = self.setting.screen_width - (2 * enemy_width)
        number_enemy_x = available_space_x // (2 * enemy_width)

        # determine the number of rows that will fit
        ship_height = self.ship.ship_rect.height
        available_space_y = self.setting.screen_height - (
            3 * enemy_height) - ship_height
        number_rows = available_space_y // (2 * enemy_height)

        # create a full fleet of aliens
        for row_number in range(number_rows + 1):
            for enemy_number in range(number_enemy_x + 1):
                self._create_alien(enemy_number, row_number)

    def _create_alien(self, enemy_number, row_number):
        new_enemy = Enemy(self)
        enemy_width, enemy_height = new_enemy.rect.size
        new_enemy.x = enemy_width + 2 * enemy_width * enemy_number
        new_enemy.rect.x = new_enemy.x
        new_enemy.rect.y = new_enemy.rect.height + 2 * new_enemy.rect.height * row_number
        self.enemy.add(new_enemy)

    def run_game(self):
        """Start the main loop for game"""
        while True:
            self._check_event()
            if self.stats.game_active:
                self.ship.update()
                self._update_bullets()
                self._update_enemy()
            self._update_screen()

    def _ship_hit(self):
        """Respond to the ship being hit by alien"""
        # decrement ship left
        if self.stats.ships_left > 0:
            self.stats.ships_left -= 1
            self.score_board.prep_ships()

            # get rid of any remaining aliens and bulllets
            self.enemy.empty()
            self.bullets.empty()

            # Create a new fleet
            self._create_fleet()
            self.ship.center_ship()

            # pause
            sleep(0.5)
        else:
            self.stats.game_active = False
            self.stats.reset_stat()
            self.ship.center_ship()
            pygame.mouse.set_visible(True)
            self.stats.level = 0

    def _update_enemy(self):
        """Update the position of enemy ships"""
        self._check_fleet_edges()
        self.enemy.update()
        # Look for alien-ship collision
        if pygame.sprite.spritecollideany(
                self.ship,
                self.enemy):  # use for collision bw images or rectangles
            self._ship_hit()
        self._check_enemy_bottom()

    def _check_fleet_edges(self):
        """Respond appropriatly if any aliens have reached an edge"""
        for enemy in self.enemy.sprites():
            if enemy.check_edge():
                self._change_fleet_direction()
                break

    def _change_fleet_direction(self):
        """Drop the entire fleet and change the fleet's direction"""
        for enemy in self.enemy.sprites():
            enemy.rect.y += self.setting.fleet_drop_speed
        self.setting.fleet_direction *= -1

    def _update_bullets(self):
        self.bullets.update()

        # get rid of the bullets that have disapperead
        for bullet in self.bullets.copy():
            if bullet.rect.y <= 0:
                self.bullets.remove(bullet)
        self._check_bullet_enemy_collision()

    def _check_bullet_enemy_collision(self):
        """Respond to bullet - alien collision"""
        # check for any bullet that have hit enemy
        # if so , get rid of the bullet and the enemy
        collisions = pygame.sprite.groupcollide(self.bullets, self.enemy, True,
                                                True)
        if not self.enemy:
            self.bullets.empty()
            self._create_fleet()
            self.setting.increase_speed()

            #increase level
            self.stats.level += 1
            self.score_board.prep_level()
        if collisions:
            for enemy in collisions.values():
                self.stats.score += self.setting.enemy_point * len(enemy)
            self.score_board.prep_score()
            self.score_board.check_high_score()

    def _check_event(self):
        """Response to keypress and mouse event"""
        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_event(event)
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                self._check_play_button(mouse_pos)

    def _check_play_button(self, mouse_pos):
        """Start a new game when the player clicked clicks play"""
        button_clicked = self.play_button.rect.collidepoint(mouse_pos)
        if button_clicked and not self.stats.game_active:
            self.stats.reset_stat()
            self.score_board.prep_score()
            self.setting.initialize_dynamic_setting()
            self.stats.game_active = True
            self.score_board.prep_level()
            pygame.mouse.set_visible(False)
            self.score_board.prep_ships()
            # Get rid of any remaining aliens and bullets
            self.enemy.empty()
            self.bullets.empty()

            # create a new fleet and center the ship
            self._create_fleet()
            self.ship.center_ship()

    def _check_keydown_events(self, event):
        """Response to keyup events"""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = True
        elif event.key == pygame.K_UP:
            self.ship.moving_up = True
        elif event.key == pygame.K_DOWN:
            self.ship.moving_down = True
        elif event.key == pygame.K_q:
            sys.exit()
        elif event.key == pygame.K_SPACE:
            self._fire_bullet()

    def _fire_bullet(self):
        if len(self.bullets) < self.setting.bullet_alloewed:
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)

    def _check_keyup_event(self, event):
        """Response to keyup events"""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = False
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = False
        elif event.key == pygame.K_UP:
            self.ship.moving_up = False
        elif event.key == pygame.K_DOWN:
            self.ship.moving_down = False

    def _update_screen(self):
        """update images on the screen, and flip to the new screen"""
        self.screen.fill(self.setting.bg_color)
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()
        self.enemy.draw(self.screen)
        self.score_board.show_score()
        # draw the play button if the game is inactive
        if not self.stats.game_active:
            self.play_button.draw_button()
        """Make the latest change visible on screen"""
        pygame.display.flip()

    def _check_enemy_bottom(self):
        """check if any aliens have reached the bottom of screen"""
        screen_rect = self.screen.get_rect()
        for enemy in self.enemy.sprites():
            if enemy.rect.bottom >= screen_rect.bottom:
                self._ship_hit()
                break