Pygame库200行代码实现简易飞机大战
本文通过200行Python代码演示如何使用Pygame库开发简易飞机大战游戏。内容涵盖Pygame模块介绍、环境安装配置、游戏原理分析以及核心代码实现,包括敌机生成、碰撞检测和精灵组管理等关键功能,适合初学者快速上手。
在开始之前需要说明,本实验的主要目的是帮助作者熟悉Pygame库的使用,因此游戏的部分细节可能尚不完善,敬请谅解。

安装使用库
Pygame简介
Pygame是一个跨平台的Python模块,专为电子游戏设计,支持图像和声音处理。它建立在SDL(Simple DirectMedia Layer)基础之上,允许开发者在无需受限于低级语言的情况下进行实时电子游戏研发,从而将精力集中在游戏架构的设计上。
Pygame中主要模块介绍
(1) pygame
pygame模块会自动导入其他相关的Pygame模块。
该模块包含surface函数,用于返回一个新的surface对象。init()函数是Pygame游戏的核心部分,必须在进入主游戏循环之前调用,它会自动初始化所有其他模块。
(2) pygame.locals
该模块包含在自定义模块作用域内使用的名称(变量),包括事件类型、按键定义和视频模式等的常量。
(3) pygame.display
该模块包含处理Pygame显示方式的函数,支持普通窗口和全屏模式。Pygame.display中一些常用的方法如下:
- flip:用于更新整个显示屏幕。
- update:当只需更新屏幕部分区域时使用。
- set_mode:用于设定显示的类型和尺寸。
- set_caption:用于设定Pygame程序的窗口标题。
- get_surface:在调用flip和blit之前,返回一个可用于绘图的surface对象。
(4) pygame.font
该模块包含font函数,用于渲染和显示不同的字体样式。
(5) pygame.sprite
涉及游戏精灵(Sprite)的管理,Group类用作sprite对象的容器。调用group对象的update方法时,会自动调用所有sprite对象的update方法。
(6) pygame.mouse
用于隐藏鼠标光标以及获取鼠标当前的位置坐标。
(7) pygame.event
用于追踪鼠标单击、按键按下和释放等用户交互事件。
(8) pygame.image
用于处理保存在GIF、PNG或JPEG格式文件内的图像数据。
注:在本程序中,除了local模块和font模块未被使用外,其他模块均有涉及。
Pygame的安装
你可以选择使用PyCharm工具栏下方的python packages搜索Pygame进行安装,当然也可以使用CMD命令行中常用的pip install pygame命令来安装。
如果安装过程中因网速慢导致超时,可以指定国内镜像源进行加速。
pip install -i 国内镜像地址 包名
例如:pip install -i https://mirrors.aliyun.com/pypi/simple/ numpy
国内常用的源镜像地址包括:
清华:https://pypi.tuna.tsinghua.edu.cn/simple 阿里云:http://mirrors.aliyun.com/pypi/simple/ 中国科技大学: https://pypi.mirrors.ustc.edu.cn/simple/ 豆瓣:http://pypi.douban.com/simple/
验证安装
为了验证Pygame是否安装成功,可以在CMD命令行中使用pip list语句。如果安装成功,可以在输出结果中找到相关版本信息。

程序原理
首先创建游戏的主窗体,主窗体的大小应与背景图片的尺寸保持一致。
import pygame
#游戏初始化
pygame.init()
#创建游戏主窗口
screen = pygame.display.set_mode((480,700))
#绘制背景图香
#1 加载图像数据
background = pygame.image.load('./image/background.png')
#2 blit绘制图像
#从左上角绘制
screen.blit(background,(0,0))
pygame.display.update()
#卸载所有的模块
pygame.quit()
在绘制图像时需注意方向问题,后续主机、敌机、背景和子弹的绘制均需遵循这一方向设定。

