使用python实现飞机大战游戏


Posted in Python onMarch 23, 2020

本文实例为大家分享了Python飞机大战项目,供大家参考,具体内容如下

import gc
import random

import pygame

# 玩家飞机精灵类
import Constants


class HeroPlane(pygame.sprite.Sprite):
 def __init__(self, screen):
  # 调用父类初始化方法
  # pygame.sprite.Sprite.__init__(self)
  super().__init__()
  # 窗口
  self.screen = screen
  # 一个玩家飞机图片
  self.image = pygame.image.load('./feiji/feiji.png')
  # 飞机矩形区域对象
  self.rect = self.image.get_rect()
  # 左上角坐标
  self.rect.topleft = [512 / 2 - 116 / 2, 600]
  # 飞机的速度
  self.speed = 15
  # 一个精灵组 存放所有的子弹精灵
  self.bullets = pygame.sprite.Group()
  # 血量 初始100
  self.blood_value = 100

  # 标记玩家飞机是否over
  self.is_remove = False

  # 显示爆炸图片的 索引 从0开始
  self.mIndex = 0

  # 存放爆炸图片 的列表
  self.bomb_mImages = []

  for v in range(1, 15):
   # 把所有图片 存到列表里 每个图片 存2次
   self.bomb_mImages.append(pygame.image.load('./feiji/image ' + str(v) + '.png'))
   self.bomb_mImages.append(pygame.image.load('./feiji/image ' + str(v) + '.png'))

 def kill_blood(self, kill_value=10):
  """血量减少"""
  self.blood_value -= kill_value
  print('被打中了,血量还剩%s' % self.blood_value)
  if self.blood_value <= 0:
   # 避免血量负值
   self.blood_value = 0
   # 血量<=0 设置is_remove 为True
   self.is_remove = True

 def key_control(self):
  """按键监听 操作飞机上下左右和发子弹"""
  # 监听键盘事件
  key_pressed = pygame.key.get_pressed() # 注意这种方式是能够检测到一直按下不松开的键盘

  if key_pressed[pygame.K_w] or key_pressed[pygame.K_UP]:
   # top值如果小于0 就到了最顶部 不要再移动了
   if self.rect.top > 3:
    self.rect.top -= self.speed
  if key_pressed[pygame.K_s] or key_pressed[pygame.K_DOWN]:
   if self.rect.bottom <= 768:
    self.rect.bottom += self.speed
  if key_pressed[pygame.K_a] or key_pressed[pygame.K_LEFT]:
   if self.rect.left > 0:
    self.rect.left -= self.speed
  if key_pressed[pygame.K_d] or key_pressed[pygame.K_RIGHT]:
   if self.rect.right < 520:
    self.rect.right += self.speed
  if key_pressed[pygame.K_SPACE]:
   # print("space")
   # 创建3个子弹
   bullet1 = Bullet(self.screen, self.rect.left, self.rect.top, 1)
   bullet2 = Bullet(self.screen, self.rect.left, self.rect.top, 2)
   bullet3 = Bullet(self.screen, self.rect.left, self.rect.top, 3)
   # 添加到精灵组
   self.bullets.add(bullet1, bullet2, bullet3)

 def bomb(self):
  print('玩家飞机爆炸中')
  """显示爆炸图片"""
  self.screen.blit(self.bomb_mImages[self.mIndex], self.rect)
  self.mIndex += 1
  print('mIndex', self.mIndex)
  if self.mIndex >= len(self.bomb_mImages):
   # 播放到了最后 爆炸结束 返回True
   return True

 def update(self):
  if self.is_remove:
   print('玩家飞机挂掉')
   # 如果玩家飞机挂掉
   if self.bomb():
    # 爆炸结束
    print('爆炸结束')
    self.rect.topleft = [-200, -200]
    # 开启倒计时
    pygame.time.set_timer(Constants.game_over_id, 1000)
    # 把玩家飞机指向None 停止update
    manager.hero = None
  else:
   self.key_control()
   self.display()

 def display(self):
  # if self.blood_value <= 0:
  #  # 如果血量小于0 移出窗口
  #  self.rect.topleft = [-200, -200]

  # 把飞机显示到窗口上 飞机 116*100
  self.screen.blit(self.image, self.rect)
  # 更新精灵组里的子弹位置
  self.bullets.update()
  # 精灵组所有子弹显示到窗口
  self.bullets.draw(self.screen)


