python实现坦克大战游戏 附详细注释


Posted in Python onMarch 27, 2020

本文实例为大家分享了python实现坦克大战的具体代码,供大家参考,具体内容如下

#功能实现游戏主窗口
import pygame,time,random#导入模块
_display = pygame.display#赋值给一个变量 调用时方便
color_red = pygame.Color(255,0,0)#同上 v
class MainGame(object):
 screen_width = 900#游戏界面宽度
 screen_height = 550#界面的高度
 Tank_p1 = None#坦克对象
 window = None #窗口对象
 EnemyTank_list = []# 存储所有敌方坦克
 EnemTank_count = 10# 要创建的敌方坦克的数量
 Bullet_list = [] #创建我方子弹列表
 EnemyTank_bullet_list = []
 Explode_list= []
 wall_list = []
 def startGame(self):
 pygame.display.init()#初始化游戏模块的显示
 MainGame.window = _display.set_mode([MainGame.screen_width,MainGame.screen_height])#生成并加载游戏窗口、\
 #pygame.display模块及set_mode方法和pygame相关方法调用设置
 # 见<<https://www.pygame.org/docs/ref/display.html#pygame.display.set_mode>> UC浏览器实现自动翻译
 pygame.display.set_caption("坦克大战v1.0")#s设置游戏标题
 self.creatEnemyTank()#类中调用初始敌方坦克方法
 self.creatMyTank()#创建我方坦克
 self.creatWalls()#创建障碍物
 
 while True:#无限循环 所有行为方法都要无限制的显示
  MainGame.window.fill(pygame.Color(0,0,0))#窗口颜色设置 Window在开始方法已设置为游戏窗口
  self.getEvent()#死循环中 获取事件的值 对其进行相应处理
  MainGame.window.blit(self.drawText("剩余敌方数量%d" %len(MainGame.EnemyTank_list)),(7, 7))#循环游戏窗口加载文本 bilt方法在页面写入另一个
 
  self.blitWalls()
  if MainGame.Tank_p1 and MainGame.Tank_p1.alive:
  MainGame.Tank_p1.displayTank()#循环调用生成的坦克对象(显示)方法
 
 
  self.blitEnemyTank()# 此类中用self 循环展示敌方坦克
 
  if MainGame.Tank_p1 and not MainGame.Tank_p1.stop:
  MainGame.Tank_p1.move()# 移动
  MainGame.Tank_p1.hitWall()#撞击墙壁
  MainGame.Tank_p1.hitEnemyTank()#撞击敌方坦克方法
  self.blitEnemyBullet()#显示敌方坦克子弹
  self.blitBullet()#显示炮弹
  self.blitExplode()#显示爆炸效果
  time.sleep(0.02)
  _display.update()#获取更新
  #将带有文字的surface 绘制到窗口中 循环
 # 创建敌方坦克
 
 def creatEnemyTank(self):#创建敌方坦克
 
 top = 100
 
 for i in range(MainGame.EnemTank_count):#MainGame.EnemTank_count=5 五次循环创建敌方坦克
  speed = random.randint(3, 6) # 随机模块 random.randint
  # 每次都随机生成一个left值
  left = random.randint(1, 7)
  eTank = EnemyTank(left * 100, top, speed)#生成敌方坦克类对象 传入参数 left为随机
  MainGame.EnemyTank_list.append(eTank)#将创建的每一个敌方坦克添加到列表
 # 将坦克加入到窗口中
 def creatMyTank(self):
 MainGame.Tank_p1 = MyTank(400, 480) # 生成一个坦克类的实例对象
 music = Music("img/start.wav")
 music.play()
 def creatWalls(self):
 for i in range(1,10):
  wall = Wall(60*i,250)
  MainGame.wall_list.append(wall)
 def blitWalls(self):
 for wall in MainGame.wall_list:
  if wall.live == True:
  wall.displayWall()
  else:
  MainGame.wall_list.remove(wall)
 def blitEnemyTank(self):#显示敌方坦克 若出现坦克图片重叠也是符合逻辑
 for eTank in MainGame.EnemyTank_list:
  if eTank.live :
  eTank.displayTank()#将列表中每一个进行显示 eTank为敌方坦克类对象 调用父类Tank类中显示方法
  eTank.randMove()
  eTank.hitWall()
  eTank.hitMyTank()
  ebullet = eTank.shot()
 
  if ebullet:#如果不为空
   MainGame.EnemyTank_bullet_list.append(ebullet)
  else:
  MainGame.EnemyTank_list.remove(eTank)
 def blitEnemyBullet(self):#将敌方坦克加入到窗口中
 for ebullet in MainGame.EnemyTank_bullet_list:
  if ebullet.alive:
  ebullet.display_bullet()
  ebullet.bulletMove()
  ebullet.hitWalls()
  if MainGame.Tank_p1.alive:
   ebullet.hitMyTank()
  else:
  MainGame.EnemyTank_bullet_list.remove(ebullet)
 def blitBullet(self):#显示子弹
 for bullet in MainGame.Bullet_list:#事件中获的子弹的列表进行遍历 类似显示坦克方法 逐个展示
  if bullet.alive:#Bullet类中设置的标签 来判断子弹的存活 True为生 根据炮弹移动方法bulletmove()中所加限制条件
  bullet.display_bullet()#调用列表中子弹对象的显示方法
  bullet.bulletMove()#子弹的移动
  bullet.hitEnemyTank()#调用与敌方坦克的碰撞检测方法
  bullet.hitWalls()#d调用子弹碰撞墙壁
  else:
 
  MainGame.Bullet_list.remove(bullet)#如果为False bulletmove()中触碰墙壁就是False 就从列表删除 循环执行
 def blitExplode(self):
 for explode in MainGame.Explode_list:
  if explode.live:
  explode.display_explode()
  music = Music("img/blast.wav")
  music.play()
  else:
  MainGame.Explode_list.remove(explode)
 def drawText(self,content):#文本 写入游戏窗口
 pygame.font.init()#初始化字体
 font = pygame.font.SysFont("kaiti",18)#创建字体对象
 text_sf = font.render(content,True,color_red)#字体样式对象
 return text_sf #返回内容的surface
 def getEvent(self):#获取所有事件
 eventlist = pygame.event.get()#所有事件列表
 for event in eventlist:#遍历每一个事件进行判断 键盘输入的字符
  #type属性
  if event.type == pygame.QUIT:#如果是QUIT(就是点击窗口的退出按钮 叉号)
  print("退出游戏")
  self.gameOver()#退出方法
  if event.type == pygame.KEYUP:#如果键盘按钮抬起 并且是上下左右键
  if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_UP\
  or event.key == pygame.K_DOWN:
   if MainGame.Tank_p1 and MainGame.Tank_p1.alive:
   MainGame.Tank_p1.stop = True#stop为True 按钮抬起就停止 start方法中的开关 实现坦克按住按钮持续移动
 
  if event.type == pygame.KEYDOWN:#如果事件的类型为按下按键进行如下判断
  if event.key == pygame.K_ESCAPE :
   self.creatMyTank()
  if MainGame.Tank_p1 and MainGame.Tank_p1.alive:
   if event.key == pygame.K_LEFT:#如果为左方向键 如下为同一类型
   print("向左移动")
   MainGame.Tank_p1.direction = "L"#设置坦克方向进行判断向左就是L,
   # 并设置游戏窗口的界限 还可以利用方向作为字典的键获取坦克图片 坦克的移动方向
   #就是加载不同方向的坦克图片 呈现出移动的效果
   MainGame.Tank_p1.stop = False#坦克移动的开关 循环使用 False为移动
   if event.key == pygame.K_RIGHT:
   print("向右移动")
   MainGame.Tank_p1.direction = "R"
   MainGame.Tank_p1.stop = False
   if event.key ==pygame.K_UP:
   print("向上移动")
   MainGame.Tank_p1.direction = "U"
   MainGame.Tank_p1.stop = False
   if event.key == pygame.K_DOWN:
   print("向下移动")
   MainGame.Tank_p1.direction = "D"
   MainGame.Tank_p1.stop = False
   if event.key == pygame.K_SPACE:#空格键发射子弹
   if len(MainGame.Bullet_list) < 3:#控制子弹在屏幕显示的数量 太多没有游戏体验 列表中存储三个
    m = Bullet(MainGame.Tank_p1)#子弹类对象 添加到列表 开始方法调用显示子弹 子弹触碰墙壁列表内移除对象
    MainGame.Bullet_list.append(m)
    music =Music("img/fire.wav")
    music.play()
 def gameOver(self):#游戏结束方法
 exit()
