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