python alien invasion project

Posted by BZero on Thu, 23 Dec 2021 10:27:19 +0100

python alien invasion project (I)
python alien invasion project (II)
python alien invasion project (III)
python alien invasion project (IV)
python alien invasion project (V)
python alien invasion project (6)
python alien invasion project (7)

Shoot aliens

Detect the collision between bullets and aliens

When a bullet hits an alien, we need to know immediately so that the alien can disappear immediately after the collision. For this purpose, we will detect the collision immediately after updating the bullet position. Method sprite Groupcollapse () compares the rect of each bullet with the rect of each alien and returns a dictionary containing the bullet and alien that collided. In this dictionary, each key is a bullet, and the corresponding value is the alien who was hit.

Generate a new group of Aliens

An important feature of this game is that aliens are endless. After an alien population is eliminated, a group of aliens will appear. To display a group of aliens after the alien population is destroyed, first check whether the grouping aliens is empty. If it is empty, call create_fleet() . We will update_ This check is performed in bullets (), because aliens are destroyed here

End the game

Detect alien and spacecraft collisions

We first check the collision between aliens and spacecraft so that we can make appropriate response when aliens collide with spacecraft. After updating the location of each alien, we immediately detect the collision between aliens and spacecraft.

Responding to alien and spacecraft collisions

Now we need to determine what to do when aliens collide with spacecraft. Instead of destroying the ship instance and creating a new ship instance, we track the statistics of the game to record how many times the ship was hit (tracking statistics can also help score). Write a new class for tracking game statistics - GameStats and save it as the file game_stats.py

An alien has reached the bottom of the screen

If an alien reaches the bottom of the screen, we will respond as if an alien hit a spacecraft. Please add a new function to perform this task and name it update_aliens()

game over

Now the game looks more complete, but it will never end, just ships_left continues to become a smaller negative number. Next, add an attribute game as a flag in GameStats_ Active to end the game when the player's ship runs out

Document code:
alien_invasion.py:

import sys
import pygame
from settings import Settings
from ship import Ship
from alien import Alien
import game_functions as gf
from pygame.sprite import Group
from game_stats import GameStats

def run_game():
    # Initialize the game and create a screen object
    pygame.init()
    ai_settings = Settings()
    screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))
    pygame.display.set_caption("Alien Invasion")
    # Create an instance that stores statistics
    stats = GameStats(ai_settings)
    # Create a spaceship
    ship = Ship(ai_settings, screen)
    bullets = Group()
    aliens = Group()
    # Create alien groups
    gf.create_fleet(ai_settings, screen, ship, aliens)
    while True:
        gf.check_events(ai_settings, screen, ship, bullets)
        if stats.game_active:
            ship.update()
            gf.update_bullets(ai_settings, screen, ship, aliens, bullets)
            gf.update_aliens(ai_settings, stats, screen, ship, aliens, bullets)
            gf.update_screen(ai_settings, screen, ship, aliens, bullets)
run_game()

alien.py:

import pygame
from pygame.sprite import Sprite
class Alien(Sprite):
    """Class representing a single alien"""
    def __init__(self, ai_settings, screen):
        """Initialize the alien and set its starting position"""
        super(Alien, self).__init__()
        self.screen = screen
        self.ai_settings = ai_settings
        # Load the alien image and set its rect property
        self.image = pygame.image.load('images/alien.bmp')
        self.rect = self.image.get_rect()
        # Each alien was initially near the upper left corner of the screen
        self.rect.x = self.rect.width
        self.rect.y = self.rect.height
        # Store the exact location of aliens
        self.x = float(self.rect.x)

    def blitme(self):
        """Draw aliens at the specified location"""
        self.screen.blit(self.image, self.rect)

    def check_edges(self):
        """If the alien is at the edge of the screen, return True"""
        screen_rect = self.screen.get_rect()
        if self.rect.right >= screen_rect.right:
            return True
        elif self.rect.left <= 0:
            return True

    def update(self):
        """Move aliens left or right"""
        self.x += (self.ai_settings.alien_speed_factor * self.ai_settings.fleet_direction)
        self.rect.x = self.x

