在Python中实现游戏开发,首选必然是pygame。pygame是一组功能强大且有趣的模块,可用于管理图形、图像、动画及声音等,使用户能够更轻松地开发复杂的游戏。本章将介绍如何使用pygame模块进行游戏开发。
学习目标:
掌握pygame的安装方法
掌握pygame模块的基本使用方法
掌握面向对象编程思路
掌握使用Python编写大型程序的方法
本文相关的代码和图片资源:
【免费】Python-游戏开发相关代码文件资源-优快云文库
一.pygame简介
pygame是一组用来开发游戏的Python程序模块,它是在SDL库的基础上开发的。
用户可以利用它,在Python程序中创建功能丰富的游戏和多媒体程序。
pygame是一组高可移植性的模块,可以支持多个操作系统,非常适合小游戏的开发。
SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言编写而成。SDL提供了数种控制图形、图像、声音、输入和输出的函数,使用户只要用相同或相似的代码就可以开发出跨多个平台(Linux,Windows,Mac OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。
由于pygame不是Python默认集成的模块,因此,需要通过pip3指令进行安装,pip3安装命令如下:
pip install pygame
通常需要使用国内代理:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ pygame
安装完成后,输入以下命令,如果出现如下图所示示例图,则说明安装成功。
python -m pygame.examples.aliens
二.pygame常用功能
2.1 创建窗口并显示图片
pygame中最重要的就是surface对象,它是pygame用来表示图像的对象。
2.2.1 pygame.display.set_mode()方法
pygame.display.set_mode()方法用于初始化一个窗口或屏幕。其方法原型如下:
2.2.2 pygame.image.load()方法
pygame.image.load()方法用于加载一张新的图片。其方法原型如下:
使用pygame.image.load()可创建一个包含图像的surface对象。创建完surface对象后,要想显示图像,还需要调用blit()方法,该方法用于将一个图像(surface对象)绘制到另一个图像上方。其方法原型如下:
例子:创建一个窗口,并加载一张图片作为窗口的背景。
#导入所需的模块
import pygame, sys
#导入了 Pygame 库,Pygame 是一个用于编写视频游戏的 Python 模块,也可以用来创建其他类型的多媒体应用程序。
#导入了 Python 的标准库 sys,这通常用于与解释器交互,例如退出程序。
#导入所有pygame.locals里的变量(比如下面大写的QUIT变量)
from pygame.locals import *
#从pygame.locals模块中导入所有名称。这样做是为了方便访问 Pygame 中定义的各种常量(如 QUIT),而不需要每次都使用完整的命名空间(例如,可以直接写 QUIT 而不是 pygame.locals.QUIT)。
#初始化pygame
pygame.init()
#设置窗口的大小,单位为像素
screen = pygame.display.set_mode((500, 400))
#screen = pygame.display.set_mode((500, 400),FULLSCREEN | HWSURFACE)
#如果想要全屏显示游戏界面,可在调用pygame.display.set_mode()方法时设置第二个参数为FULLSCREEN,同时加上硬件加速HWSURFACE
#创建一个背景图片
background = pygame.image.load("./pic/back.png")
#路径 "./pic/back.png" 表示该图片位于当前工作目录下的 pic 文件夹中,如果不在,需要指定文件路径如下:
#("E:\\python学习课件\\第13章/pic/back.png")
#设置窗口标题
pygame.display.set_caption('Hello World')
#程序主循环
#主循环是每个 Pygame 程序的核心部分,它不断地执行,处理用户输入、更新游戏状态和渲染画面。
while True:
screen.blit(background, (0,0)) #把背景复制到窗口的(0,0)处开始贴进去
#获取事件
#遍历所有发生的事件。Pygame 收集用户的输入和其他事件(如鼠标点击、键盘按键等),并将它们放入一个队列中。event.get() 函数返回这个队列中的所有事件。
for event in pygame.event.get():
#判断事件是否为退出事件
if event.type == QUIT:
pygame.quit() #退出pygame #关闭 Pygame 并释放所有资源
sys.exit() #退出系统#完全退出 Python 程序
pygame.display.update() #绘制屏幕内容
#更新整个显示表面的内容到屏幕上。因为 Pygame 使用双缓冲技术,所以需要调用此函数来刷新屏幕,使所有绘制操作可见。
程序运行效果:
2.2 绘制图形
pygame中绘制图形的模块是pygame.draw,该模块中常用的方法如下表所示。
pygame.draw方法的第一个参数总是surface(即surface对象名);
接下来是参数color,表示颜色;
再后就是一系列坐标等。
例子:绘制图形实例。
#导入需要的模块
import pygame, sys
from pygame.locals import *
from math import pi
#导入了 Pygame 和 sys 模块,前者用于图形处理,后者用于系统级别的操作(如退出程序)。
#从 Pygame 的 locals 模块中导入所有名称,以便直接访问常量(如 QUIT)。
#从 Python 的数学库中导入圆周率 pi,用于绘制弧线时的角度计算。
#初始化pygame
pygame.init()
#设置窗口的大小,单位为像素
screen = pygame.display.set_mode((400,300))
#设置窗口标题
pygame.display.set_caption('Drawing')
#定义颜色
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
# 设置背景颜色
screen.fill(WHITE)
#screen.fill("white") #和上面的效果一样
#绘制一条线
pygame.draw.line(screen, RED, [0, 10], [50,10], 2)
#在屏幕上画一条红色的直线,起点坐标为 [0, 10],终点坐标为 [50, 10],线条宽度为 2 像素。
#导入需要的模块绘制一条抗锯齿的线
pygame.draw.aaline(screen, GREEN, [0, 50],[50, 50],True)
#使用 aaline 方法绘制一条绿色的抗锯齿线,最后一个参数 True 表示线条两端封闭。
#绘制一条折线
pygame.draw.lines(screen, BLACK, False, [[0, 80], [50, 80], [50, 120]], 5)
#绘制一条黑色折线,False 表示不闭合,线条宽度为 5 像素。
#绘制一个空心矩形
pygame.draw.rect(screen, BLACK, [75, 10, 50, 20], 2)
#位置和大小由 [75, 10, 50, 20] 指定,最后的参数 2 是边框宽度。
#绘制一个矩形
pygame.draw.rect(screen, BLACK, [150, 10, 50, 20])
#这次没有指定边框宽度,因此默认绘制的是一个实心矩形。
#绘制一个空心椭圆
pygame.draw.ellipse(screen, RED, [225, 10, 50, 20], 2)
#制一个红色的空心椭圆,参数含义同矩形类似,最后的 2 是边框宽度。
#绘制一个实心的红色椭圆
pygame.draw.ellipse(screen, RED, [300, 10, 50, 20])
#
#绘制多边形(三角形)
pygame.draw.polygon(screen, BLACK, [[120, 150], [0, 200], [200, 200]], 5)
#绘制一个黑色的空心三角形,顶点坐标分别为 [120, 150], [0, 200], [200, 200],边框宽度为 5 像素。
#绘制多条弧线
pygame.draw.arc(screen, BLACK,[210, 75, 150, 125], 0, pi/2, 2)
#0, pi/2:这两个参数定义了弧线的起始角度和结束角度,单位是弧度。这里的 0 表示从正 x 轴开始,pi/2 表示到正 y 轴结束,即这条弧线是从右方开始,顺时针方向画到上方。
pygame.draw.arc(screen, GREEN,[210, 75, 150, 125], pi/2, pi, 2)
pygame.draw.arc(screen, BLUE, [210, 75, 150, 125], pi,3*pi/2, 2)
pygame.draw.arc(screen, RED, [210, 75, 150, 125], 3*pi/2, 2*pi, 2)
#绘制四个不同颜色的弧线,它们共同组成一个圆圈。每个弧线由起始角度和结束角度定义,例如第一个弧线从角度 0 开始到 pi/2 结束,宽度为 2 像素。
#[210, 75, 150, 125]:这是一个矩形区域的定义,用于指定弧线所在的椭圆边界框的位置和大小:[210, 75] 是左上角的坐标 (x, y)。150 是宽度。125 是高度。
#绘制一个圆
pygame.draw.circle(screen, BLUE, [200, 250], 40)
#绘制一个蓝色的实心圆,中心坐标为 [200, 250],半径为 40 像素。
#程序主循环
while True:
#获取事件
for event in pygame.event.get():
#判断事件是否为退出事件
if event.type == QUIT:
pygame.quit() #退出pygame
sys.exit() #退出系统
pygame.display.update() #绘制屏幕内容
程序运行效果:
2.3 动画效果
物体移动的原理很简单,即在原有坐标的基础上增加偏移量,再重新绘制图片,依次一张一张地循环绘制下去,就可以得到物体移动的效果。
还有一个问题就是两个画面之间的时间间隔,即经过多长时间绘制下一张图片。
pygame.time模块提供了一个Clock对象,调用其tick()方法即可解决上述问题:
(1)pygame.time.Clock()用于实例化对象以获得pygame的时钟。
(2)调用pygame.time.Clock.tick(FPS)方法设置pygame时钟的间隔时间,其中参数FPS即为帧率(帧率即为每秒钟显示的帧数)。
例:动画效果实例。
#导入需要的模块
import pygame, sys
from pygame.locals import *
#导入了 Pygame 和 sys 模块,前者用于图形处理,后者用于系统级别的操作(如退出程序)。
#从 Pygame 的 locals 模块中导入所有名称,以便直接访问常量(如 QUIT)
#初始化pygame
pygame.init()
# 设置帧率(屏幕每秒刷新的次数)
FPS = 30
#定义每秒刷新屏幕的次数为 30 次(帧率)。这有助于控制动画的速度。
#如果这里改为1,相当于1秒移动一次
#获得pygame的时钟
fpsClock = pygame.time.Clock()
#创建一个时钟对象,用于跟踪时间并确保程序按照设定的帧率运行。
#设置窗口大小
screen = pygame.display.set_mode((500, 400), 0, 32)
#创建一个宽 500 像素、高 400 像素的窗口,深度为 32 位颜色。
#设置标题
pygame.display.set_caption('Animation')
#定义颜色
WHITE = (255, 255, 255)
#加载一张图片
img = pygame.image.load('./pic/yundong.png')
#初始化图片的位置
imgx = 10
imgy = 10
#设置图片初始位置为 (10, 10)。
#初始化图片的移动方向为向右。
direction = 'right'
#程序主循环
while True:
#每次都要重新绘制背景白色
screen.fill(WHITE)
#判断移动的方向,并对相应的坐标做加减
if direction == 'right':
imgx += 5
if imgx == 380:
direction = 'down'
elif direction == 'down':
imgy += 5
if imgy == 300:
direction = 'left'
elif direction == 'left':
imgx -= 5
if imgx == 10:
direction = 'up'
elif direction == 'up':
imgy -= 5
if imgy == 10:
direction = 'right'
#该方法将用于图片绘制到相应的坐标中
screen.blit(img, (imgx, imgy))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
#刷新屏幕
pygame.display.update()
#设置pygame时钟的间隔时间
fpsClock.tick(FPS)
图片的像素水平117,垂直113,可以将FPS = 150,5换成1,移动效果一样,然后把临界值修改为383,287,0,0
2.4 播放声音
对于一般游戏来说,声音分为音效和背景音乐两种。
音效是在某种条件下被触发播放的,音效可采用无压缩的wav格式。
而背景音乐则是时刻伴随着游戏存在的,背景音乐可采用ogg格式或者mp3格式。
2.4.1 播放音效
播放音效使用mixer模块,需要首先生成一个Sound对象,其具体语法格式如下:
2.4.2 播放背景音乐
播放背景音乐使用music模块,music模块是mixer模块中的一个特殊实现,可使用pygame.mixer.music来调用该模块下的方法。
music模块支持的常用方法如下表所示:
例:播放声音实例。
#导入需要的模块
import pygame, sys
from pygame.locals import *
#初始化pygame
pygame.init()
#设置窗口的大小,单位为像素
screen = pygame.display.set_mode((200,150))
#设置窗口的标题
pygame.display.set_caption('Audio')
#定义颜色
WHITE = (255, 255, 255)
#设置背景
screen.fill(WHITE)
#加载并播放一个特效音频文件
sound = pygame.mixer.Sound('sound/bird.wav')
sound.play()
#加载背景音乐文件
pygame.mixer.music.load('sound/Remember.mp3')
#播放背景音乐,第一个参数为播放的次数(-1表示无限循环),第二个参数是设置播放的起点(单位为秒)
pygame.mixer.music.play(-1, 0.0)
#程序主循环
while True:
#获取事件
for event in pygame.event.get():
#判断事件是否为退出事件
if event.type == QUIT:
#停止播放背景音乐
pygame.mixer.music.stop()
#退出pygame
pygame.quit()
#退出系统
sys.exit()
#绘制屏幕内容
pygame.display.update()
2.5 显示文字
如果想要将文字显示到屏幕上,可首先使用pygame.font.Font()创建一个Font对象,其语法格式如下:
创建Font对象后,就可以使用render()方法绘制文本了,其语法格式如下:
最后需要调用blit()方法显示文字。
例:显示文字实例。
#导入需要的模块
import pygame, sys
from pygame.locals import *
#初始化pygame
pygame.init()
#设置窗口的大小,单位为像素
screen = pygame.display.set_mode((300,200))
#设置窗口的标题
pygame.display.set_caption('Font')
#定义颜色
WHITE = (255, 255, 255)
RED = ( 255, 0, 0)
GREEN = ( 0, 255, 0)
#通过字体文件获得字体对象
fontObj = pygame.font.Font('ziti/FZQTFW.TTF', 50)
#fontObj = pygame.font.Font('./ziti/FZQTFW.TTF', 50)#和上面效果一样,有./和没有都表示当前路径
#通过指定的字体文件 'ziti/FZQTFW.TTF' 创建一个字体对象,字号为 50。这个字体文件应该位于当前工作目录下的 ziti 文件夹中。
#配置要显示的文字
textSurfaceObj = fontObj.render('Pygame', True, GREEN, RED)
#获得要显示的对象的rect,可通过get_rect()方法获得一个对象的结构,以便于设置其坐标位置。
textRectObj = textSurfaceObj.get_rect()
#获取文本表面的矩形区域对象,这有助于确定文本的位置和大小。
#设置显示对象的坐标
textRectObj.center = (150, 100)
#设置文本矩形的中心点坐标为 (150, 100),即将文本居中显示在窗口内。
#设置背景
screen.fill(WHITE)
#绘制字体
screen.blit(textSurfaceObj, textRectObj)
#将渲染好的文本表面绘制到屏幕上,位置由 textRectObj 确定。
#程序主循环
while True:
#获取事件
for event in pygame.event.get():
#判断事件是否为退出事件
if event.type == QUIT:
#退出pygame
pygame.quit()
#退出系统
sys.exit()
#绘制屏幕内容
pygame.display.update()
2.6 事件
事件是pygame提供的干预机制。
pygame会接收用户的各种操作(如敲击键盘、移动鼠标、单击鼠标等)产生事件。
一般可使用pygame.event.get()方法来处理所有事件,pygame中常用的事件及含义如下表所示:
例:事件实例。
#导入需要的模块
import pygame, sys
from pygame.locals import *
# 定义颜色
WHITE = (255, 255, 255)
# 初始化pygame
pygame.init()
#设置窗口的大小,单位为像素
screen = pygame.display.set_mode((300,200), 0, 32)
#设置窗口的标题
pygame.display.set_caption('Event')
#设置背景
screen.fill(WHITE)
#程序主循环
while True:
#获取事件
for event in pygame.event.get():
#判断事件是否为退出事件
if event.type == QUIT:
#如果检测到 QUIT 事件(即用户点击了窗口的关闭按钮),则调用 pygame.quit() 关闭 Pygame 并使用 sys.exit() 退出程序。
#退出pygame
pygame.quit()
#退出系统
sys.exit()
#获得鼠标当前的位置
if event.type == MOUSEMOTION:
#如果检测到鼠标移动事件,则打印鼠标的当前位置 event.pos,它是一个包含 x 和 y 坐标的元组。
print(event.pos)
#获得鼠标按下的位置
if event.type == MOUSEBUTTONDOWN:
print("鼠标按下:",event.pos)
#获得鼠标抬起的位置
if event.type == MOUSEBUTTONUP:
print("鼠标抬起:",event.pos)
#获得键盘按下的事件
if event.type == KEYDOWN:
if(event.key==K_UP):
print("上")
if(event.key==K_DOWN):
print("下")
if(event.key==K_LEFT):
print("左")
if(event.key==K_RIGHT):
print("右")
if(event.key==K_w):
print('W键被按下')#需要切换到英文
#按下键盘的Esc键退出
if(event.key==K_ESCAPE):
#退出pygame
pygame.quit()
#退出系统
sys.exit()
# 处理文本输入事件
elif event.type == TEXTINPUT:
print(f"输入的字符是: {event.text}")
#绘制屏幕内容
pygame.display.update()
三.典型案例
3.1 项目要求
开发一款飞机大战游戏,要求:
(1)玩家飞机位于屏幕底部,玩家可按左右方向键来操控飞机;
(2)玩家飞机可发射子弹(按空格键);
(3)敌机在屏幕顶部左右移动;
(4)当玩家飞机发射的子弹射中敌机时结束游戏。
3.2 创建子弹类
该项目可采用面向对象编程思路进行设计,对于不同的对象可设计3个不同的类,分别是子弹类、玩家飞机类和敌机类。
子弹类主要实现的功能是:显示子弹、子弹移动和处理子弹越界问题。
#子弹类
class Bullet(object):
def __init__(self, screen_temp, x, y): #构造方法 初始化子弹对象的属性
self.x = x+40 #子弹起始X坐标
self.y = y-20 #子弹起始Y坐标
self.screen = screen_temp #窗口
self.image = pygame.image.load("./images/bullet.png") #创建一个子弹图片
def display(self): #显示子弹图片的方法
self.screen.blit(self.image, (self.x, self.y)) #将创建的子弹图片按设定的坐标贴到窗口中
def move(self): #子弹移动方法
self.y-=10 #子弹Y坐标自减10
def judge(self): #判断子弹是否越界的方法
if self.y<0: #如果子弹的Y坐标小于0
return True #返回true正确
else:
return False #返回false错误
3.3 创建玩家飞机类
玩家飞机类中主要实现的功能是:显示玩家飞机、控制玩家飞机左右移动以及发射子弹。
#飞机类
class Aircraft_obj(object):
def __init__(self, screen_temp): #构造方法 初始化飞机对象的属性
self.x = 190 #飞起起始X坐标
self.y = 708 #飞机起始Y坐标
self.screen = screen_temp #窗口
self.image = pygame.image.load("./images/hero1.png") #创建一个飞机图
self.bullet_list = []#存储发射出去的子弹对象引用
def display(self): #显示飞机图片的方法(这里包括了显示子弹的图片)
self.screen.blit(self.image, (self.x, self.y)) #将创建的飞机图片按设定的坐标贴到窗口中
#显示飞机发射的所有子弹
for bullet in self.bullet_list:
bullet.display() #显示子弹
bullet.move() #移动子弹
if bullet.judge():#判断子弹是否越界
self.bullet_list.remove(bullet) #将子弹从bullet_list中删除
def move_left(self): #飞机左移方法
if self.x < 10: #X坐标小于10(移动距离)
pass #不做任何事
else:
self.x -= 10 #X坐标自减少10
def move_right(self): #飞机右移方法
if self.x > 480-100-10: #X坐标大于(窗口宽度-飞机宽度-移动距离)的值
pass #不做任何事
else:
self.x += 10 #坐标自增加10
#存储发射子弹的方法
def fire(self):
self.bullet_list.append(Bullet(self.screen, self.x, self.y)) #将发射的子弹对象存储到bullet_list中
3.4 创建敌机类
敌机类中主要实现的功能是:显示敌机、敌机左右移动以及敌机被击中并爆炸。
#敌机类
class EnemyPlane(object):
def __init__(self, screen_temp): #构造方法 初始化敌机对象的属性
self.x = 0 #敌机的起始X坐标
self.y = 0 #敌机的起始Y坐标
self.screen = screen_temp #窗口
self.image = pygame.image.load("./images/enemy0.png") #创建一个敌机图片
self.direction = "right" #用来存储飞机移动方向,默认向右移动
#爆炸效果用的属性
self.hit = False #表示是否要爆炸
self.bomb_lists = [] #用来存储爆炸时需要的图片
self.__crate_images() #调用这个方法向bomb_lists中添加图片
self.image_num = 0#用来记录while循环的次数,当次数达到一定值时才显示一张爆炸的图,然后清空,当这个次数再次达到时,再显示下一个爆炸效果的图片
self.image_index = 0#用来记录当前要显示的爆炸效果的图片的序号
def __crate_images(self): #将爆炸需要的图片添加到self.bomb_lists中
self.bomb_lists.append(pygame.image.load("./images/enemy0_down1.png"))
self.bomb_lists.append(pygame.image.load("./images/enemy0_down2.png"))
self.bomb_lists.append(pygame.image.load("./images/enemy0_down3.png"))
self.bomb_lists.append(pygame.image.load("./images/enemy0_down4.png"))
#判断爆炸的方法,x1表示子弹最左侧的X坐标,x2表示子弹最右侧的X坐标,y表示子弹当前的Y坐标
def blast(self,x1,x2,y):
#判断子弹能命中敌机的三种情况,满足任意一种即可让敌机爆炸,51是敌机图片的宽度,39是敌机图片的高度
#1.子弹横坐标在敌机横坐标的区域中,并且子弹Y坐标小于敌机图片的高度
#2.子弹最右侧坐标等于敌机最左侧坐标,并且子弹Y坐标小于敌机图片的高度
#3.子弹最左侧坐标等于敌机最右侧坐标,并且子弹Y坐标小于敌机图片的高度
if ((x1>=self.x and x2<=self.x+51) or x2==self.x or x1==self.x+51) and y<39:
self.hit = True
def display(self): #显示敌机的方法
#如果被击中,就显示爆炸效果,否则显示普通的飞机效果
if self.hit == True: #如果满足爆炸条件,就显示爆炸的图片
self.screen.blit(self.bomb_lists[self.image_index], (self.x, self.y))
self.image_num+=1 #这是统计循环次数,为了使玩家看清爆炸效果
if self.image_num == 7: #如果循环次数达到7次
self.image_num=0 #将循环次数改为0次
self.image_index+=1 #图片显示序号+1,换为另一张图
if self.image_index>3: #这里爆炸图片一共是四张,所以是图片序号大于三次
time.sleep(1) #暂停一秒
exit() #调用exit让游戏退出
else: #否则显示正常的敌机图片
self.screen.blit(self.image,(self.x, self.y))
def move(self): #敌机移动方法
if self.hit == True:
pass
else:
if self.direction=="right": #如果是向右移动
self.x += 5 #X坐标自增加5
elif self.direction=="left": #如果是向左移动
self.x -= 5 #X坐标自减少5
if self.x>480-50: #如果X坐标大于窗口减去敌机宽度的值
self.direction = "left" #移动方向改为左
elif self.x<0: #如果X坐标小于0
self.direction = "right" #移动方向改为右
3.5 检查键盘输入
#处理鼠标和键盘事件的方法
def key_control(aircraft_temp):
#获取当前等待处理的事件,使用for循环来遍历里面的事件
for event in pygame.event.get():
#判断是否点击了退出按钮
if event.type == QUIT:
print("exit") #输出“exit”
exit() #退出窗口
#判断是不是键盘按下事件
elif event.type == KEYDOWN:
#检测按键是不是a或者left
if event.key == K_a or event.key == K_LEFT:
print('left') #输出“left”
aircraft_temp.move_left() #执行飞机左移方法
#检测按键是不是d或者right
elif event.key == K_d or event.key == K_RIGHT:
print('right') #输出“right”
aircraft_temp.move_right() #执行飞机右移方法
#检测按键是不是空格键
elif event.key == K_SPACE:
print('space') #输出“space”
aircraft_temp.fire() #执行飞机类中存储子弹的方法
3.6 创建主模块
import pygame #导入pygame模块
from pygame.locals import * #导入pygame.locals模块
import time #导入time模块
def main():
#创建窗口
pygame.init() #初始化pygame
screen = pygame.display.set_mode((480,852),0,32)
#创建一个背景图片
background = pygame.image.load("./images/background.png")
#创建一个玩家飞机对象
aircraft = Aircraft_obj(screen)
#创建一个敌机对象
enemy = EnemyPlane(screen)
while True:
screen.blit(background, (0,0)) #显示背景图片
aircraft.display() #执行飞机类中显示飞机的方法
for bullet in aircraft.bullet_list: #遍历飞机对象中存储的子弹信息
x1 = bullet.x #子弹当前横坐标
x2 = bullet.x + 22 #子弹当前横坐标加子弹图片的宽
y1 = bullet.y #子弹当前纵坐标
enemy.blast(x1,x2,y1) #判断子弹的坐标区域有没有与敌机相交
enemy.display() #执行敌机类中显示敌机的方法
enemy.move() #调用敌机的移动方法
pygame.display.update() #更新需要显示的内容到窗口
key_control(aircraft) #处理飞机对象的相关事件
time.sleep(0.01) #暂停0.01秒
main()