class BaseItem(pygame.sprite.Sprite):
 def __init__(self):
 pygame.sprite.Sprite.__init__(self)
class Tank(BaseItem):#坦克的父类
 def __init__(self,left,top):
 #坦克图片集合
 self.images = {"U":pygame.image.load("img/p1tankU.gif"),
   "D": pygame.image.load("img/p1tankD.gif"),
   "L":pygame.image.load("img/p1tankL.gif"),
   "R": pygame.image.load("img/p1tankR.gif"),}#坦克各方向图片的加载
  #坦克的方向
 self.direction = "U"
 #坦克初始化时候的默认图片,根据坦克的方向从字典里去提取
 self.image = self.images[self.direction]
 #坦克的区域(left,top,width,height)坦克位置以及坦克的大小
 self.rect = self.image.get_rect()
 self.rect.left = left#坦克距离左边位置修改默认参数指定的位置
 self.rect.top = top#将坦克距离上边的位置修改我指定的位置
 self.speed = 15#设置坦克的速度
 self.stop = True #设置移动的开关
 self.oldtop = self.rect.top
 self.oldleft = self.rect.left
 def move(self):
 self.oldtop = self.rect.top
 self.oldleft = self.rect.left
 if self.direction == "U":#向上时
  if self.rect.top > 0:#self.rect = self.image.get_rect()
  # self.rect.top = top#将坦克距离上边的位置修改我指定的位置
  self.rect.top -= self.speed#坦克的速度距离每一次调用时相减 直到<0时
 elif self.direction == "D":#向下时
  if self.rect.top < MainGame.screen_height-MainGame.Tank_p1.rect.height:#下边界小于窗口的高度减去坦克自身的高度的距离
  self.rect.top += self.speed #距离加速度的距离 循环一次添加一次
 elif self.direction == "L":
  if self.rect.left > 0:
  self.rect.left -= self.speed
 elif self.direction == "R":
  if self.rect.left < MainGame.screen_width -MainGame.Tank_p1.rect.width:
  self.rect.left += self.speed
 def stay(self):
 self.rect.left = self.oldleft
 self.rect.top = self.oldtop
 def hitWall(self):
 for wall in MainGame.wall_list:
  if pygame.sprite.collide_rect(wall,self):
  self.stay()
 def shot(self):
 return Bullet(self)
 def displayTank(self):#坦克显示方法
 #1.重新设置坦克的图片
 self.image = self.images[self.direction]
 #2.将坦克加入到窗口中
 MainGame.window.blit(self.image,self.rect)#调用MainGame window方法
 # 传入图片和位置 self.rect = self.image.get_rect()
