This time use the pygame module in Python to complete a small game of airplane war; the basic idea is to use the arrow keys to control the left and right movement of the airplane to shoot the spacecraft. Let's look at the final effect first
In order to be completed by novices, this article records the entire process of writing, that is, the code that is modified each time is included, and understandable comments are added to most of the code, look at the final count of words.
A total of 40,000 characters were typed, and I hope to help interested readers!
To complete this project, you must install the pygame third-party library. First, check whether the system is installed with the pip tool through the command line tool.
python -m pip --version
Xiao Tian is a Windows system, here only the detection method of Windows system is provided
If it is not installed, install the pip tool, if you install, please skip this step
python get-pip.py
After the installation is complete, return to the first step to re-check, now install pygame
python -m pip install pygame --user
Or install the third library through pycharm, and now import pygame
import pygame
**Goal: **Create a small aircraft that can move left and right, and the user can control the aircraft to launch bullets through the space key.
First write an empty pygame window, the file name is plane_war.py
"""
- *- coding:uft-8-*-
author:Sweetie
date:2020/6/3"""
import pygame
import sys #Used to exit the game
def run_game():
# Initialize the game
pygame.init()
# Set the resolution of the screen
screen = pygame.display.set_mode((1000,600)) #The size is 1000px by 600px
# Print its type
# print(type(screen)) # <class'pygame.Surface'>
pygame.display.set_caption("Aircraft war") #title
# Variable to store background
bg_img = pygame.image.load("./imgs/bg_img.png") #relative path
print(bg_img)
# Start the main loop of the game
while True:
# In order to prevent the game window from closing immediately after startup, a game loop is added to it(Infinite loop),
for event in pygame.event.get():
# Redraw the screen every time the loop
screen.blit(bg_img,[0,0]) #Draw image
if event.type == pygame.QUIT: #QUIT user requests program to close
sys.exit()
# Update the full display Surface to the screen
pygame.display.flip()run_game()
display.set_mode returns a Surface data type
A game usually has n multiple settings. If you want to change one of the values every time, it is easy to find it in the main file. Now create a new file settings.py to store these information.
"""
- *- coding:uft-8-*-
author:Sweetie
date:2020/6/3"""
import pygame
classSettings:"""Store all settings of the plane war"""
def __init__(self):
# Screen settings
self.screen_width =1000
self.screen_height =600
self.bg_img = pygame.image.load("./imgs/bg_img.png")
# Rewrite now
plane_war.py"""
- *- coding:uft-8-*-
author:Sweetie
date:2020/6/3"""
import pygame
import sys #Used to exit the game
from settings import Settings #Import settings.py
def run_game():
# Initialize the game
pygame.init()
# Set the resolution of the screen
setting =Settings()
screen = pygame.display.set_mode((setting.screen_width, setting.screen_height))
pygame.display.set_caption("Aircraft war") #title
# Start the main loop of the game
while True:
# In order to prevent the game window from closing immediately after startup, a game loop is added to it(Infinite loop),
for event in pygame.event.get():
# Redraw the screen every time the loop
screen.blit(setting.bg_img,[0,0]) #Draw image
if event.type == pygame.QUIT: #QUIT user requests program to close
sys.exit()
# Update the full display Surface to the screen
pygame.display.flip()run_game()
The small plane used here
Now that the image is also available, create a plane.py module, which has a Plane class to store various behaviors of the plane.
"""
- *- coding:uft-8-*-
author:Sweetie
date:2020/6/3"""
import pygame
classPlane:
def __init__(self, screen):
# Initialize the small plane and set its initial position
self.screen = screen
# Load the image and get its rectangular area
self.img_plane = pygame.image.load("./imgs/plane.png")
self.rect = self.img_plane.get_rect() #Get the rectangular area of the small plane
self.screen_rect = self.screen.get_rect() #Get the rectangular area of the screen
# Place the small plane in the bottom center
self.rect.centerx = self.screen_rect.centerx #Center horizontally
self.rect.bottom = self.screen_rect.bottom #bottom
def blitme(self):
# Draw a small plane at the specified location
self.screen.blit(self.img_plane, self.rect)
get_rect will return the rectangular area of the Surface, .centerx and .bottom are its two attributes
Rewrite plane_war.py to draw the small plane on the screen
"""
- *- coding:uft-8-*-
author:Sweetie
date:2020/6/3"""
import pygame
import sys #Used to exit the game
from settings import Settings #Import settings.py
from plane import Plane
def run_game():
# Initialize the game
pygame.init()
# Set the resolution of the screen
setting =Settings()
screen = pygame.display.set_mode((setting.screen_width, setting.screen_height)) #The size is 1000px by 600px
pygame.display.set_caption("Aircraft war") #title
# Create a small plane
plane =Plane(screen)
# Start the main loop of the game
while True:
# In order to prevent the game window from closing immediately after startup, a game loop is added to it(Infinite loop),
for event in pygame.event.get():
# Redraw the screen every time the loop
screen.blit(setting.bg_img,[0,0]) #Draw image
plane.blitme() #Draw the spaceship to the screen
if event.type == pygame.QUIT: #QUIT user requests program to close
sys.exit()
# Update the full display Surface to the screen
pygame.display.flip()run_game()
In order not to make plane_war.py too long and affect the reading, create a module named game_func.py, and use the function of the plane war to make its logic easier to understand
"""
- *- coding:uft-8-*-
author:Sweetie
date:2020/6/3"""
import sys
import pygame
def check_events():
# In order to prevent the game window from closing immediately after startup, a game loop is added to it(Infinite loop),
for event in pygame.event.get():if event.type == pygame.QUIT: #QUIT user requests program to close
sys.exit()
def update_screen(screen, bg_img, plane):
# Update screen image
# Redraw the screen every time the loop
screen.blit(bg_img,[0,0]) #Draw image
plane.blitme() #Draw the spaceship to the screen
# Update the full display Surface to the screen
pygame.display.flip()
The check_events function is used to complete the function that the window will not close, and update_screen is used to complete the function of updating the image. There are 3 formal parameters, Surface object, background image, and small plane function
Because check_events has completed the operation of exiting the game, plane_war.py does not need the sys module. The updated plane_war.py is as follows
"""
- *- coding:uft-8-*-
author:Sweetie
date:2020/6/3"""
import pygame
from settings import Settings #Import settings.py
from plane import Plane
import game_func as fg
def run_game():
# Initialize the game
pygame.init()
# Set the resolution of the screen
setting =Settings()
screen = pygame.display.set_mode((setting.screen_width, setting.screen_height)) #The size is 1000px by 600px
pygame.display.set_caption("Aircraft war") #title
# Create a small plane
plane =Plane(screen)
# Start the main loop of the game
while True:
# Do not close the window
fg.check_events()
# Draw image
fg.update_screen(screen, setting.bg_img, plane)run_game()
The movement is completed by modifying the coordinates of the small plane, which changes regularly when the user presses the arrow keys.
When the user presses a key, an event is registered in pygame. Any event is obtained through pygame.event.get(), so a KEYDOWN event can be registered for each key in the function body.
Now rewrite the check_events function, and move the small plane by detecting the key pressed
def check_events(plane):
# In order to prevent the game window from closing immediately after startup, a game loop is added to it(Infinite loop),
for event in pygame.event.get():if event.type == pygame.QUIT: #QUIT user requests program to close
sys.exit()
elif event.type == pygame.KEYDOWN:if event.key == pygame.K_RIGHT:
# The small plane moves back and forth
plane.rect.centerx +=1
Now press the small plane to move one pixel. In general games, it will keep moving by pressing and not sending. The pygame.KEYUP in Pygame can detect whether the user releases the button. Now combine KEYDOWN and KEYUP to complete a continuous movement
To define a flag bit to determine whether the user presses the button, the default is that once Flase detects that the user presses my home, it is True, and the small plane can continue to move
Since the small plane is controlled by the plane.py file, rewrite this file
"""
- *- coding:uft-8-*-
author:Sweetie
date:2020/6/3"""
import pygame
classPlane:
def __init__(self, screen):
# Initialize the small plane and set its initial position
self.screen = screen
# Load the image and get its rectangular area
self.img_plane = pygame.image.load("./imgs/plane.png")
self.rect = self.img_plane.get_rect() #Get the rectangular area of the small plane
self.screen_rect = self.screen.get_rect() #Get the rectangular area of the screen
# print(self.screen_rect)
# Place the small plane in the bottom center
self.rect.centerx = self.screen_rect.centerx #Center horizontally
self.rect.bottom = self.screen_rect.bottom #bottom
# Flag bit
self.mv_right = False
# Define a method to adjust the position of the small plane
def update(self):
# Adjust the position of the small plane according to the sign
if self.mv_right:
self.rect.centerx +=1
def blitme(self):
# Draw a small plane at the specified location
self.screen.blit(self.img_plane, self.rect)
The update method is when the flag bit is True, the small plane starts to move
Rewrite the check_events function in game_func.py
def check_events(plane):
# In order to prevent the game window from closing immediately after startup, a game loop is added to it(Infinite loop),
for event in pygame.event.get():if event.type == pygame.QUIT: #QUIT user requests program to close
sys.exit()
elif event.type == pygame.KEYDOWN:if event.key == pygame.K_RIGHT:
# The flag bit is True when the user presses the key
plane.mv_right = True
elif event.type == pygame.KEYUP:if event.key == pygame.K_RIGHT:
# When the user releases the key, it is false
plane.mv_right = False
Finally, just call the update method in plane_war.py to complete the continuous movement operation
Use the same method to move left
The rewritten plane.py file
"""
- *- coding:uft-8-*-
author:Sweetie
date:2020/6/3"""
import pygame
classPlane:
def __init__(self, screen):
# Initialize the small plane and set its initial position
self.screen = screen
# Load the image and get its rectangular area
self.img_plane = pygame.image.load("./imgs/plane.png")
self.rect = self.img_plane.get_rect() #Get the rectangular area of the small plane
self.screen_rect = self.screen.get_rect() #Get the rectangular area of the screen
# print(self.screen_rect)
# Place the small plane in the bottom center
self.rect.centerx = self.screen_rect.centerx #Center horizontally
self.rect.bottom = self.screen_rect.bottom #bottom
# Flag bit
self.mv_right = False
self.mv_left = False
# Define a method to adjust the position of the small plane
def update(self):
# Adjust the position of the small plane according to the sign
if self.mv_right:
self.rect.centerx +=1if self.mv_left:
self.rect.centerx -=1
def blitme(self):
# Draw a small plane at the specified location
self.screen.blit(self.img_plane, self.rect)
The check_events function in game_func.py after rewriting
def check_events(plane):
# In order to prevent the game window from closing immediately after startup, a game loop is added to it(Infinite loop),
for event in pygame.event.get():if event.type == pygame.QUIT: #QUIT user requests program to close
sys.exit()
elif event.type == pygame.KEYDOWN:if event.key == pygame.K_RIGHT:
# The flag bit is True when the user presses the key
plane.mv_right = True
elif event.key == pygame.K_LEFT:
plane.mv_left = True
elif event.type == pygame.KEYUP:if event.key == pygame.K_RIGHT:
# When the user releases the key, it is false
plane.mv_right = False
elif event.key == pygame.K_LEFT;
plane.mv_left = False
Now the small plane moves by 1px at a time. The speed is quite slow. Modify the speed of the small plane.
First add a line in setting.py
self.plane_speed =2.5
Now make changes to plane.py
"""
- *- coding:uft-8-*-
author:Sweetie
date:2020/6/3"""
import pygame
classPlane:
def __init__(self, screen, setting):
# Initialize the small plane and set its initial position
self.screen = screen
self.setting = setting #Instantiated attributes
# Load the image and get its rectangular area
self.img_plane = pygame.image.load("./imgs/plane.png")
self.rect = self.img_plane.get_rect() #Get the rectangular area of the small plane
self.screen_rect = self.screen.get_rect() #Get the rectangular area of the screen
# print(self.screen_rect)
# Place the small plane in the bottom center
self.rect.centerx = self.screen_rect.centerx #Center horizontally
self.rect.bottom = self.screen_rect.bottom #bottom
# Modify it to a floating point number
self.center =float(self.rect.centerx)
# Flag bit
self.mv_right = False
self.mv_left = False
# Define a method to adjust the position of the small plane
def update(self):
# Adjust the position of the small plane according to the sign
if self.mv_right:
self.center += self.setting.plane_speed #properties in settings
if self.mv_left:
self.center -= self.setting.plane_speed
# According to self.the value of center to update self.rect.centerx
self.rect.centerx = self.center
def blitme(self):
# Draw a small plane at the specified location
self.screen.blit(self.img_plane, self.rect)
The plane_war.Add an attribute to the plane in py
plane =Plane(screen, setting)
Now the small plane can fly and fly, but there is nothing to restrict him, it can easily fly off the screen. Now limit it to the screen to avoid flying out.
Just modify the update method in plane.py and refactor the check_events function in game_func.py.
With more and more functions of the small plane, check_events is now refactored into three functions, and two functions are defined respectively for capturing user keystrokes and user releasing keys.
Check_events after reconstruction
def check_keydown_events(event, plane):
# Capture user press
if event.key == pygame.K_RIGHT:
# The flag bit is True when the user presses the key
plane.mv_right = True
elif event.key == pygame.K_LEFT:
plane.mv_left = True
def check_keyup_events(event, plane):
# Catch user release
if event.key == pygame.K_RIGHT:
# When the user releases the key, it is false
plane.mv_right = False
elif event.key == pygame.K_LEFT:
plane.mv_left = False
def check_events(plane):
# In order to prevent the game window from closing immediately after startup, a game loop is added to it(Infinite loop),
for event in pygame.event.get():if event.type == pygame.QUIT: #QUIT user requests program to close
sys.exit()
elif event.type == pygame.KEYDOWN:check_keydown_events(event, plane)
elif event.type == pygame.KEYUP:check_keyup_events(event, plane)
The player presses the space to fire a bullet (a small rectangle)
Add the following data in the init method in settings.py
# Bullet settings
self.bullet_speed =3 #speed
self.bullet_width =3 #The width of the bullet
self.bullet_height =15 #Bullet height
self.bullet_color =100,100,100 #The color of the bullet
Create a bullet.py file of the Bullet class that stores bullets
"""
- *- coding:uft-8-*-
author:Sweetie
date:2020/6/3"""
import pygame
from pygame.sprite import Sprite
classBullet(Sprite): #Inherit pygame.Sprite class in sprite
""" Bullet management"""
def __init__(self, setting, screen, plane):super().__init__()
self.screen = screen
# in(0,0)Create a rectangle representing the bullet
# pygame.Rect
# Pygame object used to store rectangular coordinates
self.rect = pygame.Rect(0,0, setting.self.bullet_width, setting.self.bullet_height)
# Set the display position
self.rect.centerx = plane.rect.centerx
self.rect.top = plane.rect.top
# Make the position of the bullet overlap with the small plane, when the bullet flies out, it looks like it was shot from the small plane
# Convert the coordinates of the bullet to a floating point number
self.y =float(self.rect.y)
# The color of the bullet
self.color = setting.bullet.color
# Bullet speed
self.speed = setting.bullet.speed
def update(self):
# Move bullet up
self.y -= self.speed
# According to self.The value of y updates self.rect.y
self.rect.y = self.y
def draw_bullet(self):"""Draw bullet"""
# pygame.draw.rect() draws a rectangular shape
pygame.draw.rect(self.screen, self.color, self.rect)
The Bullet class inherits from the Sprite class in pygame.sprite. This class can group elements in the game and operate all elements in the group at the same time
First, create a group in plane_war.py to store all valid bullets so as to be able to manage the fired bullets; this group is an instance of the pygame.sprite.Group class; the pygame.sprite.Group class is similar to a list, but Provides additional features that help develop games. In the main loop, we will use this group to draw bullets on the screen and update the position of each bullet.
"""
- *- coding:uft-8-*-
author:Sweetie
date:2020/6/3"""
import pygame
from settings import Settings
from plane import Plane
import game_func as fg
from pygame.sprite import Group
def run_game():
# Initialize the game
pygame.init()
# Set the resolution of the screen
setting =Settings()
screen = pygame.display.set_mode((setting.screen_width, setting.screen_height)) #The size is 1000px by 600px
pygame.display.set_caption("Aircraft war") #title
# Create a group to store bullets
bullets =Group()
# Create a small plane
plane =Plane(screen, setting)
# Start the main loop of the game
while True:
# Do not close the window
fg.check_events(plane, setting, screen, bullets)
# Invoke the method of small plane movement
plane.update()
bullets.update()
# Draw image
fg.update_screen(screen, setting.bg_img, plane, bullets)run_game()
Fire
Complete the operation of firing bullets by modifying the function in game_func.py
"""
- *- coding:uft-8-*-
author:Sweetie
date:2020/6/3"""
import sys
from bullet import Bullet
import pygame
def check_keydown_events(event, plane, setting, screen, bullets):
# Capture user press
if event.key == pygame.K_RIGHT:
# The flag bit is True when the user presses the key
plane.mv_right = True
elif event.key == pygame.K_LEFT:
plane.mv_left = True
elif event.key == pygame.K_SPACE:
# Create a bullet and add it to the group bullets
new_bullet =Bullet(setting, screen, plane)
bullets.add(new_bullet)
def check_keyup_events(event, plane):
# Catch user release
if event.key == pygame.K_RIGHT:
# When the user releases the key, it is false
plane.mv_right = False
elif event.key == pygame.K_LEFT:
plane.mv_left = False
def check_events(plane, setting, screen, bullets):
# In order to prevent the game window from closing immediately after startup, a game loop is added to it(Infinite loop),
for event in pygame.event.get():if event.type == pygame.QUIT: #QUIT user requests program to close
sys.exit()
elif event.type == pygame.KEYDOWN:check_keydown_events(event, plane, setting, screen, bullets)
elif event.type == pygame.KEYUP:check_keyup_events(event, plane)
def update_screen(screen, bg_img, plane, bullets):
# Update screen image
# Redraw the screen every time the loop
screen.blit(bg_img,[0,0]) #Draw image
# Draw bullet
for bullet in bullets.sprites():
bullet.draw_bullet() #Draw bullet
plane.blitme() #Draw the spaceship to the screen
# Update the full display Surface to the screen
pygame.display.flip()
After the user presses the space, a bullet (a Bullet instance named new_bullet) is created, and the add method bullets.sprites returns a list that contains all the sprites in the group, traverses the sprites in the group, and passes draw_bullet() draws to the screen
Now that the basic shooting function has been completed, although the bullets disappeared after reaching the top of the screen, it was only because pygame could not draw things outside the screen. These bullets actually still exist, and their y coordinates are negative and decreasing. Continue to consume memory.
Here is a shallow copy through .copy, and then check whether the bullet disappears, and then delete it
Add the following sentence to the while statement in plane_war.py.
# Delete the disappeared bullet
for bullet in bullets.copy():if bullet.rect.bottom <=0:
bullets.remove(bullet)
# print(len(bullets)) #Used to test whether the bullet is deleted
Note: add before fg.update_screen
In order not to make this little game look like opening and hanging, we must limit the number of bullets fired, add a line in settings.py
# Limit the number of bullets
self.bullet_allowed =5
Add a judgment to the body of the check_keydown_events function
Move the fired bullet to the game_func.py file and create an update_bullets
def update_bullets(bullets):
# Call bullet for each bullet in the group.update()
bullets.update()
# Delete the disappeared bullet
for bullet in bullets.copy():if bullet.rect.bottom <=0:
bullets.remove(bullet)
There are only 4 lines of code in the while statement at this time
while True:
fg.check_events(plane, setting, screen, bullets) #Do not close the window
plane.update() #Invoke the method of small plane movement
fg.update_bullets(bullets) #Draw bullet
fg.update_screen(screen, setting.bg_img, plane, bullets)
# Draw image
Now that the small plane has been created, it’s time to create the enemy of the small plane. Also use a class to control all its behaviors. Let’s take a look at this kawaii spaceship first.
Goal: Create it so that it can move at will. It can shoot and kill the spacecraft. When the spacecraft touches the small plane GAMEOVER, the spacecraft touches the ground also GAMEOVER.
Create a file called spaceship.py to store the Spaceship class
"""
- *- coding:uft-8-*-
author:Sweetie
date:2020/6/4"""
import pygame
from pygame.sprite import Sprite
classSpaceship(Sprite):'''Class representing the spaceship'''
def __init__(self, setting, screen):super().__init__()
self.screen = screen
self.setting = setting
# Add spaceship image
self.img = pygame.image.load("./imgs/enemy.png")
# Get rect attribute
self.rect = self.img.get_rect()
# Each ship is initially near the upper left corner of the screen
self.rect.x = self.rect.width #The left margin of the spaceship image is equal to the width of the image
self.rect.y = self.rect.height #The top margin of the spaceship book is equal to the height of the image
self.x =float(self.rect.x)
def blitme(self):
# Draw the spaceship image
self.screen.blit(self.img, self.rect)
Here except the location is basically the same as the Plane class
Instantiate the Spaceship class on the plane_war.Add Spaceship instance in py"""
- *- coding:uft-8-*-
author:Sweetie
date:2020/6/3"""
import pygame
from settings import Settings #Import settings.py
from plane import Plane
import game_func as fg
from pygame.sprite import Group
from spaceship import Spaceship
def run_game():
# Initialize the game
pygame.init()
# Set the resolution of the screen
setting =Settings()
screen = pygame.display.set_mode((setting.screen_width, setting.screen_height)) #The size is 1000px by 600px
pygame.display.set_caption("Aircraft war") #title
# Create a group to store bullets
bullets =Group()
# Create a small plane
plane =Plane(screen, setting)
# Create a spaceship
spaceship =Spaceship(setting, screen)
# Start the main loop of the game
while True:
# Do not close the window
fg.check_events(plane, setting, screen, bullets)
# Invoke the method of small plane movement
plane.update()
# Draw bullet
fg.update_bullets(bullets)
# Draw image
fg.update_screen(screen, setting.bg_img, plane, bullets, spaceship)run_game()
Import the newly created Spaceship class here, create an instance outside the while loop, and pass an instance of the spaceship to update_screen
Modify the update_screen function
def update_screen(screen, bg_img, plane, bullets, spaceship):
# Update screen image
# Redraw the screen every time the loop
screen.blit(bg_img,[0,0]) #Draw image
# Draw bullet
for bullet in bullets.sprites():
bullet.draw_bullet() #Draw bullet
plane.blitme() #Draw the spaceship to the screen
# Draw spaceship
spaceship.blitme()
# Update the full display Surface to the screen
pygame.display.flip()
This is the process of creating an aircraft war map, and the implementation process will be released later~
Recommended Posts