class Bullet(pygame.sprite.Sprite):
 # path_num表示散弹中 子弹是哪一个
 def __init__(self, screen, planex, planey, path_num):
  # 调用父类初始化方法
  # pygame.sprite.Sprite.__init__(self)
  super().__init__()
  # 窗口
  self.screen = screen
  # 一个子弹图片
  self.image = pygame.image.load('./feiji/bullet_12.png')
  # 子弹矩形区域对象
  self.rect = self.image.get_rect()
  # 子弹左上角坐标
  self.rect.topleft = [planex + 48, planey - 20]
  # 子弹的速度
  self.speed = 15
  # path_num表示散弹中 子弹是哪一个
  self.path_num = path_num

 def update(self):
  """修改子弹坐标"""
  self.rect.top -= self.speed
  if self.rect.bottom < 0:
   # 子弹已经移出了屏幕上方 这时把子弹从精灵组删除
   self.kill()
  if self.path_num == 1:
   pass
  elif self.path_num == 2:
   # 如果等于2 就是左侧的散弹
   self.rect.left -= 10
  elif self.path_num == 3:
   # 如果等于3 就是右侧的散弹
   self.rect.right += 10


# 敌机精灵类
class EnemyPlane(pygame.sprite.Sprite):
 # 创建类属性 存放所有飞机的所有的子弹
 all_bullets = pygame.sprite.Group()

 def __init__(self, screen):
  # 调用父类初始化方法
  # pygame.sprite.Sprite.__init__(self)
  super().__init__()
  # 窗口
  self.screen = screen
  # 一个玩家飞机图片
  self.image = pygame.image.load('./feiji/img-plane_5.png')
  # 飞机矩形区域对象
  self.rect = self.image.get_rect()
  # 左上角坐标 x坐标随机
  self.rect.topleft = [random.randint(0, 412), 0]
  # 飞机的速度
  self.speed = 3
  # 一个精灵组 存放所有的子弹精灵
  self.bullets = pygame.sprite.Group()
  # 敌机的左右方向 默认一开始向右
  self.direction = 'right'
  # 子弹的精灵组
  self.bullets = pygame.sprite.Group()
  # 标记敌机是否被击中 是否要删除
  self.is_remove = False

  # 显示爆炸图片的 索引 从0开始
  self.mIndex = 0

  # 存放爆炸图片 的列表
  self.bomb_mImages = []

  for v in range(1, 14):
   # 把所有图片 存到列表里 每个图片 存2次
   self.bomb_mImages.append(pygame.image.load('./feiji/image ' + str(v) + '.png'))
   self.bomb_mImages.append(pygame.image.load('./feiji/image ' + str(v) + '.png'))

  # 记录爆炸位置
  self.x = 0
  self.y = 0

 def auto_move(self):
  """自动移动"""
  # 向下移动
  self.rect.bottom += self.speed
  # 如果飞机向下移出边界 删除它
  if self.rect.top > Manager.height:
   self.kill()

  # 按不同方向左右移动
  if self.direction == 'right':
   self.rect.right += 6
  elif self.direction == 'left':
   self.rect.right -= 6

  # 超出左右边界 更改移动方向
  if self.rect.right >= Manager.width:
   self.direction = 'left'
  if self.rect.left <= 0:
   self.direction = 'right'

 def auto_fire(self):
  # 用一个随机数
  num = random.randint(1, 40)
  # 判断如果等于1就发射一个子弹 ,降低了概率
  if num == 5:
   # 生成敌机子弹
   bullet = EnemyBullet(self.screen, self.rect.left, self.rect.top)
   # 添加到精灵组
   self.bullets.add(bullet)
   # 把子弹添加到类的all_bullets里 用来碰撞检测
   EnemyPlane.all_bullets.add(bullet)

 def bomb(self):
  """显示爆炸图片"""
  if self.mIndex >= len(self.bomb_mImages):
   # 播放到了最后 爆炸结束 返回True
   return True
  self.screen.blit(self.bomb_mImages[self.mIndex], (self.x, self.y))
  self.mIndex += 1

 def update(self):
  if self.is_remove:
   if self.rect.left != -200:
    # 记录爆炸时的位置
    self.x = self.rect.left
    self.y = self.rect.top
   # 如果已经被击中 把飞机移除窗口 防止继续碰撞检测
   self.rect.left = -200
   self.rect.top = -200
   # 显示爆炸效果
   if self.bomb() and not self.bullets:
    # 如果爆炸结束 把自己从精灵组删除
    self.kill()
  else:
   # 移动
   self.auto_move()
   # 开火
   self.auto_fire()
   # 显示
   self.display()

  self.bullet_show()

 def display(self):
  # 把飞机显示到窗口上 飞机 116*100
  self.screen.blit(self.image, self.rect)

 def bullet_show(self):
  if self.bullets:
   # 敌机子弹更新
   self.bullets.update()
   # 敌机子弹显示
   self.bullets.draw(self.screen)