在背景图像绘制完成后,接着绘制主机和敌机。所有绘制工作完成后,可以统一调用update方法来刷新屏幕显示。
#绘制飞机图片
hero = pygame.image.load('./image/hero2.png')
screen.blit(hero,(150,300))
pygame.display.update()
飞机大战的原理与动画片类似,需要对玩家按下的指令做出反应,从而形成连贯的画面。这里需要用到Pygame库中的time模块来控制帧率。
#创造时钟对象 屏幕绘制速率
clock = pygame.time.Clock()
#游戏循环
while True:
#指定循环体内部代码的执行频率 每秒重复60次
clock.tick(60)
#将移动前飞机进行遮挡 达到动画效果
screen.blit(background, (0, 0))
screen.blit(hero,hero_rect)
如果尝试停止程序发现点击窗口右上角的关闭按钮无反应,是因为尚未在循环体内进行事件监听并对事件类型进行判断处理。
event_list = pygame.event.get()
for event in event_list:
#判断是否为退出事件
if event.type == pygame.QUIT:
print("退出游戏...")
#卸载所有模块
pygame.quit()
exit()
关于敌机的生成,需要使用到sprite精灵和精灵组模块。创建两个相同的敌机对象,但赋予它们不同的飞行速度,然后将敌机精灵添加到敌机精灵组中。在循环体中,不断对敌机精灵组进行绘制即可实现敌机移动效果。
enemy = GameSprite("./image/enemy0.png")
enemy1 = GameSprite("./image/enemy0.png",2)
enemy_group = pygame.sprite.Group(enemy,enemy1)
#精灵组调用方法
enemy_group.update()
enemy_group.draw(screen)
对上述部分代码进行整理和简化后,可以得到主机和敌机均可移动的效果,最终呈现如图示。
import pygame
from plane_sprites import *
#游戏初始化
pygame.init()
#创建游戏主窗口
screen = pygame.display.set_mode((480,700))
#绘制背景图香
#1 加载图像数据
background = pygame.image.load('./image/background.png')
#2 blit绘制图像
#从左上角绘制
screen.blit(background,(0,0))
#3 update更新屏幕显示
# pygame.display.update()
#绘制飞机图片
hero = pygame.image.load('./image/hero2.png')
screen.blit(hero,(150,300))
#可以在所有绘制工作完成后,统一调用update方法
pygame.display.update()
#创造时钟对象 屏幕绘制速率
clock = pygame.time.Clock()
#定义飞机初始位置
hero_rect = pygame.Rect(150,300,100,122)
#敌机精灵创建
enemy = GameSprite("./image/enemy0.png")
enemy1 = GameSprite("./image/enemy0.png",2)
enemy_group = pygame.sprite.Group(enemy,enemy1)
#游戏循环
while True:
#指定循环体内部代码的执行频率 每秒重复60次
clock.tick(60)
#监听时间
event_list = pygame.event.get()
# if len(event_list)>0:
# print(event_list)
for event in event_list:
#判断是否为退出事件
if event.type == pygame.QUIT:
print("退出游戏...")
#卸载所有模块
pygame.quit()
exit()
hero_rect.y -= 1
if hero_rect.y <=0:
hero_rect.y = 700
#将移动前飞机进行遮挡 达到动画效果
screen.blit(background, (0, 0))
screen.blit(hero,hero_rect)
#精灵组调用方法
enemy_group.update()
enemy_group.draw(screen)
pygame.display.update()
pass
pygame.quit()