game_functions.py:

import sys
import pygame
from bullet import Bullet
from alien import Alien
from time import sleep

def check_keydown_events(event, ai_settings, screen, ship, bullets):
    """Response key"""
    if event.key == pygame.K_RIGHT:
        ship.moving_right = True
    elif event.key == pygame.K_LEFT:
        ship.moving_left = True
    elif event.key == pygame.K_SPACE:
        fire_bullet(ai_settings, screen, ship, bullets)
    elif event.key == pygame.K_q:
        sys.exit()

def fire_bullet(ai_settings, screen, ship, bullets):
    """If the limit is not reached, fire a bullet"""
    # Create a new bullet and add it to the group bullets
    if len(bullets) < ai_settings.bullets_allowed:
        new_bullet = Bullet(ai_settings, screen, ship)
        bullets.add(new_bullet)

def check_keyup_events(event, ship):
    """Response release"""
    if event.key == pygame.K_RIGHT:
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:
        ship.moving_left = False

def check_events(ai_settings, screen, ship, bullets):
    """Respond to key and mouse events"""
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event, ai_settings, screen, ship, bullets)
        elif event.type == pygame.KEYUP:
            check_keyup_events(event, ship)

def update_screen(ai_settings, screen, ship, aliens, bullets):
    """Update the image on the screen and switch to a new screen"""
    # Redraw the screen each time you cycle
    screen.fill(ai_settings.bg_color)
    for bullet in bullets.sprites():
        bullet.draw_bullet()
    ship.blitme()
    aliens.draw(screen)
    # Make recently drawn screens visible
    pygame.display.flip()

def update_bullets(ai_settings, screen, ship, aliens, bullets):
    """Update the location of bullets and delete disappeared bullets"""
    # Update bullet location
    bullets.update()
    # Delete lost bullets
    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)
    check_bullet_alien_collisions(ai_settings, screen, ship, aliens, bullets)

def check_bullet_alien_collisions(ai_settings, screen, ship, aliens, bullets):
        """In response to the collision between bullets and aliens"""
        # Delete bullets and aliens that collide
        collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
        if len(aliens) == 0:
            # Delete existing bullets and create a new group of aliens
            bullets.empty()
            create_fleet(ai_settings, screen, ship, aliens)

def get_number_aliens_x(ai_settings, alien_width):
    """Calculate how many aliens can be accommodated in each row"""
    available_space_x = ai_settings.screen_width - 2 * alien_width
    number_aliens_x = int(available_space_x / (2 * alien_width))
    return number_aliens_x

def get_number_rows(ai_settings, ship_height, alien_height):
    """Calculate how many lines the screen can hold"""
    available_space_y = (ai_settings.screen_height - (7 * alien_height) - ship_height)
    number_rows = int(available_space_y / (2 * alien_height))
    return number_rows

def create_alien(ai_settings, screen, aliens, alien_number, row_number):
    """Create an alien and place it on the current line"""
    alien = Alien(ai_settings, screen)
    alien_width = alien.rect.width
    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
    aliens.add(alien)

def check_fleet_edges(ai_settings, aliens):
    """Take appropriate measures when aliens reach the edge"""
    for alien in aliens.sprites():
        if alien.check_edges():
            change_fleet_direction(ai_settings, aliens)
            break

def change_fleet_direction(ai_settings, aliens):
    """Move the whole group of aliens down and change their direction"""
    for alien in aliens.sprites():
        alien.rect.y += ai_settings.fleet_drop_speed
    ai_settings.fleet_direction *= -1