class EnemyBullet(pygame.sprite.Sprite):
 # path_num表示散弹中 子弹是哪一个
 def __init__(self, screen, x, y):
  # 调用父类初始化方法
  # pygame.sprite.Sprite.__init__(self)
  super().__init__()
  # 窗口
  self.screen = screen
  # 一个子弹图片
  self.image = pygame.image.load('./feiji/bullet_6.png')
  # 子弹矩形区域对象
  self.rect = self.image.get_rect()
  # 子弹左上角坐标
  self.rect.topleft = [x + 40, y + 60]
  # 子弹的速度
  self.speed = 10

 def update(self):
  """修改子弹坐标"""
  self.rect.bottom += self.speed
  # 如果子弹向下移出边界 删除它
  if self.rect.top > Manager.height:
   self.kill()


# 游戏音乐
class GameSound(object):
 def __init__(self):
  pygame.mixer.init() # 音乐模块初始化
  pygame.mixer.music.load("./feiji/Jamesketed.mp3")
  pygame.mixer.music.set_volume(0.5) # 声音大小 一半

  self.__bomb = pygame.mixer.Sound("./feiji/bomb.wav")

 def playBackgroundMusic(self):
  # 开始播放背景音乐 -1表示一直重复播放
  pygame.mixer.music.play(-1)

 def playBombSound(self):
  pygame.mixer.Sound.play(self.__bomb) # 爆炸音乐


class GameBackground(object):
 # 初始化地图
 def __init__(self, screen):
  self.mImage1 = pygame.image.load("./feiji/img_bg_level_4.jpg")
  self.mImage2 = pygame.image.load("./feiji/img_bg_level_4.jpg")
  # 窗口
  self.screen = screen
  # 辅助移动地图
  self.y1 = 0
  self.y2 = -Manager.height # -768

 def update(self):
  self.move()
  self.draw()

 # 移动地图
 def move(self):
  self.y1 += 2
  self.y2 += 2
  if self.y1 >= Manager.height:
   self.y1 = 0
  if self.y2 >= 0:
   self.y2 = -Manager.height

 # 绘制地图
 def draw(self):
  self.screen.blit(self.mImage1, (0, self.y1))
  self.screen.blit(self.mImage2, (0, self.y2))