程序升级
设置飞机大战的精灵类和常量
这里的update方法主要为了在后续的背景类、敌机类和子弹类中实现垂直飞行的效果。
#屏幕大小
SCREEN_RECT = pygame.Rect(0,0,480,700)
#刷新帧率
SCREEN_PER_SEC = 60
#创建敌机的定时器常量
CREATE_ENEMY_EVENT = pygame.USEREVENT
#英雄发射子弹事件
HERO_FIRE_EVENT = pygame.USEREVENT + 1
class GameSprite(pygame.sprite.Sprite):
def __init__(self,image_name,speed=1):
#调用父类初始化方法
super().__init__()
#定义对象属性
self.image = pygame.image.load(image_name)
self.rect = self.image.get_rect()
self.speed = speed
#更新显示
def update(self):
self.rect.y += self.speed
背景类和敌机类
为了实现背景随游戏进程移动的效果,在背景类的__init__中设置了is_alt参数,用于将背景添加到原图像的上方,从而达成背景滚动的视觉效果。在敌机类中,对敌机的位置进行判断,如果敌机超出预设屏幕Y轴方向,则使用kill()方法从精灵组中将其删除。敌机生成的位置和速度采用了random随机数的randint()方法生成。
class Background(GameSprite):
#游戏背景滚动
def __init__(self,is_alt=False):
#调用父类中精灵中的创建 image/rect/speed
super().__init__("./image/background.png")
if is_alt:
self.rect.y = -self.rect.height
def update(self):
super().update()
#如果移出屏幕,将图像移到屏幕上访
if self.rect.y >= SCREEN_RECT.height:
self.rect.y = -self.rect.height
class Enemy(GameSprite):
#敌机精灵
def __init__(self):
#1 调用父类方法 创建敌机精灵
super().__init__("./image/enemy0.png")
#2 指定敌机初始随机速度
self.speed = random.randint(1,2)
#3 指定敌机初始随机位置
self.rect.bottom = 0
max_x = SCREEN_RECT.width - self.rect.width
self.rect.x = random.randint(0,max_x)
def update(self):
#!调用父类方法 垂直方向飞行
super().update()
#2 判断是否飞出屏幕 如果是,需要从精灵组中删除
if self.rect.y >= SCREEN_RECT.height:
print("飞出屏幕,需要从精灵组中删除...")
#kill方法可以将精灵从精灵族中移出,精灵自动销毁
self.kill()
def __del__(self):
print("敌机死亡 %s" % self.rect)
主机类和子弹类
SCREEN_RECT.centerx用于保证主机初始位置位于屏幕中央。关于主机的Y坐标,由于一开始绘制了示意图,此处应设置为屏幕的SCREEN_RECT.bottom减去一定距离。
子弹类中与敌机类同理,需要判断子弹是否飞出屏幕范围,如果超出则使用kill()方法从精灵组中删除。子弹的初始位置应位于主机上方,即子弹的X坐标等于主机的X坐标。