class MyTank(Tank):
 def __init__(self,left,top):
 super(MyTank,self).__init__(left,top)
 def hitEnemyTank(self):
 for etank in MainGame.EnemyTank_list:
  if pygame.sprite.collide_rect(etank,self):
  self.stay()
class EnemyTank(Tank):#敌方坦克类
 def __init__(self,left,top,speed):#初始化敌方坦克 三个参数
 self.images = {"U": pygame.image.load("img/enemy1U.gif"),
   "D": pygame.image.load("img/enemy1D.gif"),
   "L": pygame.image.load("img/enemy1L.gif"),
   "R": pygame.image.load("img/enemy1R.gif"), }#加载敌方坦克图片
 # 坦克的方向
 self.direction = self.randDirection()#自定义坦克的随机方向
 self.image = self.images[self.direction]#坦克的信息 从字典中以键获得值
 # 坦克所在的区域 Rect->
 self.rect = self.image.get_rect()#获得坦克图片的距离 距左和距上
 # 指定坦克初始化位置 分别距x,y轴的位置
 self.rect.left = left#距左的位置>>形参
 self.rect.top = top#距上的位置
 # 新增速度属性
 self.speed = speed #速度>>初始化时设置
 self.stop = True
 self.step = 50#设置步数
 self.live = True
 def randDirection(self):#随机生成敌方坦克的方向图片
 num = random.randint(1, 4)
 if num == 1:
  return 'U'
 elif num == 2:
  return 'D'
 elif num == 3:
  return 'L'
 elif num == 4:
  return 'R'
 def randMove(self):#敌方坦克随机移动
 if self.step <= 0:#如果步数为0
  self.direction = self.randDirection()#方向为随机方向
  self.step = 30# 重置步数
 else:
  self.move()#移动 坦克位置不断改变
  self.step -= 1#步数每次循环减一
 def shot(self):
 s = random.randint(1,1000)
 if s <30:
  return Bullet(self)
 def hitMyTank(self):
 if pygame.sprite.collide_rect(self,MainGame.Tank_p1):
  self.stay()
