python实现坦克大战游戏 附详细注释
作者:浪荡之徒 发布时间:2023-06-26 07:58:13
标签:python,坦克大战
本文实例为大家分享了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微信跳一跳游戏集合
来源:https://blog.csdn.net/Chujianlong321/article/details/89215708


猜你喜欢
- MySQL字符集:cp1252 West European (latin1) ,解决乱码问题 使用虚拟主机空间上的phpmyadmin操作数
- 本文实例讲述了thinkPHP框架通过Redis实现增删改查操作的方法。分享给大家供大家参考,具体如下:一、概述Redis是一个NoSQL数
- 一、函数解释setdiff1d(ar1, ar2, assume_unique=False)1.功能:找到2个数组中集合元素的差异。2.返回
- 1 concatconcat函数是在pandas底下的方法,可以将数据根据不同的轴作简单的融合pd.concat(objs, axis=0,
- 将Excel中的数据导入到Access中,前提是在Access中的表已经建好。 dim conn dim co
- 本文实例讲述了JSP使用MVC模式完成删除和修改功能的方法。分享给大家供大家参考。具体如下:目标:① 进一步理解MVC模式;② 掌握删除功能
- 解决Microsoft VBScript 运行时错误 (0x800A0046) 没有权限的解决方案,0x800a0046错误。前段时间在做站
- 如何调用多个不同的ip接口灵感来源:项目的登录登出权限是调A的ip下面的接口,其他的功能调的接口是B的ip下面的接口思路:其实就是多写几个r
- SQL Server2000中,如果数据库文件(非系统数据库文件)遇到错误的时候,我们该怎么办。以下是笔者以前的笔记。仅适用于非master
- 下面这段代码是兼容IE的图片切换代码,请问各位老鸟如何兼容FF,或者有相类似无按钮无数字兼容FF的图片切换代码?<!DOCTYPE h
- CKEditor官方演示是有上传图片和浏览服务器文件功能的,但是我们自己下载回来的却没有这两个功能…… 其实还需要下载另外一个组件:CKFi
- 之前博客有用logstash-input-jdbc同步mysql数据到ElasticSearch,但是由于同步时间最少是一分钟一次,无法满足
- Dataframe结构放在numpy来看应该是二维矩阵的形式,每一列是一个特征,上面会有个列标题,每一行是一个样本。对Dataframe结构
- 本文实例讲述了Python元组常见操作。分享给大家供大家参考,具体如下:不能修改的列表就叫做元组。1 访问元素元组是使用圆括号来标识的。 定
- 先看一下总体效果:上传文件做了大小和类型的限制,在动图中无法展现出来。使用file类型的input实现选择本地文件但是浏览器原生的文件上传按
- 天冷,人懒,事多,我就不全文翻译了。只列几个标题,很多内容完全按照我自己的理解写了一下。想读原汁原味的请移步:Icon design tre
- 01 Go中的泛型是什么众所周知,Go是一门静态类型的语言。静态类型也就意味着在使用Go语言编程时,所有的变量、函数参数都需要指定具体的类型
- python中有指定的代码进行输入操作,所以今天就由小编来为大家介绍python怎么实现键盘输入。第一首先打开电脑的python编辑工具。再
- Pygame的Font文本和字体Pygame 通过pygame.font模块来创建一个字体对象,从而实现绘制文本的目的。该模块的常用方法如下
- 相信大家都试过将Python文件进行打包,来发给其他没有安装Python环境的用户使用,但通常情况下,打包生成的exe文件都很大,而产生这种