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 相关文章推荐
Python2.x中str与unicode相关问题的解决方法
Mar 30 Python
python 与GO中操作slice,list的方式实例代码
Mar 20 Python
python导出chrome书签到markdown文件的实例代码
Dec 27 Python
TensorFlow模型保存/载入的两种方法
Mar 08 Python
Python日期时间对象转换为字符串的实例
Jun 22 Python
python的debug实用工具 pdb详解
Jul 12 Python
基于MATLAB和Python实现MFCC特征参数提取
Aug 13 Python
pycharm配置git(图文教程)
Aug 16 Python
Python中Subprocess的不同函数解析
Dec 10 Python
python中的split()函数和os.path.split()函数使用详解
Dec 21 Python
python实现加密的方式总结
Jan 19 Python
Pytest之测试命名规则的使用
Apr 16 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
在服务端进行目录建立、删除,文件上传、删除的过程的php代码
2008/09/10 PHP
使用session判断用户登录用户权限(超简单)
2013/06/08 PHP
php仿QQ验证码的实例分析
2013/07/01 PHP
PHP编译安装中遇到的两个错误和解决方法
2014/08/20 PHP
PHP实现通过二维数组键值获取一维键名操作示例
2019/10/11 PHP
JS弹出对话框返回值代码(asp.net后台)
2010/12/28 Javascript
dojo学习第二天 ajax异步请求之绑定列表
2011/08/29 Javascript
js 调用本地exe的例子(支持IE内核的浏览器)
2012/12/26 Javascript
微信小程序  wx.request合法域名配置详解
2016/11/23 Javascript
vue2.0中vue-cli实现全选、单选计算总价格的实例代码
2017/07/18 Javascript
js Element Traversal规范中的元素遍历方法
2018/04/19 Javascript
React.js绑定this的5种方法(小结)
2018/06/05 Javascript
ES6 系列之 Generator 的自动执行的方法示例
2018/10/19 Javascript
JS实现扫码枪扫描二维码功能
2020/01/03 Javascript
vue自定义组件实现双向绑定
2021/01/13 Vue.js
[32:56]完美世界DOTA2联赛PWL S3 Rebirth vs CPG 第二场 12.11
2020/12/16 DOTA
python实现telnet客户端的方法
2015/04/15 Python
分数霸榜! python助你微信跳一跳拿高分
2018/01/08 Python
python之从文件读取数据到list的实例讲解
2018/04/19 Python
Python中.join()和os.path.join()两个函数的用法详解
2018/06/11 Python
Python3 Post登录并且保存cookie登录其他页面的方法
2018/12/28 Python
python使用参数对嵌套字典进行取值的方法
2019/04/26 Python
如何通过50行Python代码获取公众号全部文章
2019/07/12 Python
python opencv圆、椭圆与任意多边形的绘制实例详解
2020/02/06 Python
Django Form设置文本框为readonly操作
2020/07/03 Python
python tkinter实现下载进度条及抖音视频去水印原理
2021/02/07 Python
css3 border旋转时的动画应用
2016/01/22 HTML / CSS
美国批发供应商:Kole Imports
2019/04/10 全球购物
C&A巴西网上商店:时尚、衣服、手机和鞋子
2020/06/07 全球购物
颇特女士香港官网:NET-A-PORTER香港
2021/03/08 全球购物
求职信的最佳写作思路
2014/02/01 职场文书
飘柔洗发水广告词
2014/03/14 职场文书
小学生国庆演讲稿
2014/09/05 职场文书
领导班子作风建设年个人整改措施
2014/09/29 职场文书
运动会5000米加油稿
2015/07/21 职场文书
学校教代会开幕词
2016/03/04 职场文书