使用python实现飞机大战游戏

本文实例为大家分享了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()

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

(0)

相关推荐

  • python实现飞机大战

    本文实例为大家分享了python实现飞机大战的具体代码,供大家参考,具体内容如下 实现的效果如下: 主程序代码如下: import pygame from plane_sprites import * class PlaneGame(object): """飞机大战主游戏""" def __init__(self): print("游戏初始化") # 1,绘制屏幕窗口 self.screen = pygame.display.

  • python实现飞机大战游戏

    飞机大战(Python)代码分为两个python文件,工具类和主类,需要安装pygame模块,能完美运行(网上好多不完整的,调试得心累.实现出来,成就感还是满满的),如图所示: 完整代码如下: 1.工具类plane_sprites.py import random import pygame # 屏幕大小的常量 SCREEN_RECT = pygame.Rect(0, 0, 480, 700) # 刷新的帧率 FRAME_PER_SEC = 60 # 创建敌机的定时器常量 CREATE_ENEM

  • python飞机大战pygame碰撞检测实现方法分析

    本文实例讲述了python飞机大战pygame碰撞检测实现方法.分享给大家供大家参考,具体如下: 目标 了解碰撞检测方法 碰撞实现 01. 了解碰撞检测方法 pygame 提供了 两个非常方便 的方法可以实现碰撞检测: pygame.sprite.groupcollide() 两个精灵组 中 所有的精灵 的碰撞检测 groupcollide(group1, group2, dokill1, dokill2, collided = None) -> Sprite_dict 如果将 dokill 设

  • 用Python写飞机大战游戏之pygame入门(4):获取鼠标的位置及运动

    目标是拷贝微信的飞机大战,当然拷贝完以后大家就具备自己添加不同内容的能力了. 首先是要拿到一些图片素材,熟悉使用图像处理软件和绘画的人可以自己制作,并没有这项技能的同学只能和我一样从网上下载相应的素材了. 网上可以找到相应的这样的图片,注意,所有的元件图片要是png类型的图片,那样可以有透明的背景,否则会有白色的边框露出来. 找到素材以后我们就要开始搭建我们的飞机大战了. 微信上的飞机大战是由手指控制的,在电脑上,我们就先用鼠标代替了. 按照之前我们在天空上移动云的那个程序,我们可以知道该怎么做

  • python pygame模块编写飞机大战

    本文实例为大家分享了python pygame模块编写飞机大战的具体代码,供大家参考,具体内容如下 该程序没有使用精灵组,而是用列表存储对象来替代精灵组的动画效果.用矩形对象的重叠来判断相撞事件.该程序可以流畅运行,注释较为详细,希望可以帮助大家. import pygame from pygame.locals import * from sys import exit import time import random # 创建子弹类,把子弹的图片转化为图像对象,设定固定的移动速度 clas

  • python版飞机大战代码分享

    利用pygame实现了简易版飞机大战.源代码如下: # -*- coding:utf-8 -*- import pygame import sys from pygame.locals import * from pygame.font import * import time import random class Hero(object): #玩家 英雄类 def __init__(self, screen_temp): self.x = 210 self.y = 700 self.life

  • python飞机大战pygame游戏背景设计详解

    本文实例讲述了python飞机大战pygame游戏背景设计.分享给大家供大家参考,具体如下: 目标 背景交替滚动的思路确定 显示游戏背景 01. 背景交替滚动的思路确定 运行 备课代码,观察 背景图像的显示效果: 游戏启动后,背景图像 会 连续不断地 向下方 移动 在 视觉上 产生英雄的飞机不断向上方飞行的 错觉 -- 在很多跑酷类游戏中常用的套路 游戏的背景 不断变化 游戏的主角 位置保持不变 1.1 实现思路分析 解决办法 创建两张背景图像精灵 第 1 张 完全和屏幕重合 第 2 张在 屏幕

  • 500行代码使用python写个微信小游戏飞机大战游戏

    这几天在重温微信小游戏的飞机大战,玩着玩着就在思考人生了,这飞机大战怎么就可以做的那么好,操作简单,简单上手. 帮助蹲厕族.YP族.饭圈女孩在无聊之余可以有一样东西让他们振作起来!让他们的左手 / 右手有节奏有韵律的朝着同一个方向来回移动起来! 这是史诗级的发明,是浓墨重彩的一笔,是-- 在一阵抽搐后,我结束了游戏,瞬时觉得一切都索然无味,正在我进入贤者模式时,突然想到,如果我可以让更多人已不同的方式体会到这种美轮美奂的感觉岂不美哉? 所以我打开电脑,创建了一个 plan_game.py-- 先

  • python实现飞机大战小游戏

    本文实例为大家分享了python实现飞机大战的具体代码,供大家参考,具体内容如下 初学Python,写了一个简单的Python小游戏. 师出bilibili某前辈 pycharm自带了第三方库pygame,安装一下就好了,很方便. 虽然很多大佬已经给出了步骤,我这里还是啰嗦一下,也为了自己巩固一下. 上图: 这里再给出代码的逻辑架构 plane_main.py import pygame from plane_sprites import * class PlaneGame(object): "

  • python实现飞机大战微信小游戏

    0.前言 我学一种语言,可以说学任何东西都喜欢自己动手实践,总感觉自己动手一遍,就可以理解的更透彻,学python也一样,自己动手写代码,但更喜欢做点小东西出来,一边玩一边学.下面我就展示一下我最近做的一个小游戏. 1.素材准备 首先我们先来预览一下游戏的最终运行界面 根据游戏界面,我们可以清楚的知道必须要先准备游戏背景图片,飞机图片,子弹图片等等.这些素材我已经放到网上, 点我下载 ,里面包括了我的代码和图片素材. 2.代码部分 库依赖: pygame 本游戏主要有两个py文件,主文件plan

随机推荐