def ship_hit(ai_settings, stats, screen, ship, aliens, bullets):
    """Respond to a spaceship hit by aliens"""
    # Ship_ Left minus 1
    if stats.ships_left > 0:
        stats.ships_left -= 1
        # Empty alien list and bullet list
        aliens.empty()
        bullets.empty()
        # Create a new group of aliens and place the spacecraft in the center at the bottom of the screen
        create_fleet(ai_settings, screen, ship, aliens)
        ship.center_ship()
        # suspend
        sleep(0.5)
    else:
        stats.game_active = False

def check_aliens_bottom(ai_settings, stats, screen, ship, aliens, bullets):
    """Check if any aliens have reached the bottom of the screen"""
    screen_rect = screen.get_rect()
    for alien in aliens.sprites():
        if alien.rect.bottom >= screen_rect.bottom:
            # Deal with it like a ship was hit
            ship_hit(ai_settings, stats, screen, ship, aliens, bullets)
            break

def update_aliens(ai_settings, stats, screen, ship, aliens, bullets):
    """ Check whether there are aliens at the edge of the screen and update the position of the whole group of aliens """
    check_fleet_edges(ai_settings, aliens)
    aliens.update()
    # Detect collisions between aliens and spacecraft
    if pygame.sprite.spritecollideany(ship, aliens):
        ship_hit(ai_settings, stats, screen, ship, aliens, bullets)
    check_aliens_bottom(ai_settings, stats, screen, ship, aliens, bullets)

def create_fleet(ai_settings, screen, ship, aliens):
    """Create alien groups"""
    alien = Alien(ai_settings, screen)
    number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width)
    number_rows = get_number_rows(ai_settings, ship.rect.height, alien.rect.height)
    # Create alien groups
    for row_number in range(number_rows):
        for alien_number in range(number_aliens_x):
            create_alien(ai_settings, screen, aliens, alien_number, row_number)

game_stats.py:

class GameStats():
    """Track game statistics"""
    def __init__(self, ai_settings):
        """Initialization statistics"""
        self.ai_settings = ai_settings
        self.reset_stats()
        self.game_active = True

    def reset_stats(self):
        """Initializes statistics that may change during game operation"""
        self.ships_left = self.ai_settings.ship_limit

ship.py:

import pygame
class Ship():
    def __init__(self, ai_settings, screen):
        """Initialize the spacecraft and set its initial position"""
        self.screen = screen
        self.ai_settings = ai_settings
        # Load the ship image and obtain its circumscribed rectangle
        self.image = pygame.image.load('images/ship.bmp')
        self.rect = self.image.get_rect()
        self.screen_rect = screen.get_rect()
        # Place each new ship in the center of the bottom of the screen
        self.rect.centerx = self.screen_rect.centerx
        self.rect.bottom = self.screen_rect.bottom
        # Store small values in the ship's Property center
        self.center = float(self.rect.centerx)
        # Move flag
        self.moving_right = False
        self.moving_left = False

    def update(self):
        if self.moving_right and self.rect.right < self.screen_rect.right:
            self.center += self.ai_settings.ship_speed_factor
        if self.moving_left and self.rect.left > 0:
            self.center -= self.ai_settings.ship_speed_factor
        # According to self Center Update rect object
        self.rect.centerx = self.center


    def blitme(self):
        """Draw the ship at the specified location"""
        self.screen.blit(self.image, self.rect)

    def center_ship(self):
        """Center the ship on the screen"""
        self.center = self.screen_rect.centerx

settings.py:

class Settings():
    """A class that stores all the settings of alien invasion"""
    def __init__(self):
        """Initialize game settings"""
        # screen setting
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (230, 230, 230)
        # Spacecraft settings
        self.ship_speed_factor = 1.5
        # Bullet settings
        self.ship_limit = 3
        self.bullet_speed_factor = 3
        self.bullet_width = 3
        self.bullet_height = 15
        self.bullet_color = 60, 60, 60
        self.bullets_allowed = 3
        self.alien_speed_factor = 0.5
        self.fleet_drop_speed = 10
        # fleet_ A direction of 1 means to move to the right, and a direction of - 1 means to move to the left
        self.fleet_direction = 1

Topics: Python Game Development pygame