class Bullet(BaseItem):#炮弹类
 def __init__(self,tank):
 self.image = pygame.image.load("img\enemymissile.gif")
 self.direction = tank.direction
 #子弹速度
 self.speed = 18
 self.rect = self.image.get_rect()#获得子弹的对象的坐标 只计算距离左侧和和上面
 #子弹初始化位置要根据坦克大方向进行调整 可以自己画图计算
 if self.direction == "U":
  #子弹的位置 left += 坦克宽度的一半 - 子弹的宽度的一半
  self.rect.left = tank.rect.left + tank.rect.width/2 - self.rect.width/2
  self.rect.top = tank.rect.top - self.rect.height
 elif self.direction == "D":
  self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2
  self.rect.top = tank.rect.top - self.rect.height
 elif self.direction == "L":
  self.rect.left = tank.rect.left - tank.rect.width / 2 - self.rect.width / 2
  self.rect.top = tank.rect.top + tank.rect.width/2 -self.rect.width/2
 elif self.direction == "R":
  self.rect.left = tank.rect.left + tank.rect.width / 2
  self.rect.top = tank.rect.top + tank.rect.width/2 -self.rect.width/2
 speed = 10#速度
 alive = True#设置一个小标签 作判断
 def bulletMove(self):#炮弹移动
 if self.direction == "U":
  if self.rect.top > 0 :#距离限制计算 self子弹对象本身 rect.top距离窗口上方 rect.left左侧
  self.rect.top -= self.speed
  else:
  self.alive = False#此为<0时的情况 同下都是触碰墙壁时的情况
 elif self.direction == "D":
  if self.rect.top < MainGame.screen_height - self.rect.height:#屏幕高度 - 子弹的高度
  self.rect.top += self.speed
  else:
  self.alive = False
 elif self.direction == "L":
  if self.rect.left > 0:
  self.rect.left -= self.speed
  else:
  self.alive = False
 elif self.direction == "R":
  if self.rect.left < MainGame.screen_width - self.rect.width:
  self.rect.left += self.speed
  else:
  self.alive = False
 def hitEnemyTank(self):#我方子弹与敌方坦克相碰
 for etank in MainGame.EnemyTank_list:#敌方坦克列表
  if pygame.sprite.collide_rect(etank,self):#sprite中的相撞测试
  explode = Explode(etank)#产生一个爆炸效果
  MainGame.Explode_list.append(explode)
  self.alive = False
  etank.live = False
 def hitMyTank(self):
 if pygame.sprite.collide_rect(self,MainGame.Tank_p1):
  explode = Explode(MainGame.Tank_p1)
  MainGame.Explode_list.append(explode)
  MainGame.Tank_p1.alive = False
  self.alive = False
 def hitWalls(self):
 for wall in MainGame.wall_list:
  if pygame.sprite.collide_rect(wall,self):
  self.alive = False
  wall.hp -= 1
  if wall.hp <= 0:
   wall.live = False
 def display_bullet(self):#显示子弹方法
 MainGame.window.blit(self.image,self.rect)#窗口写入
class Explode:#爆炸效果
 def __init__(self,tank):
 self.step = 0
 self.rect = tank.rect
 self.images = [pygame.image.load("img/blast0.gif"),
   pygame.image.load("img/blast1.gif"),
   pygame.image.load("img/blast2.gif"),
   pygame.image.load("img/blast3.gif"),
   pygame.image.load("img/blast4.gif"),
   pygame.image.load("img/blast5.gif"),
   pygame.image.load("img/blast6.gif"),
   pygame.image.load("img/blast7.gif"),]
 self.live = True
 self.image = self.images[self.step]
 def display_explode(self):#显示爆炸效果
 if self.step < len(self.images):
  MainGame.window.blit(self.image,self.rect)
  self.image = self.images[self.step]
  self.step += 1
 else:
  self.live = False
  self.step = 0
class Wall:
 def __init__(self,left,top):
 self.image = pygame.image.load("img/steels.gif")
 self.rect = self.image.get_rect()
 
 self.rect.left = left
 self.rect.top = top
 self.live = True
 self.hp = 3
 def displayWall(self):#显示障碍物
 MainGame.window.blit(self.image,self.rect)
 
class Music:#音效
 def __init__(self,filename):
 self.filename = filename
 pygame.mixer.init()#混合器的初始
 pygame.mixer.music.load(self.filename)#加载音乐文件
 def play(self):
 pygame.mixer.music.play(loops=0)#播放音乐
 