#主角飞机
class Hero(GameSprite):
def __init__(self):
# 调用父类 设置英雄图像和速度
super().__init__("./image/hero2.png",0)
# 设置主机位置
self.rect.centerx = SCREEN_RECT.centerx
self.rect.bottom = SCREEN_RECT.bottom - 50
# 子弹精灵组
self.bullet_group = pygame.sprite.Group()
def update(self):
#水平方向移动
self.rect.x += self.speed
#控制英雄不能为0
if self.rect.x < 0:
self.rect.x =0
elif self.rect.right > SCREEN_RECT.right:
self.rect.right = SCREEN_RECT.right
#子弹发射
def fire(self):
print("发射子弹...")
#创建子弹精灵
bullet = Bullet()
#设置子弹位置
bullet.rect.bottom = self.rect.y-20
bullet.rect.centerx = self.rect.centerx
#添加到子弹精灵组中
self.bullet_group.add(bullet)
#子弹类
class Bullet(GameSprite):
def __init__(self):
#调用父类方法 设置子弹图片速度
super().__init__("./image/bullet1.png",-2)
def update(self):
#调用父类方法 让子弹垂直飞行
super().update()
#判断子弹是否飞出
if self.rect.bottom < 0:
self.kill()
def __del__(self):
print("子弹被销毁")
主游戏类
在主类中进行精灵组的创建,其中背景精灵组的创建是为了实现背景滚动的效果。
#精灵组的创建
def __create_sprites(self):
#创建背景精灵和精灵1组
bg1 = Background()
bg2 = Background(True)
self.back_group = pygame.sprite.Group(bg1,bg2)
#创建敌机精灵和精灵组
self.enemy_group = pygame.sprite.Group(
#创建英雄精灵和精灵组
self.hero = Hero()
self.hero_group = pygame.sprite.Group(self.hero)
游戏的初始化
def __init__(self):
print("游戏初始化")
#创建游戏窗口
self.screen = pygame.display.set_mode(SCREEN_RECT.size)
#创建游戏时钟
self.clock = pygame.time.Clock()
self.__create_sprites()
#敌机生成和主机开火的定时器
pygame.time.set_timer(CREATE_ENEMY_EVENT,1000)#单位是ms
pygame.time.set_timer(HERO_FIRE_EVENT,500)
事件监听方法
在事件监听过程中,需要对敌机生成、子弹飞行以及主机移动指令做出相应的反应处理。
def __event_handler(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
PlaneGame.__game_over()
elif event.type == CREATE_ENEMY_EVENT:
print("敌机生成...")
#创建敌机精灵
enemy = Enemy()
#敌机精灵加入精灵组
self.enemy_group.add(enemy)
elif event.type == HERO_FIRE_EVENT:
print("发射子弹...")
self.hero.fire()
#飞机移动
keyss_pressed = pygame.key.get_pressed()
if keyss_pressed[pygame.K_RIGHT]:
print("向右移动")
self.hero.speed = 2
elif keyss_pressed[pygame.K_LEFT]:
print("向左移动")
self.hero.speed = -2
else:
self.hero.speed = 0
碰撞检测
对子弹碰撞敌机和敌机碰撞主机的情况进行判定处理。
#碰撞检测
def __check_collide(self):
#子弹摧毁敌机
pygame.sprite.groupcollide(self.hero.bullet_group,self.enemy_group,True,True)
#敌机撞毁英雄
enemies = pygame.sprite.spritecollide(self.hero, self.enemy_group, True)
if len(enemies) > 0:
self.hero.kill()
PlaneGame.__game_over()
精灵组更新显示
#精灵更新显示
def __update_sprites(self):
#背景精灵组
self.back_group.update()
self.back_group.draw(self.screen)
#敌机精灵组
self.enemy_group.update()
self.enemy_group.draw(self.screen)
#主机精灵组
self.hero_group.update()
self.hero_group.draw(self.screen)
#子弹精灵组
self.hero.bullet_group.update()
self.hero.bullet_group.draw(self.screen)
游戏的开始与结束逻辑处理
def start_game(self):
print("游戏开始...")
while True:
#1 设置刷新帧率
self.clock.tick(SCREEN_PER_SEC)
#2 时间监听
self.__event_handler()
#3 碰撞检测
self.__check_collide()
#4 更新敌机
self.__update_sprites()
#5 更新显示
pygame.display.update()
@staticmethod
def __game_over():
print("游戏结束")
pygame.quit()
exit()
程序总结
程序中使用的print语句主要用于运行时的功能检测,可以直接注释掉,对程序整体运行无影响。游戏仅包含简单规则:主机可以左右移动,敌机会随机从上方垂直下落,敌机撞到主机后游戏结束并直接关闭游戏窗口。例如击毁敌机并未设置得分机制,这些都是可以进一步优化规则的部分。由于本程序旨在帮助熟悉Pygame库的功能,代码并未写得过于详细。感兴趣的用户可以对代码部分进行修改以达到预期效果。程序升级部分未做过多文字解释,代码中保留了注释以便解读。
程序中用到的素材以及未使用到的音乐均在提供的链接中。
到此这篇关于Pygame库200行代码实现简易飞机大战的文章就介绍到这了,更多相关Pygame 飞机大战内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