class Manager:
 hero: HeroPlane
 # 创建宽高
 width = 512
 height = 768

 def __init__(self):
  # pygame初始化 否则找不到字体文件
  pygame.init()

  # 1 创建一个窗口 参数1是宽高,参数2 附加参数 参3是颜色深度
  self.screen = pygame.display.set_mode((self.width, self.height), 0, 32)

  # 2创建背景图的对象
  # self.background = pygame.image.load('./feiji/img_bg_level_5.jpg')
  self.background = GameBackground(self.screen)

  # 创建飞机对象
  self.hero = HeroPlane(self.screen)

  # 创建时钟对象
  self.clock = pygame.time.Clock()

  # 敌机的精灵组
  self.enemys = pygame.sprite.Group()

  # 初始化音效对象
  self.sound = GameSound()
  # 定义分数属性
  self.score = 0
  # 倒计时时间
  self.over_time = 3

 def exit(self):
  # 执行退出代码
  pygame.quit()
  # 程序的退出
  exit()

 def new_enemy(self):
  # 创建敌机对象
  enemy = EnemyPlane(self.screen)
  # 添加到精灵组
  self.enemys.add(enemy)

 def drawText(self, text, x, y, textHeight=30, fontColor=(255, 255, 255), backgroudColor=None):

  # 通过字体文件获得字体对象 参数1 字体文件 参数2 字体大小
  font_obj = pygame.font.Font('./feiji/baddf.ttf', textHeight)
  # 1文字 2是否抗锯齿 3文字颜色 4背景颜色
  text_obj = font_obj.render(text, True, fontColor, backgroudColor) # 配置要显示的文字
  # 获得要显示的对象的rect
  text_rect = text_obj.get_rect()
  # 设置显示对象的坐标
  text_rect.topleft = (x, y)
  # 绘制字 到指定区域 参1是文字对象 参2 矩形对象
  self.screen.blit(text_obj, text_rect)

 def game_over_timer(self):
  """执行倒计时"""
  self.over_time -= 1
  if self.over_time == 0:
   # 停止倒计时
   pygame.time.set_timer(Constants.game_over_id, 0)
   # 重新开始游戏
   self.start_game()

 def show_over_text(self):
  print('self.over_time', self.over_time)
  # 游戏结束 显示倒计时时间
  self.drawText('gameover %d' % self.over_time, 0, Manager.height / 2, textHeight=50,
      fontColor=[0, 0, 0])

 def start_game(self):
  global manager
  # 情况敌机子弹的精灵组
  EnemyPlane.all_bullets.empty()
  manager = Manager()
  # 垃圾回收 提示python解释器 要回收了
  gc.collect()
  manager.main()

 def main(self):
  # 播放背景音乐
  self.sound.playBackgroundMusic()

  # 参1eventid是事件id,自己定义(0 - 32之间)不要和已用的pygame的其它事件id冲突,
  # 参2是定时事件的间隔时间,单位是毫秒
  pygame.time.set_timer(Constants.new_enemy, 500)

  while True:
   # 控制每s执行的次数
   self.clock.tick(60)
   # 获取事件 并且处理
   for event in pygame.event.get():
    # 判断事件的类型是否是退出
    if event.type == pygame.QUIT:
     # 退出
     self.exit()
    elif event.type == Constants.new_enemy:
     # 等于20 说明定时器生效 添加一个敌机
     # print('添加一个敌机')
     self.new_enemy()
    elif event.type == Constants.game_over_id:
     print('倒计时 33333')
     # 显示倒计时时间
     self.game_over_timer()

   # 3把背景图显示到窗口上
   # self.screen.blit(self.background, (0, 0))
   self.background.update()

   self.drawText('分数:%s' % self.score, 0, 0)

   if self.hero:
    self.drawText('血量:%s' % self.hero.blood_value, 0, 30)
    # 更新飞机
    self.hero.update()
    # if self.hero.blood_value <= 0 and not self.hero.bullets.sprites():
    #  # 把玩家飞机引用指向None 尽快释放
    #  self.hero = None
   else:
    self.drawText('血量:0', 0, 30)

   # 更新 敌机
   self.enemys.update()

   # 如果飞机已经挂掉 就一直显示倒计时
   if not self.hero:
    # 显示倒计时
    self.show_over_text()

   # 判断 玩家飞机 和敌机是否都存在 self.enemys.sprites()返回精灵组对应的精灵列表
   if self.hero and self.enemys.sprites():
    # 碰撞检测 返回的碰撞到的 敌机列表
    collide_enemys = pygame.sprite.spritecollide(self.hero, self.enemys, False, pygame.sprite.collide_mask)
    if collide_enemys:
     # 如果列表不为空 说明碰到了敌机
     print('碰到了敌机')
     # 爆炸声音
     self.sound.playBombSound()
     self.hero.kill_blood(100)
     for enemy_item in collide_enemys:
      # 标记敌机已经被撞到
      enemy_item.is_remove = True

   # 判断 玩家飞机 和 玩家飞机的子弹 和 敌机是否都存在
   if self.hero and self.hero.bullets and self.enemys:
    # 检测玩家飞机的子弹 和敌机的碰撞
    # 返回是个字典 格式{<Bullet sprite(in 0 groups)>: [<EnemyPlane sprite(in 0 groups)>]}
    # {碰撞的子弹1:[打中的敌机1,打中的敌机2],碰撞的子弹2:[打中的敌机1,打中的敌机5]}
    collode_dict = pygame.sprite.groupcollide(self.hero.bullets, self.enemys, True, False,
               pygame.sprite.collide_mask)

    # 1多个子弹打中同一个飞机 # 2不同子弹 打中不同飞机 # 所有加分值时 要去除重复的敌机

    # print(collode_dict)
    if collode_dict:
     # 爆炸声音
     self.sound.playBombSound()

     print(self.score)
     # 用一个集合 添加敌机 去除重复的
     enemyset = set()
     # 获取所有打中的敌机列表,然后遍历
     for v_enemys in collode_dict.values():
      # 遍历敌机列表
      for enemy_item in v_enemys:
       # print(id(enemy_item))
       enemyset.add(enemy_item)
       # 标记敌机已经被击中
       enemy_item.is_remove = True

     # 碰撞后 +10分*集合里敌机的数量
     self.score += 10 * len(enemyset)

   # 判断 玩家飞机 和 和 敌机子弹
   if self.hero and EnemyPlane.all_bullets:
    # 检测玩家 和敌机子弹的碰撞
    collide_bullets = pygame.sprite.spritecollide(self.hero, EnemyPlane.all_bullets, True,
                pygame.sprite.collide_mask)
    if collide_bullets:
     # 如果碰到了 就减少10*子弹数量的血量
     self.hero.kill_blood(10 * len(collide_bullets))

   # 2 显示窗口
   pygame.display.update()


