import pygame,random,time
from pygame.sprite import Sprite
# 定义常量
SCREEN_WIDTH = 1500
SCREEN_HEIGHT = 750
BG_COLOR = pygame.Color(0,0,0)
TEXT_COLOR = pygame.Color(255,0,0)
# 创建精灵基类
class BaseItem(Sprite):
pass
# 主类
class MainGame():
window = None
Mytank = None
enemyCount = 5
enemyList = []
MybulletList = []
enemybulletList = []
explodeList = []
walllist = []
# 初始化
def __init__(self):
pass
# 创建敌方坦克
def createenemytank(self):
top = 100
speed = 3
for i in range(MainGame.enemyCount):
left = random.randint(0,1500)
enemyTank = enemytank(left,top,speed)
# 添加到列表
MainGame.enemyList.append(enemyTank)
# 加载敌方坦克
def displayenemytank(self):
for enemyTank in MainGame.enemyList:
if enemyTank.live:
enemyTank.displaytank()
# 调用move使敌方坦克移动
enemyTank.randmove()
# 判断是否与墙壁碰撞
enemyTank.tank_hit_wall()
# 判断敌方坦克是否与我方坦克碰撞
enemyTank.tank_hit_tank(MainGame.Mytank)
# 初始化敌方坦克发射的子弹
enemybullet = enemyTank.shot()
if enemybullet:
MainGame.enemybulletList.append(enemybullet)
else:# 当前敌方坦克已经死亡,从敌方坦克列表移除
MainGame.enemyList.remove(enemyTank)
def displaymybullet(self):
for Mybullet in MainGame.MybulletList:
# 判断子弹是否存活
if Mybullet.live:
Mybullet.displaybullet()
# 调用子弹移动方法
Mybullet.move()
# 调用我方子弹是否和敌方坦克碰撞
Mybullet.Mybullet_hit_enemytank()
# 判断子弹是否击中墙壁
Mybullet.hit_wall()
else:
# 从子弹列表删除子弹
MainGame.MybulletList.remove(Mybullet)
def displayenemybullet(self):
for enemybullet in MainGame.enemybulletList:
if enemybullet.live:
enemybullet.displaybullet()
enemybullet.move()
# 调用敌方子弹与我方坦克碰撞检测
enemybullet.enemyBullet_hit_mytank()
# 判断是否击中墙壁
enemybullet.hit_wall()
else:
MainGame.enemybulletList.remove(enemybullet)
def displayExplodeList(self):
for explode in MainGame.explodeList:
# 判断是否存活
if explode.live:
# 展示
explode.disexplode()
else:
# 从爆炸效果中移除
MainGame.explodeList.remove(explode)
# 创建我方坦克
def createmytank(self):
MainGame.Mytank = tank(400,680)
# 创建音乐对象
Music = music("E/pygame.坦克大战/start")
# 播放音乐
Music.playmusic()
# 创建墙壁
def createwall(self):
top = 300
for i in range(6):
# 初始化墙壁
wall = Wall(i*288,top)
# 添加到墙壁列表
MainGame.walllist.append(wall)
# 加载墙壁
def displaywall(self):
for Wall in MainGame.walllist:
# 判断墙壁状态
if Wall.live:
Wall.displaywall()
else:
MainGame.walllist.remove(Wall)
# 开始游戏
def startGame(self):
# 初始化窗口
pygame.display.init()
# 设置窗口大小
MainGame.window = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
# 设置窗口的标题
pygame.display.set_caption("坦克大战")
# 初始化我方坦克
self.createmytank()
# 创建敌方坦克
self.createenemytank()
# 创建墙壁
self.createwall()
while True:
time.sleep(0.01)
# 添加事件监听
self.getEvent()
# 添加文字信息
textSurface = self.getTextSurface("敌方坦克剩余数量%d " %len(MainGame.enemyList))
# 给窗口设置填充色
MainGame.window.fill(BG_COLOR)
# 主窗口显示文字信息
MainGame.window.blit(textSurface,(10,10))
# 调用坦克的显示方法
if MainGame.Mytank and MainGame.Mytank.live:
MainGame.Mytank.displaytank()
else:
# 删除我方坦克
del MainGame.Mytank
MainGame.Mytank = None
if MainGame.Mytank and MainGame.Mytank.live:
if not MainGame.Mytank.stop:
# 我方坦克移动
MainGame.Mytank.move()
# 检测我方坦克是否与墙壁发生碰撞
MainGame.Mytank.tank_hit_wall()
# 检测我方坦克是否与敌方坦克碰撞
for enemytank in MainGame.enemyList:
MainGame.Mytank.tank_hit_tank(enemytank)
# 调用敌方坦克
self.displayenemytank()
# 加载我方坦克发射的子弹
self.displaymybullet()
# 加载敌方坦克发射的子弹
self.displayenemybullet()
# 调用爆炸效果方法
self.displayExplodeList()
# 显示墙壁
self.displaywall()
pygame.display.update()
# 结束游戏
def endGame(self):
print("谢谢使用,期待与您的下次相见")
exit()
# 添加文字信息提示
def getTextSurface(self,text):
# 初始化字体模块
pygame.font.init()
# 获取所有字体
# print(font.get_fonts())
# 获取字体对象
font = pygame.font.SysFont("kaiti",18)
# 绘制文字信息
textSurface = font.render(text,True,TEXT_COLOR)
return textSurface
def getEvent(self):
# 获取所有的事件
eventList = pygame.event.get()
# 遍历事件
for event in eventList:
# 判断按下是否关闭
if event.type == pygame.QUIT:
self.endGame()
# 判断是否是键盘事件
if event.type == pygame.KEYDOWN:
# 判断我方坦克是否消亡
if not MainGame.Mytank:
# 判断按下的键是否是esc键
if event.key == pygame.K_ESCAPE:
# 调用创建我方坦克的方法
self.createmytank()
if MainGame.Mytank and MainGame.Mytank.live:
# 判断按下的是什么建
if event.key == pygame.K_a:
print("按下a键,坦克向左移动")
# 修改我方坦克的方向
MainGame.Mytank.direction = "a"
# 修改坦克移动开关
MainGame.Mytank.stop = False
elif event.key == pygame.K_d:
print("按下d键,坦克向右移动")
# 修改我方坦克的方向
MainGame.Mytank.direction = "d"
# 修改坦克移动开关
MainGame.Mytank.stop = False
elif event.key == pygame.K_w:
print("按下w键,坦克向上移动")
# 修改我方坦克的方向
MainGame.Mytank.direction = "w"
# 修改坦克移动开关
MainGame.Mytank.stop = False
elif event.key == pygame.K_s:
print("按下s键,坦克向下移动")
# 修改我方坦克的方向
MainGame.Mytank.direction = "s"
# 修改坦克移动开关
MainGame.Mytank.stop = False
elif event.key == pygame.K_j:
print("发射子弹")
if len(MainGame.MybulletList) < 3:
# 初始化子弹
Mybullet = bullet(MainGame.Mytank)
MainGame.MybulletList.append(Mybullet)
# 判断键盘是否松开
if event.type == pygame.KEYUP:
if MainGame.Mytank and MainGame.Mytank.live:
if event.key == pygame.K_w or event.key == pygame.K_a or event.key == pygame.K_s or event.key == pygame.K_d:
print("松开移动键,停止移动")
MainGame.Mytank.stop = True
# 坦克类
class tank(BaseItem):
# 初始化
def __init__(self,left,top):
# 保存加载的图片
self.images = {
"w": pygame.image.load("E:/pygame.坦克大战/p1tankU.gif"),
"s": pygame.image.load("E:/pygame.坦克大战/p1tankD.gif"),
"a": pygame.image.load("E:/pygame.坦克大战/p1tankL.gif"),
"d": pygame.image.load("E:/pygame.坦克大战/p1tankR.gif")
}
# 设置坦克方向
self.direction = "w"
# 根据坦克的方向,获取加载的图片
self.image = self.images.get(self.direction)
# 根据图片获取的图片的矩形区域
self.rect = self.image.get_rect()
# 设置区域的left和top
self.rect.left = left
self.rect.top = top
# 速度
self.speed = 3
# 坦克移动开关
self.stop = True
# 生存状态
self.live = True
# 展示坦克
def displaytank(self):
self.image = self.images.get(self.direction)
# 调用blit方法展示坦克
MainGame.window.blit(self.image,self.rect)
# 坦克移动
def move(self):
# 坦克的移动,记录坦克的位置,为了还原碰撞位置
self.old_left = self.rect.left
self.old_top = self.rect.top
# 判断坦克的方向
if self.direction == "a":
if self.rect.left > 0:
self.rect.left -= self.speed
elif self.direction == "d":
if self.rect.left + self.rect.height < SCREEN_WIDTH:
self.rect.left += self.speed
elif self.direction == "w":
if self.rect.top > 0:
self.rect.top -= self.speed
elif self.direction == "s":
if self.rect.top + self.rect.width < SCREEN_HEIGHT:
self.rect.top += self.speed
# 发射子弹
def shot(self):
pass
def tank_hit_wall(self):
for Wall in MainGame.walllist:
# 检测当前坦克是否和墙壁碰撞,将位置还原到碰撞前的位置
if pygame.sprite.collide_rect(self,Wall):
self.rect.left = self.old_left
self.rect.top = self.old_top
def tank_hit_tank(self,tank):
# 判断坦克是否都存活
if self.live and tank.live:
# 检测两个坦克之间的碰撞
if pygame.sprite.collide_rect(self,tank):
self.rect.left = self.old_left
self.rect.top = self.old_top
# 我方坦克类
class mytank(tank):
# 初始化
def __init__(self):
pass
# 敌方坦克
class enemytank(tank):
# 初始化
def __init__(self,left,top,speed):
# 调用父类初始化方法
super(enemytank,self).__init__(left,top)
# 加载保存的图片集
self.images = {
"w":pygame.image.load("E:/pygame.坦克大战/enemy1U.gif"),
"a":pygame.image.load("E:/pygame.坦克大战/enemy1L.gif"),
"s":pygame.image.load("E:/pygame.坦克大战/enemy1D.gif"),
"d":pygame.image.load("E:/pygame.坦克大战/enemy1R.gif")
}
# 设置敌方坦克方向
self.direction = self.randDirection()
# 根据方向获取图片
self.image = self.images.get(self.direction)
# 获取图片矩形区域
self.rect = self.image.get_rect()
# 设置left top
self.rect.left = left
self.rect.top = top
self.speed = speed
# 步数
self.step = 100
# 随机生成方向
def randDirection(self):
num = random.randint(1,4)
if num == 1:
return "w"
elif num == 2:
return "a"
elif num == 3:
return "s"
elif num == 4:
return "d"
# 随机移动敌方坦克方法
def randmove(self):
if self.step <= 0:
#修改敌方坦克方向
self.direction = self.randDirection()
# 让步数重置
self.step = 100
else:
self.move()
# 步数递减
self.step -= 1
def shot(self):
num = random.randint(0,1000)
if num < 8:
return bullet(self)
# 子弹类
class bullet(BaseItem):
# 初始化
def __init__(self,tank):
# 加载子弹图片
self.image = pygame.image.load("E:/pygame.坦克大战/enemymissile.gif")
# 子弹的方向
self.direction = tank.direction
# 根据图片获取区域
self.rect = self.image.get_rect()
# 设置left top
if self.direction == "w":
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 == "s":
self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2
self.rect.top = tank.rect.top + tank.rect.width
elif self.direction == "a":
self.rect.left = tank.rect.left - self.rect.width
self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2
elif self.direction == "d":
self.rect.left = tank.rect.left + tank.rect.width
self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2
# 子弹的速度
self.speed = 6
# 子弹是否存活
self.live = True
# 展示子弹
def displaybullet(self):
# 将图片加载到窗口
MainGame.window.blit(self.image,self.rect)
# 子弹移动
def move(self):
if self.direction == "w":
if self.rect.top > 0 :
self.rect.top -= self.speed
else:
self.live = False
elif self.direction == "s":
if self.rect.top + self.rect.height < SCREEN_HEIGHT:
self.rect.top += self.speed
else:
self.live = False
elif self.direction == "a":
if self.rect.left > 0:
self.rect.left -= self.speed
else:
self.live = False
elif self.direction == "d":
if self.rect.left + self.rect.width < SCREEN_WIDTH:
self.rect.left += self.speed
else:
self.live = False
# 我方子弹与敌方坦克碰撞检测
def Mybullet_hit_enemytank(self):
# 循环遍历敌方坦克列表
for enemyTank in MainGame.enemyList:
if pygame.sprite.collide_rect(self,enemyTank):
# 修改敌方坦克与我方子弹生存状态
enemyTank.live = False
self.live = False
# 初始化爆炸效果类
Explode = explode(enemyTank)
# 添加爆炸效果到爆炸效果列表类
MainGame.explodeList.append(Explode)
# 敌方子弹与我方坦克碰撞
def enemyBullet_hit_mytank(self):
if MainGame.Mytank and MainGame.Mytank.live:
if pygame.sprite.collide_rect(self,MainGame.Mytank):
# 产生爆炸效果
Explode = explode(MainGame.Mytank)
# 将爆炸效果添加到爆炸效果列表
MainGame.explodeList.append(Explode)
# 修改敌方子弹与我方坦克的生存状态
self.live = False
MainGame.Mytank.live = False
def hit_wall(self):
for Wall in MainGame.walllist:
# 判断是否碰撞
if pygame.sprite.collide_rect(self,Wall):
# 修改子弹状态
self.live = False
# 修改墙壁的生命值
Wall.hp -= 1
# 判断墙壁是否显示
if Wall.hp <= 0:
Wall.live = False
# 墙壁类
class Wall():
# 初始化
def __init__(self,left,top):
# 加载墙壁图片
self.image = pygame.image.load("E:/pygame.坦克大战/steels.gif")
# 根据图片获取区域
self.rect = self.image.get_rect()
# 设置left top
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 explode():
# 初始化
def __init__(self,tank):
# 爆炸效果位置
self.rect = tank.rect
self.images = [
pygame.image.load("E:/pygame.坦克大战/blast0.gif"),
pygame.image.load("E:/pygame.坦克大战/blast1.gif"),
pygame.image.load("E:/pygame.坦克大战/blast2.gif"),
pygame.image.load("E:/pygame.坦克大战/blast3.gif"),
pygame.image.load("E:/pygame.坦克大战/blast4.gif")
]
self.step = 0
self.image = self.images[self.step]
# 生存状态
self.live = True
# 展示爆炸
def disexplode(self):
if self.step < len(self.images):
self.image = self.images[self.step]
self.step += 1
# 添加到主窗口
MainGame.window.blit(self.image,self.rect)
else:
# 修改存活状态
self.live = False
self.step = 0
# 音乐类
# 音乐类
class music():
pygame.mixer.init()
# 初始化
def __init__(self):
# 创建音乐文件
pygame.mixer.music.load("E/pygame.坦克大战")
# 播放音乐
def playmusic(self):
pygame.mixer.music.play()
if __name__ == '__main__':
# 调用主类中的startGame
MainGame().startGame()
Traceback (most recent call last):
File "C:\PycharmProjects\tank01.py", line 541, in <module>
MainGame().startGame()
File "C:\PycharmProjects\tank01.py", line 125, in startGame
self.createmytank()
File "C:\PycharmProjects\tank01.py", line 95, in createmytank
Music = music("E/pygame.坦克大战/start")
TypeError: music.__init__() takes 1 positional argument but 2 were given
老师这哪出问题了