MainGame().startGame()

更多关于python游戏的精彩文章请点击查看以下专题:

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

Python 相关文章推荐
Python实现全角半角转换的方法
Aug 18 Python
python使用cStringIO实现临时内存文件访问的方法
Mar 26 Python
Python中datetime常用时间处理方法
Jun 15 Python
Python使用multiprocessing实现一个最简单的分布式作业调度系统
Mar 14 Python
Python字符串处理实现单词反转
Jun 14 Python
用Python实现KNN分类算法
Dec 22 Python
Python单元和文档测试实例详解
Apr 11 Python
django-filter和普通查询的例子
Aug 12 Python
python NumPy ndarray二维数组 按照行列求平均实例
Nov 26 Python
解决django无法访问本地static文件(js,css,img)网页里js,cs都加载不了
Apr 07 Python
Python转换字典成为对象,可以用&quot;.&quot;方式访问对象属性实例
May 11 Python
Python爬取微信小程序Charles实现过程图解
Sep 29 Python
六行python代码的爱心曲线详解
May 17 #Python
python使用pygame模块实现坦克大战游戏
Mar 25 #Python
Django如何开发简单的查询接口详解
May 17 #Python
详解python函数的闭包问题(内部函数与外部函数详述)
May 17 #Python
学习python分支结构
May 17 #Python
python pygame实现方向键控制小球
May 17 #Python
基于Numpy.convolve使用Python实现滑动平均滤波的思路详解
May 16 #Python
You might like
2021年最新CPU天梯图
2021/03/04 数码科技
php下使用SimpleXML 处理XML 文件
2010/02/27 PHP
php多种形式发送邮件(mail qmail邮件系统 phpmailer类)
2014/01/22 PHP
php动态变量定义及使用
2015/06/10 PHP
HTML代码中标签的全部属性 中文注释说明
2009/03/26 Javascript
解析Javascript中难以理解的11个问题
2013/12/09 Javascript
常见的原始JS选择器使用方法总结
2014/04/09 Javascript
javascript 获取HTML DOM父、子、临近节点
2014/06/16 Javascript
基于jQuery+JSON的省市二三级联动效果
2015/06/05 Javascript
JS模拟实现Select效果代码
2015/09/24 Javascript
js获取客户端操作系统类型的方法【测试可用】
2016/05/27 Javascript
JS中使用FormData上传文件、图片的方法
2016/08/07 Javascript
node网页分段渲染详解
2016/09/05 Javascript
Vue+Vux项目实践完整代码
2017/11/30 Javascript
js实时监控文本框输入字数的实例代码
2018/01/18 Javascript
使用Vue写一个datepicker的示例
2018/01/27 Javascript
详解VueJS应用中管理用户权限
2018/02/02 Javascript
从零开始搭建vue移动端项目到上线的步骤
2018/10/15 Javascript
Vue实现移动端左右滑动效果的方法
2018/11/27 Javascript
利用jsonp解决js读取本地json跨域的问题
2018/12/11 Javascript
js中innerText/textContent和innerHTML与target和currentTarget的区别
2019/01/21 Javascript
JavaScript模块管理的简单实现方式详解
2019/06/15 Javascript
Vue 根据条件判断van-tab的显示方式
2020/08/03 Javascript
python 回调函数和回调方法的实现分析
2016/03/23 Python
python利用有道翻译实现&quot;语言翻译器&quot;的功能实例
2017/11/14 Python
Python自定义函数实现求两个数最大公约数、最小公倍数示例
2018/05/21 Python
python3学习之Splash的安装与实例教程
2018/07/09 Python
详解Python计算机视觉 图像扭曲(仿射扭曲)
2019/03/27 Python
在Qt5和PyQt5中设置支持高分辨率屏幕自适应的方法
2019/06/18 Python
如何通过安装HomeBrew来安装Python3
2020/12/23 Python
英国最大的手表网站:The Watch Hut
2017/03/31 全球购物
Bowflex美国官方网站:高级家庭健身器材
2017/12/22 全球购物
弄虚作假心得体会
2014/09/10 职场文书
党员干部观看《周恩来四个昼夜》思想汇报
2014/09/10 职场文书
详解MySQL InnoDB存储引擎的内存管理
2021/04/08 MySQL
Python趣味爬虫之用Python实现智慧校园一键评教
2021/05/28 Python