用Pygame怎样设计和实现一个简单的飞机大战
Admin 2022-05-23 群英技术资讯 733 次浏览
这篇文章主要介绍了用Pygame怎样设计和实现一个简单的飞机大战相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇用Pygame怎样设计和实现一个简单的飞机大战文章都会有所收获,下面我们一起来看看吧。
pygame是跨平台python模块,专为电子游戏设计,包括图像、声音。建立在SDL基础上,允许实时电子游戏研发而无需被低级语言束缚, 开发者可以把精力放在游戏的架构上。
(1) pygame
pygame模块会自动导入其它的pygame相关模块。
pygame模块包括surface函数, 可以返回一个新的surface 对象。 init()函数是pygame游戏的核心,必须在进入游戏的主循环之前调用。init()会自动初始化其它所有模块。
(2) pygame.locals
包括在你自己的模块作用域内使用的名字(变量)。包括事件类型、键和视频模式等的名字。
(3) pygame.display
包括处理pygame显示方式的函数。包括普通窗口和全屏模式。 pygame.display中一些常用的方法如下:
(4) pygame.font
包括font函数,用于表现不同的字体。
(5) pygame.sprite
游戏精灵,Group用做sprite对象的容器。调用group对象的update对象,会自动调用所有sprite对象的update方法。
(6) pygame.mouse
隐藏鼠标光标,获取鼠标位置。
(7) pygame.event
追踪鼠标单击、按键按下和释放等事件。
(8) pygame.image
用于处理保存在GIF、PNG或者JPEG文件内的图像。
注:程序中除了local模块和font模块没有使用,其他模块均有涉及。
你可以选择使用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库的功能,所以代码并未写的更加详细,感兴趣的话你可以对代码部分进行更改达到你想要的效果,程序升级部分并未进行太多的文字解释部分,在代码中我保留了我的注释部分方便你对代码进行解读。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
open()函数的作用是打开一个文件,并返回一个file对象(即文件对象),下面这篇文章主要给大家介绍了关于python中open函数对文件处理的相关资料,需要的朋友可以参考下
虽然把JSON数据存入mysql也是比较蛋疼,但是相比使用Nodejs嵌套处理多个mysql查询并拼接返回数据也算是没mongo时的一个折中方案了。我使用python拼接了一个json格式的字符串,却遇到了一些问题1,如果把json数据转成str存入,那么nodejs获取数据的时候就无法使用json格式了处理方法就是importjsondata=json.dumps(data_d
说起处理数据就离不开导入导出,而我们使用Pandas时候最常用的就是read_excel、read_csv了,下面这篇文章主要给大家介绍了关于如何利用python在剪贴板上读取/写入数据的相关资料,需要的朋友可以参考下
这篇文章主要为大家介绍了pytest官方文档解读fixtures的autouse,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
这篇文章主要介绍了python3实现无权最短路径的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008