In this project , To add an alien in the upper left corner of the screen , Then calculate how many aliens can be accommodated on the screen according to the alien's margin and screen size , To create a series of Aliens , Make it fill the top half of the size screen ;

Then we need to make aliens move to both sides and below until they are shot down by aliens , An alien collides with a spaceship or an alien arrives at the bottom of the screen , Shooting down all aliens , When aliens hit the ship or reach the bottom of the screen , Another group of aliens will appear on the screen ;

In order to avoid endless repetition of the game and boring , Can limit the number of ships available to players , When the number of ships runs out , game over .

The code is shown below :

1.alien_invasion.py
import sys import pygame from time import sleep from settings import Settings
from ship import Ship from bullet import Bullet from alien import Alien from
game_stats import GameStats class AlienInvasion: """ Classes that manage game resources and behaviors """ def
__init__(self): """ Initialize games and create game resources """ pygame.init() self.settings = Settings()
self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
self.settings.screen_width = self.screen.get_rect().width
self.settings.screen_height = self.screen.get_rect().height
pygame.display.set_caption("Alien Invasion") # Create an instance to store game statistics self.stats =
GameStats(self) self.ship = Ship(self) self.bullets = pygame.sprite.Group()
self.aliens = pygame.sprite.Group() self._create_fleet() def run_game(self):
""" Start the main cycle of 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 _update_bullets(self): """ Update the location of bullets and delete missing bullets """ #
Update bullet location self.bullets.update() # Delete missing bullets for bullet in self.bullets.copy(): if
bullet.rect.bottom <= 0: # ######## There are changes here # if bullet.rect.right >=
self.ship.screen_rect.right: self.bullets.remove(bullet)
self._check_bullet_alien_collisions() def _check_bullet_alien_collisions(self):
""" Responding to the impact of bullets and aliens """ # Delete bullets and aliens that collide pygame.sprite.groupcollide(self.bullets,
self.aliens, True, True) '''
function sprite.groupcollide() For each element in a group rect For each element in the same group rect And compare . ''' if not
self.aliens: # Delete all existing bullets and create a new group of Aliens self.bullets.empty() self._create_fleet() def
_update_aliens(self): """ Check if there are aliens at the edge of the screen , And update the location of all aliens in the alien population """
self._check_fleet_edges() self.aliens.update() # Detect collisions between aliens and spacecraft if
pygame.sprite.spritecollideany(self.ship, self.aliens): print("Ship hit!!!")
self._ship_hit() # Check if any aliens have reached the bottom of the screen self._check_aliens_bottom() def
_ship_hit(self): """ The response ship was hit by aliens """ if self.stats.ships_left > 0: #
take ships_left reduce 1 self.stats.ships_left -= 1 # Empty the remaining aliens and bullets self.aliens.empty()
self.bullets.empty() # Create a new group of Aliens , And put the spacecraft in the center at the bottom of the screen self._create_fleet()
self.ship.center_ship() # suspend sleep(0.5) else: self.stats.game_active = False
def _check_events(self): """ Respond to key and mouse events """ for event in pygame.event.get(): if
event.type == pygame.QUIT: sys.exit() elif event.type == pygame.KEYDOWN: # Press the key
self._check_keydown_events(event) elif event.type == pygame.KEYUP: # Release key
self._check_keyup_events(event) def _check_keydown_events(self, event): """
Response key """ if event.key == pygame.K_RIGHT: # The key pressed is the right arrow key # Move the ship to the right
self.ship.moving_right = True elif event.key == pygame.K_LEFT: # The key pressed is the left arrow key #
Move the ship to the left self.ship.moving_left = True elif event.key == pygame.K_UP: # Move the ship up
self.ship.moving_up = True elif event.key == pygame.K_DOWN: # Move the ship down
self.ship.moving_down = True elif event.key == pygame.K_q: sys.exit() elif
event.key == pygame.K_SPACE: self._fire_bullet() def _check_keyup_events(self,
event): """ Response release """ if event.key == pygame.K_RIGHT: # The released key is the right arrow key
self.ship.moving_right = False elif event.key == pygame.K_LEFT: # The released key is the left arrow key
self.ship.moving_left = False elif event.key == pygame.K_UP: # The released key is the up arrow key
self.ship.moving_up = False elif event.key == pygame.K_DOWN: # The released key is the down arrow key
self.ship.moving_down = False def _fire_bullet(self): """
Create a bullet , And add it to the group bullets in """ if len(self.bullets) <
self.settings.bullets_allowed: new_bullet = Bullet(self)
self.bullets.add(new_bullet) def _create_fleet(self): """ Create alien colony """ #
Create an alien and calculate how many aliens a row can hold # Alien spacing is alien width alien = Alien(self) alien_width,
alien_height = alien.rect.size availiable_space_x = self.settings.screen_width
- (2 * alien_width) number_aliens_x = availiable_space_x // (2 * alien_width) +
1 # Calculate how many lines of aliens the screen can hold ship_height = self.ship.rect.height availiable_space_y =
(self.settings.screen_height - (3 * alien_height) - ship_height) number_rows =
availiable_space_y // (2 * alien_height) # Create alien colony 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 add it to the current 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 # It's important here !!! # If writing : #
alien.rect.x = alien_width + 2 * alien_width * alien_number # There will only be a list of aliens on the screen #
as a result of (alien_width + 2 * alien_width * alien_number) #
Is to calculate the position of the current alien on the current line , Then use alien attributes x To set its rect Location of , This is the process of creating alien ranks , It doesn't show the alien movement #
alien Is a class Alien() Instance of , stay Alien() in alien.x Changing all the time , Utilization function _update_aliens() to update , To show aliens moving left and right
alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
self.aliens.add(alien) def _check_fleet_edges(self): """ Take appropriate measures when aliens reach the edge """
for alien in self.aliens.sprites(): if alien.check_edges():
self._change_fleet_firection() break 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: # Deal with it like a ship was hit
self._ship_hit() break def _change_fleet_firection(self): """ Move the whole group of aliens down , And change their direction
""" for alien in self.aliens.sprites(): alien.rect.y +=
self.settings.fleet_drop_speed self.settings.fleet_direction *= -1 def
_update_screen(self): """ Update image on screen , And switch to a 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)
pygame.display.flip() if __name__ == '__main__': # Create a game instance and run the game ai =
AlienInvasion() ai.run_game()
2.settings.py
class Settings: """ Store games 《 Alien invasion 》 Classes for all settings in """ def __init__(self): """ Initialize game settings
""" # screen setting self.screen_width = 1500 self.screen_height = 800 self.bg_color =
(227, 227, 227) # Spacecraft setup self.ship_speed = 1.5 # speed : Each cycle will move 1.5 pixel self.ship_limit
= 3 # Number of spacecraft limit # Bullet setup self.bullet_speed = 3.0 self.bullet_width = 3
self.bullet_height = 15 self.bullet_color = (60, 60, 60) # Bullet color
self.bullets_allowed = 10 # Number of bullets allowed in the screen # Alien settings self.alien_speed = 1.0
self.fleet_drop_speed = 10 # fleet_direction by 1 Indicates shift right , by -1 Indicates shift left self.fleet_direction
= 1
3.alien.py
import pygame from pygame.sprite import Sprite class Alien(Sprite): """
Class representing a single alien """ def __init__(self, ai_game): """ Initialize aliens and set their starting position """
super().__init__() self.screen = ai_game.screen self.settings =
ai_game.settings # Load alien images and set their rect attribute self.image =
pygame.image.load('images/alien.bmp') self.rect = self.image.get_rect() #
Every alien was originally near the top left corner of the screen self.rect.x = self.rect.width self.rect.y = self.rect.height #
Store the exact horizontal position of Aliens self.x = float(self.rect.x) def check_edges(self): """
If aliens are at the edge of the screen , Just return True """ screen_rect = self.screen.get_rect() if self.rect.right
>= screen_rect.right or self.rect.left <= 0: return True def update(self): """
Move aliens left or right """ self.x += (self.settings.alien_speed *
self.settings.fleet_direction) self.rect.x = self.x
4.ship.py
import pygame class Ship: """ Classes for managing spacecraft """ def __init__(self, ai_game): """
Initialize the spacecraft and set its initial position """ self.screen = ai_game.screen self.settings = ai_game.settings
self.screen_rect = ai_game.screen.get_rect() # Load the ship image and get its circumscribed rectangle self.image =
pygame.image.load('images/ship.bmp') self.rect = self.image.get_rect() #
For every new ship , Put it in the center at the bottom of the screen self.rect.midbottom = self.screen_rect.midbottom # #
Make the spaceship appear in the center of the screen instead of the center at the bottom of the screen # self.rect.center = self.screen_rect.center # #
Make the spaceship appear on the left side of the screen # self.rect.midleft = self.screen_rect.midleft # Attributes on the ship x Store decimal value in
self.x = float(self.rect.x) self.y = float(self.rect.y) # Move flag
self.moving_right = False self.moving_left = False self.moving_up = False
self.moving_down = False def update(self): """ Adjust the position of the spacecraft according to the moving signs """ #
Update the ship instead of rect Object's x value if self.moving_right and self.rect.right <
self.screen_rect.right: self.x += self.settings.ship_speed if self.moving_left
and self.rect.left > 0: self.x -= self.settings.ship_speed # Update the ship instead of rect Object's y value
if self.moving_down and self.rect.bottom < self.screen_rect.bottom: self.y +=
self.settings.ship_speed if self.moving_up and self.rect.top > 0: self.y -=
self.settings.ship_speed # according to self.x to update rect object self.rect.x = self.x #
according to self.y to update rect object self.rect.y = self.y def center_ship(self): """ Center the ship at the low end of the screen """
self.rect.midbottom = self.screen_rect.midbottom self.x = float(self.rect.x)
def blitme(self): """ Draw the spaceship at the specified position """ self.screen.blit(self.image, self.rect)
5.bullet.py
import pygame from pygame.sprite import Sprite class Bullet(Sprite): """
The class that manages the bullets fired by the spacecraft """ def __init__(self, ai_game): """ Create a bullet position at the current position of the ship """
super().__init__() self.screen = ai_game.screen self.settings =
ai_game.settings self.color = self.settings.bullet_color #
stay (0,0) Creates a rectangle representing bullets at , Then set the correct position self.rect = pygame.Rect(0, 0,
self.settings.bullet_width, self.settings.bullet_height) self.rect.midtop =
ai_game.ship.rect.midtop # Store bullet position in decimal self.y = float(self.rect.y) # self.x =
float(self.rect.x) def update(self): """ Move the bullet up """ # Update decimal value indicating bullet position self.y -=
self.settings.bullet_speed # Update for bullets rect Location of self.rect.y = self.y # def
update(self): # """ Move the bullet to the right """ # # Update decimal value indicating bullet position # self.x +=
self.settings.bullet_speed # # Update for bullets rect Location of # self.rect.x = self.x def
draw_bullet(self): """ Draw bullets on screen """ pygame.draw.rect(self.screen, self.color,
self.rect)
6.game_stats.py
class GameStats: """ Track game statistics """ def __init__(self, ai_game): """ Initialize statistics
""" self.settings = ai_game.settings self.reset_stats() # The game was active when it first started
self.game_active = True def reset_stats(self): """ Initialize statistics that may change during game operation """
self.ships_left = self.settings.ship_limit

Technology
Daily Recommendation