if __name__ == '__main__':
 manager = Manager()
 manager.main()

使用python实现飞机大战游戏

使用python实现飞机大战游戏

使用python实现飞机大战游戏

使用python实现飞机大战游戏

使用python实现飞机大战游戏

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
在Python中使用HTML模版的教程
Apr 29 Python
python导入时小括号大作用
Jan 10 Python
将python代码和注释分离的方法
Apr 21 Python
华为校园招聘上机笔试题 扑克牌大小(python)
Apr 22 Python
Django forms表单 select下拉框的传值实例
Jul 19 Python
python3常用的数据清洗方法(小结)
Oct 31 Python
Python3 Tkinkter + SQLite实现登录和注册界面
Nov 19 Python
django配置app中的静态文件步骤
Mar 27 Python
Anaconda3中的Jupyter notebook添加目录插件的实现
May 18 Python
在python下实现word2vec词向量训练与加载实例
Jun 09 Python
python实现图片转字符画的完整代码
Feb 21 Python
如何用Python进行时间序列分解和预测
Mar 01 Python
如何在Django中使用聚合的实现示例
Mar 23 #Python
python3注册全局热键的实现
Mar 22 #Python
浅谈Python线程的同步互斥与死锁
Mar 22 #Python
Django 项目布局方法(值得推荐)
Mar 22 #Python
python实现吃苹果小游戏
Mar 21 #Python
python实现贪吃蛇游戏源码
Mar 21 #Python
python实现微信打飞机游戏
Mar 24 #Python
You might like
php横向重复区域显示二法
2008/09/25 PHP
CentOS 6.2使用yum安装LAMP以及phpMyadmin详解
2013/06/17 PHP
php接口数据加密、解密、验证签名
2015/03/12 PHP
PHP环形链表实现方法示例
2017/09/15 PHP
laravel 获取当前url的别名方法
2019/10/11 PHP
把textarea中字符串里含有的回车换行替换成&amp;lt;br&amp;gt;的javascript代码
2007/04/20 Javascript
js 提交和设置表单的值
2008/12/19 Javascript
javascript 关闭IE6、IE7
2009/06/01 Javascript
jquery.validate使用攻略 第一部
2010/07/01 Javascript
js控制的遮罩层实例介绍
2013/05/29 Javascript
iframe如何动态创建及释放其所占内存
2014/09/03 Javascript
escape函数解决js中ajax传递中文出现乱码问题
2014/10/30 Javascript
jquery读取xml文件实现省市县三级联动的方法
2015/05/29 Javascript
EasyUI折叠表格层次显示detailview详解及实例
2016/12/28 Javascript
jQuery中的siblings()是什么意思(推荐)
2016/12/29 Javascript
js 数字、字符串、布尔值的转换方法(必看)
2017/04/07 Javascript
微信小程序点击控件修改样式实例详解
2017/07/07 Javascript
VUE长按事件需求详解
2017/10/18 Javascript
浏览器调试动态js脚本的方法(图解)
2018/01/19 Javascript
详解在Vue中使用TypeScript的一些思考(实践)
2018/07/06 Javascript
Vue中props的详解
2019/05/16 Javascript
webpack打包html里面img后src为“[object Module]”问题
2019/12/22 Javascript
[01:08:10]2014 DOTA2国际邀请赛中国区预选赛 SPD-GAMING VS LGD-CDEC
2014/05/22 DOTA
Python捕捉和模拟鼠标事件的方法
2015/06/03 Python
python 队列详解及实例代码
2016/10/18 Python
Python3之手动创建迭代器的实例代码
2019/05/22 Python
python可视化爬虫界面之天气查询
2019/07/03 Python
Python使用__new__()方法为对象分配内存及返回对象的引用示例
2019/09/20 Python
python怎么调用自己的函数
2020/07/01 Python
如何利用python之wxpy模块玩转微信
2020/08/17 Python
python批量修改交换机密码的示例
2020/09/22 Python
python UIAutomator2使用超详细教程
2021/02/19 Python
师范生自我鉴定范文
2013/10/05 职场文书
领导干部考察材料
2014/02/08 职场文书
提档介绍信范文
2015/10/22 职场文书
CSS 实现磨砂玻璃(毛玻璃)效果样式
2023/05/21 HTML / CSS