Alien Invasion
This blog follows the previous one: Setting up a spaceship to fire bullets https://blog.csdn.net/Ace_bb/article/details/104845723
This blog enables you to add dynamic aliens spacecraft to your game window.
Alien Spacecraft
Spacecraft Picture Resources: Links: https://pan.baidu.com/s/1onui_yfopP2ko1SoqtZ6EQ
Extraction Code: snnw
Depending on the size of the game screen, add a certain number of rows and columns of spacecraft to cover a fixed area of the screen.The ship moves left and right, one cycle to the left and one space down.This cycle achieves the approximation effect of a mobile spaceship.
Steps to achieve:
- Add a single ship
- Add multiple ships to the screen
- To achieve the effect of moving a spaceship from left to right
- Achieve downward movement of spacecraft
Create Alien Class
Similar to Ship, Alien s set the basic properties of aliens, including aliens'pictures, location, size, margins, and so on.
import pygame from pygame.sprite import Sprite class Alien(Sprite): # Humans representing a single aliens def __init__(self,ai_settings,screen): # Initialize aliens and set their starting position super(Alien,self).__init__() self.screen = screen self.ai_settings = ai_settings # Load aliens images and set their screen properties self.image = pygame.image.load('images/alien.bmp') self.rect = self.image.get_rect() # Each alien was originally 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 specified locations self.screen.blit(self.image,self.rect) 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 def check_edges(self): # Return to True if the aliens are at the edge of the screen screen_rect = self.screen.get_rect() if self.rect.right >= screen_rect.right: return True elif self.rect.left <=0: return True
This is the complete code for the Alien class, with functions for updating the location of aliens and for determining whether to move to the boundary, for now.
Next, create an alien instance in the alien_invasion.py main file.
Core Code:
# Create an Alien alien = Alien(ai_settings,screen)
gf.update_screen(ai_settings, screen, ship,aliens,bullets)
Full code:
import sys import pygame from setting import Settings from pygame.sprite import Group from ship import Ship import game_functions as gf from alien import Alien from game_stats import GamStats def run_game(): # Initialize the game and create a screen object pygame.init() #Initialize background settings ai_settings = Settings() screen = pygame.display.set_mode( (ai_settings.screen_width, ai_settings.screen_height)) #Create a sceen window pygame.display.set_caption("Alien Invasion") # Create an instance to store game statistics stats = GamStats(ai_settings) #Create a ship ship = Ship(ai_settings,screen) # Create an Alien alien = Alien(ai_settings,screen) #Set background color bg_color = (230, 230, 230) # Create a group to store bullets and store all valid bullets. # Manage fired bullets bullets = Group() # Create an empty group to store all aliens aliens=Group() # Create an Alien Population gf.create_fleet(ai_settings,screen,ship,aliens) #Start the main cycle of the game #Cycle Control Management Screen Update while True: gf.check_events(ai_settings,screen,ship,bullets) if stats.game_active: ship.update() # Update bullet trajectory gf.update_bullets(ai_settings,screen,ship,aliens,bullets) gf.update_aliens(ai_settings,stats,screen,ship,aliens,bullets) # Update Alien Location gf.update_screen(ai_settings, screen, ship,aliens,bullets) run_game()
This complete code is also the complete code for alien_invasion.py for the entire project.
Then show the Alien ship on the screen
Core Code:
def update_screen(ai_settings, screen, ship,aliens,bullets): # Update the image on the screen and switch to a new screen #Redraw the screen every time you cycle screen.fill(ai_settings.bg_color) #There can only be one parameter for bullet in bullets.sprites(): bullet.draw_bullet() ship.blitme() aliens.draw(screen) # Make recently drawn screens visible pygame.display.flip()
Show multiple rows and aliens
Calculate the number of aliens a row can hold
# Calculate how many aliens each row can hold # Calculate areas that aliens can create, margined from the edge of the screen available_space_x = ai_settings.screen_width - 2*alien_width # Calculate the number of aliens a row can release number_aliens_x = int(available_space_x / (2*alien_width))
The first line of code calculates how much space each line can have to store an alien ship after removing a certain margin, which can be set by itself.
The second line calculates how many aliens can be stored by calculating the vacancies
Calculate how many aliens can be displayed
There should also be margins up and down:
# Calculate how many aliens the screen can hold available_space_y = (ai_settings.screen_height - (3*alien_height)-ship_height) number_rows = int(available_space_y / (2*alien_height))
Create an Alien Population
Modify in alien_invasion.py:
# Manage fired bullets bullets = Group() # Create an empty group to store all aliens aliens=Group() # Create an Alien Population gf.create_fleet(ai_settings,screen,ship,aliens)
gf.update_screen(ai_settings, screen, ship,aliens,bullets)
Modify in game_functions.py:
# Get the number of Aliens def get_number_aliens_x(ai_settings,alien_width): # Calculate how many aliens each row can hold # Calculate areas that aliens can create, margined from the edge of the screen available_space_x = ai_settings.screen_width - 2*alien_width # Calculate the number of aliens a row can release 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 aliens the screen can hold available_space_y = (ai_settings.screen_height - (3*alien_height)-ship_height) number_rows = int(available_space_y / (2*alien_height)) return number_rows # Create Aliens def create_alien(ai_settings,screen,aliens,alien_number,row_number): # Create an aliens and put them 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.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 create_fleet(ai_settings,screen,ship,aliens): # Create an Alien Population # Create an aliens and calculate how many aliens a row can hold # Alien Spacing is Alien Width alien = Alien(ai_settings,screen) # Create an Alien 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 the First Alien for row_number in range(number_rows): for alien_number in range(number_aliens_x): # Create an aliens and add them to your current line create_alien(ai_settings,screen,aliens,alien_number,row_number)
Modified in alien_invasion.py:
# Create an Alien Population gf.create_fleet(ai_settings,screen,ship,aliens)
Realizing Alien Movement
Make the following changes in the settings.py file:
Set the speed of a ship's movement
# Alien Parameter Settings self.alien_speed_factor = 1 # Aliens move down when they hit the edge of the screen self.fleet_drop_speed = 10 # Flet_direction 1 indicates right movement, -1 indicates left movement self.fleet_direction = 1
Make the following modifications in alien.py Alien, an aliens human:
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
Modified in alien_invasion.py:
#Start the main cycle of the game #Cycle Control Management Screen Update while True: gf.check_events(ai_settings,screen,ship,bullets) if stats.game_active: ship.update() # Update bullet trajectory gf.update_bullets(ai_settings,screen,ship,aliens,bullets) gf.update_aliens(ai_settings,stats,screen,ship,aliens,bullets) # Update Alien Location gf.update_screen(ai_settings, screen, ship,aliens,bullets)
Check if aliens are moving to the edge:
In alien.py
def check_edges(self): # Return to True if the aliens are at the edge of the screen screen_rect = self.screen.get_rect() if self.rect.right >= screen_rect.right: return True elif self.rect.left <=0: return True
Move down and change the direction of Aliens
In game_function.py
def check_fleet_edges(ai_settings,aliens): # Take action 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 whole groups 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 update_aliens(ai_settings,stats,screen,ship,aliens,bullets): # Check if aliens have reached the edge check_fleet_edges(ai_settings,aliens) # Update the location of all aliens in the Alien Population aliens.update() # Detecting collisions between aliens and spaceships # Spritecollideanyaccepts two parameters, a sprite and a marshalling. # It checks if any members of the group have collided with the elves and returns None if no collisions have occurred if pygame.sprite.spritecollideany(ship,aliens): print("Ship hit!!!") 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)
In alien_invasion.py
#Start the main cycle of the game #Cycle Control Management Screen Update while True: gf.check_events(ai_settings,screen,ship,bullets) if stats.game_active: ship.update() # Update bullet trajectory gf.update_bullets(ai_settings,screen,ship,aliens,bullets) gf.update_aliens(ai_settings,stats,screen,ship,aliens,bullets) # Update Alien Location gf.update_screen(ai_settings, screen, ship,aliens,bullets)
Complete code in several files:
alien.py file
import pygame from pygame.sprite import Sprite class Alien(Sprite): # Humans representing a single aliens def __init__(self,ai_settings,screen): # Initialize aliens and set their starting position super(Alien,self).__init__() self.screen = screen self.ai_settings = ai_settings # Load aliens images and set their screen properties self.image = pygame.image.load('images/alien.bmp') self.rect = self.image.get_rect() # Each alien was originally 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 specified locations self.screen.blit(self.image,self.rect) 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 def check_edges(self): # Return to True if the aliens are at the edge of the screen screen_rect = self.screen.get_rect() if self.rect.right >= screen_rect.right: return True elif self.rect.left <=0: return True
In the set.py file:
class Settings(): """ Classes that store all settings for the game,Store some basic parameters""" def __init__(self): """ Initialize game settings""" #screen setting self.screen_width = 900 self.screen_height = 600 self.bg_color = (230,230,230) # Ship Settings # Setting the property ship_speed_factor to control the speed of a ship # Move a spaceship 1.5 pixels self.ship_speed_factor = 1.0 self.ship_limit = 3 # Bullet Settings self.bullet_speed_factor = 1 # Bullet Speed self.bullet_width = 3 self.bullet_height = 15 self.bullet_color = 60, 60, 60 self.bullets_allowed = 10 # Limit the number of bullets # Alien Parameter Settings self.alien_speed_factor = 1 # Aliens move down when they hit the edge of the screen self.fleet_drop_speed = 10 # Flet_direction 1 indicates right movement, -1 indicates left movement self.fleet_direction = 1
game_function.py file
import sys import pygame from bullet import Bullet from alien import Alien from time import sleep # Set Keyboard Button Events def check_keydown_events(event,ai_settings,screen,ship,bullets): # Right arrow keys for response keys # Check to see if the right arrow key is pressed by reading event.key if event.key == pygame.K_RIGHT: # Move the ship to the right # ship.rect.centerx += 1 Ship Moves Right ship.moving_right = True elif event.key == pygame.K_LEFT: # Move the ship to the left # ship.rect.centerx -= 1 ship.moving_left = True elif event.key == pygame.K_SPACE: # Set fire instructions fire_bullet(ai_settings, screen, ship, bullets) # Exit the game when Q is pressed elif event.key == pygame.K_q: sys.exit() def check_keyup_events(event ,ship): # Respond Loose 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): """ Response to key and mouse events, specifying events to check in this method """ # Events are acquired through the pygame.event.get() method for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() # Each key registers a KEYDOWN # When a KEYDOWN event is detected, we need to check that a specific key is pressed elif event.type == pygame.KEYDOWN: check_keydown_events(event,ai_settings,screen,ship,bullets) # Event triggered when the arrow key is released, setting move_right or move_left to false 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 every time you cycle screen.fill(ai_settings.bg_color) #There can only be one parameter 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 position of the bullet and remove the disappeared bullet 4303987588749 bullets.update() # Clear out-of-bounds bullets to prevent memory usage # Traverse through the copy of the bullet group, check each bullet in the copy to see if it reaches the top for bullet in bullets.copy(): # Delete bullets if they reach the top if bullet.rect.bottom<=0: bullets.remove(bullet) # print(len(bullets)) # Print out the remaining number of bullets check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets) def check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets): # groupcollide traverses all bullets in the marshalling bullets and all aliens in the marshalling aliens. # groupcollide returns a key-value pair when bullets overlap with an aliens rect collisions = pygame.sprite.groupcollide(bullets,aliens,True,True) if len(aliens) ==0 : # Delete existing bullets and create a group of Aliens bullets.empty() create_fleet(ai_settings,screen,ship,aliens) def fire_bullet(ai_settings, screen, ship, bullets): # Launch a bullet if the limit has not been reached # Create a bullet and add it to the marshalling bullets # Launch bullets when space is pressed, and limit the number of bullets if len(bullets) < ai_settings.bullets_allowed: new_bullet = Bullet(ai_settings, screen, ship) bullets.add(new_bullet) # Get the number of Aliens def get_number_aliens_x(ai_settings,alien_width): # Calculate how many aliens each row can hold # Calculate areas that aliens can create, margined from the edge of the screen available_space_x = ai_settings.screen_width - 2*alien_width # Calculate the number of aliens a row can release 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 aliens the screen can hold available_space_y = (ai_settings.screen_height - (3*alien_height)-ship_height) number_rows = int(available_space_y / (2*alien_height)) return number_rows # Create Aliens def create_alien(ai_settings,screen,aliens,alien_number,row_number): # Create an aliens and put them 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.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 create_fleet(ai_settings,screen,ship,aliens): # Create an Alien Population # Create an aliens and calculate how many aliens a row can hold # Alien Spacing is Alien Width alien = Alien(ai_settings,screen) # Create an Alien 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 the First Alien for row_number in range(number_rows): for alien_number in range(number_aliens_x): # Create an aliens and add them to your current line create_alien(ai_settings,screen,aliens,alien_number,row_number) def check_fleet_edges(ai_settings,aliens): # Take action 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 whole groups 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 update_aliens(ai_settings,stats,screen,ship,aliens,bullets): # Check if aliens have reached the edge check_fleet_edges(ai_settings,aliens) # Update the location of all aliens in the Alien Population aliens.update() # Detecting collisions between aliens and spaceships # Spritecollideanyaccepts two parameters, a sprite and a marshalling. # It checks if any members of the group have collided with the elves and returns None if no collisions have occurred if pygame.sprite.spritecollideany(ship,aliens): print("Ship hit!!!") 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 ship_hit(ai_settings,stats,screen,ship,aliens,bullets): # Respond to ships hit by aliens # Reduce ships_left by 1 if stats.ships_left > 0: stats.ships_left -= 1 # Empty the aliens and bullets lists aliens.empty() bullets.empty() # Create a new group of aliens and place the ship in the center of the bottom of the screen create_fleet(ai_settings,screen,ship,aliens) ship.center_ship() # suspend sleep(0.5) else: stats.geme_active = False def check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bullets): # Check if 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: # Handle as if a ship had been hit ship_hit(ai_settings,stats,screen,ship,aliens,bullets) break
In alien_invasion.py
import sys import pygame from setting import Settings from pygame.sprite import Group from ship import Ship import game_functions as gf from alien import Alien from game_stats import GamStats def run_game(): # Initialize the game and create a screen object pygame.init() #Initialize background settings ai_settings = Settings() screen = pygame.display.set_mode( (ai_settings.screen_width, ai_settings.screen_height)) #Create a sceen window pygame.display.set_caption("Alien Invasion") # Create an instance to store game statistics stats = GamStats(ai_settings) #Create a ship ship = Ship(ai_settings,screen) # Create an Alien alien = Alien(ai_settings,screen) #Set background color bg_color = (230, 230, 230) # Create a group to store bullets and store all valid bullets. # Manage fired bullets bullets = Group() # Create an empty group to store all aliens aliens=Group() # Create an Alien Population gf.create_fleet(ai_settings,screen,ship,aliens) #Start the main cycle of the game #Cycle Control Management Screen Update while True: gf.check_events(ai_settings,screen,ship,bullets) if stats.game_active: ship.update() # Update bullet trajectory gf.update_bullets(ai_settings,screen,ship,aliens,bullets) gf.update_aliens(ai_settings,stats,screen,ship,aliens,bullets) # Update Alien Location gf.update_screen(ai_settings, screen, ship,aliens,bullets) run_game()
The complete code given is actually the whole game, because it is a blog that is written after it is finished, so there is no further split. You can look at it all first, then split it up. Actually, a strong code reader can just look at the code directly.