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实现调度算法代码详解
Dec 01 Python
django上传图片并生成缩略图方法示例
Dec 11 Python
python3实现跳一跳点击跳跃
Jan 08 Python
在mac下查找python包存放路径site-packages的实现方法
Nov 06 Python
Python实现从SQL型数据库读写dataframe型数据的方法【基于pandas】
Mar 18 Python
python图形工具turtle绘制国际象棋棋盘
May 23 Python
Python切图九宫格的实现方法
Oct 10 Python
python使用itchat模块给心爱的人每天发天气预报
Nov 25 Python
用python绘制樱花树
Oct 09 Python
python3.8动态人脸识别的实现示例
Sep 21 Python
Python内置函数及功能简介汇总
Oct 13 Python
Python使用scapy模块发包收包
May 07 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
PHP4之真OO
2006/10/09 PHP
深入file_get_contents与curl函数的详解
2013/06/25 PHP
PHP错误Parse error: syntax error, unexpected end of file in test.php on line 12解决方法
2014/06/23 PHP
PHP获取当前相对于域名目录的方法
2015/06/26 PHP
PHP高精确度运算BC函数库实例详解
2017/08/15 PHP
关于php支持的协议与封装协议总结(推荐)
2017/11/17 PHP
PHP检测接口Traversable用法详解
2017/12/29 PHP
Laravel 将数据表的数据导出,并生成seeds种子文件的方法
2019/10/09 PHP
JavaScript初学者需要了解10个小技巧
2010/08/25 Javascript
jQuery之选择组件的深入解析
2013/06/19 Javascript
PHP开发者必须掌握的6个关键字
2014/04/14 Javascript
js正则匹配出所有图片及图片地址src的方法
2015/06/08 Javascript
在Node.js应用中使用Redis的方法简介
2015/06/24 Javascript
跟我学习javascript的垃圾回收机制与内存管理
2015/11/23 Javascript
JS获取一个未知DIV高度的方法
2016/08/09 Javascript
Angular2 多级注入器详解及实例
2016/10/30 Javascript
Bootstrap路径导航与分页学习使用
2017/02/08 Javascript
Vue2几种常见开局方式详解
2017/09/09 Javascript
vue-router2.0 组件之间传参及获取动态参数的方法
2017/11/10 Javascript
Angular使用ControlValueAccessor创建自定义表单控件
2019/03/08 Javascript
vue的路由映射问题及解决方案
2019/10/14 Javascript
Python实现类似jQuery使用中的链式调用的示例
2016/06/16 Python
python @property的用法及含义全面解析
2018/02/01 Python
python opencv 直方图反向投影的方法
2018/02/24 Python
wxPython实现绘图小例子
2019/11/19 Python
python中with语句结合上下文管理器操作详解
2019/12/19 Python
Python解释器及PyCharm工具安装过程
2020/02/26 Python
HTML5的新特性(1)
2016/03/03 HTML / CSS
用html5绘制折线图的实例代码
2016/03/25 HTML / CSS
解决canvas转base64/jpeg时透明区域变成黑色背景的方法
2016/10/23 HTML / CSS
中国第一家杂志折扣订阅网:杂志铺
2016/08/30 全球购物
eBay爱尔兰站:eBay.ie
2019/08/09 全球购物
我的兄弟姐妹观后感
2015/06/15 职场文书
母亲节主题班会
2015/08/14 职场文书
《珍珠鸟》教学反思
2016/02/16 职场文书
如何使JavaScript休眠或等待
2021/04/27 Javascript