"""
新增功能：
    1音效处理
"""
#导入pygame模块
import pygame,time,random
SCREEN_WIDTH = 700
SCREEN_HEIGHT = 500
BG_COLOR = pygame.Color(0,0,0)
TEXT_COLOR = pygame.Color(255,0,0)
version = 1.25
class MainGame():
    window=None
    my_tank=None
    #创建存储敌方坦克的列表
    enemyTankList=[]
    #定义敌方坦克的数量
    enemyTankCount= 5
    #存储我方子弹的列表
    bulletList=[]
    #存储敌方子弹的列表
    Enemy_bulletList = []
    #爆炸效果列表
    ExplodeList = []
    #墙壁列表
    WallList = []
    def __init__(self):
        pass
    #开始游戏
    def startGame(self):
        #加载主窗口
        #初始化窗口
        pygame.display.init()
        #设置窗口的大小及显示
        MainGame.window = pygame.display.set_mode([SCREEN_WIDTH,SCREEN_HEIGHT])
        #初始化我方坦克
        self.createPlayerTank()
        #初始化敌方坦克 并将敌方坦克添加到列表中
        self.createEnemyTank()
        self.createWalls()
        #设置窗口的标题
        pygame.display.set_caption("坦克大战"+str(version))
        while True:
            time.sleep(0.02)
            #给窗口设置填充色
            MainGame.window.fill(BG_COLOR)
            #获取事件
            self.getEvent()
            #绘制文字
            MainGame.window.blit(self.getTextSurface("敌方坦克剩余数量%d"%len(MainGame.enemyTankList)),(10,10))
            #调用战术墙壁的方法
            self.blitWalls()
            #调用坦克显示的方法
            if MainGame.my_tank and MainGame.my_tank.live:
                MainGame.my_tank.diaplayTank()

            else:
                del MainGame.my_tank
                MainGame.my_tank = None
            #循环遍历敌方坦克列表，展示敌方坦克
            self.blitEnemyTank()
            #调用渲染敌方子弹的列表的一个方法
            self.blitEnemyBullet()
            self.blitWalls()
            #调用展示爆炸效果的方法
            self.displayExplodes()
            # 坦克移动
            if MainGame.my_tank and not MainGame.my_tank.stop:
                MainGame.my_tank.move()
                MainGame.my_tank.hitWalls()
                MainGame.my_tank.hitEnemyTank()
            #调用渲染子弹列表的一个方法
            self.blitBullet()
            pygame.display.update()
    #创建我方坦克的方法
    def createPlayerTank(self):
        #创建我方坦克
        MainGame.my_tank = MyTank(260, 300)
        #创建音乐对象
        music = Music('img/start.wav')
        #调用音乐对象
        music.play()
    #初始化敌方坦克 并将敌方坦克添加到列表中
    def createEnemyTank(self):
        top = 100
        #循环生成敌方坦克
        for i in range(MainGame.enemyTankCount):
            left = random.randint(0,600)
            speed = random.randint(1,5)
            enemy = EnemyTank(left,top,speed)
            MainGame.enemyTankList.append(enemy)
    # 新增创建墙壁的方法
    def createWalls(self):
        top = 180
        for i in range(0,7):
            wall = Wall(130*i,top)
            MainGame.WallList.append(wall)
    #循环遍历敌方坦克列表，展示敌方坦克
    def blitEnemyTank(self):
        for enemyTank in MainGame.enemyTankList:
            if enemyTank.live:
                enemyTank.diaplayTank()
                enemyTank.randMove()
                enemyTank.hitWalls()
                #敌方坦克是否撞到我方坦克
                enemyTank.hitMyTank()
                # 敌方坦克的设计
                eBullet = enemyTank.shot()
                #如果子弹为None，不加入到列表
                if eBullet:
                    #将子弹存储敌方子弹列表
                    MainGame.Enemy_bulletList.append(eBullet)
            else:
                MainGame.enemyTankList.remove(enemyTank)
    #将子弹加入到窗口中
    def blitBullet(self):
        for bullet in MainGame.bulletList:
            # 如果子弹活着渲染子弹 如果死了从子弹列表中移除
            if bullet.live:
                bullet.display()
                # 让子弹移动
                bullet.move()
                #调用我方子弹与敌方坦克的碰撞方法
                bullet.hitEnemyTank()
                #调用我方子弹是否碰撞到墙壁的方法
                bullet.hitWalls()
            else:
                MainGame.bulletList.remove(bullet)
    #将敌方子弹加入到窗口中
    def blitEnemyBullet(self):
        for ebullet in MainGame.Enemy_bulletList:
            # 如果子弹活着渲染子弹 如果死了从子弹列表中移除
            if ebullet.live:
                ebullet.display()
                # 让子弹移动
                ebullet.move()
                #调用是否碰撞到墙壁的方法
                ebullet.hitWalls()
                if MainGame.my_tank and MainGame.my_tank.live:
                    ebullet.hitPlayerTank()
            else:
                MainGame.Enemy_bulletList.remove(ebullet)
    def blitWalls(self):
        for wall in MainGame.WallList:
            if wall.live:
                wall.displayWall()
            else:
                MainGame.WallList.remove(wall)
    #新增方法：展示爆炸效果效果列表
    def displayExplodes(self):
        for explode in MainGame.ExplodeList:
            if explode.live:
                explode.displayExplode()
            else:
                MainGame.ExplodeList.remove(explode)

    #结束游戏
    def endGame(self):
        print("Thank you for your playing")
        exit()
    #左上角文字的绘制
    def getTextSurface(self,text):
        #初始化字体模块
        pygame.font.init()
        # 查看所有的字体名称
        #print(pygame.font.get_fonts())
        # 获取字体Font对象
        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:
                #点击r键让我方坦克重生
                if event.key == pygame.K_r and not MainGame.my_tank:
                    #调用创建我方坦克的方法
                    self.createPlayerTank()
                if MainGame.my_tank and MainGame.my_tank.live:
                    #判断按下的是上、下、左、右
                    if event.key == pygame.K_LEFT:
                        #切换方向
                        MainGame.my_tank.direction="L"
                        MainGame.my_tank.stop=False
                        #MainGame.my_tank.move()
                        print('按下左键，坦克向左移动')
                    elif event.key == pygame.K_RIGHT:
                        MainGame.my_tank.direction = "R"
                        #MainGame.my_tank.move()
                        MainGame.my_tank.stop = False
                        print('按下右键，坦克向右移动')
                    elif event.key == pygame.K_UP:
                        MainGame.my_tank.direction = "U"
                        #MainGame.my_tank.move()
                        MainGame.my_tank.stop = False
                        print('按下上键，坦克向上移动')
                    elif event.key == pygame.K_DOWN:
                        MainGame.my_tank.direction = "D"
                        #MainGame.my_tank.move()
                        MainGame.my_tank.stop = False
                        print('按下下键，坦克向下移动')
                    elif event.key == pygame.K_SPACE:
                        print("发射子弹")
                        if len(MainGame.bulletList)<3:
                            #产生一个颗子弹
                            bullet = MainGame.my_tank.shot()
                            #将子弹加入到子弹列表
                            MainGame.bulletList.append(bullet)
                            music = Music('img/fire.wav')
                            music.play()
                        else:
                            print("子弹数量不足")
                        print("当前子弹的数量：%d"%len(MainGame.bulletList))
                #松开方向键 坦克停止移动 修改该坦克的开关

            if event.type == pygame.KEYUP:
                #松开的方向键是上下左右 才修改坦克的开关
                if event.key == pygame.K_UP or event.key == pygame.K_DOWN or event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                    if MainGame.my_tank and MainGame.my_tank.live:
                       MainGame.my_tank.stop = True

class BaseItem(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
class Tank(BaseItem):
    # 添加距离左边left的 距离上边top
    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'
        #根据当前图片的方向获取图片 surface
        self.image=self.images[self.direction]
        #根据图片获取区域
        self.rect = self.image.get_rect()
        #设置区域的left和top
        self.rect.left=left
        self.rect.top=top
        #速度 决定移动的快慢
        self.speed=5
        #坦克移动的开关
        self.stop=True
        #新增属性 记录坦克是否活着
        self.live=True
        #新增属性：用来记录坦克移动之前的坐标(用于坐标还原时使用)
        self.oldLeft = self.rect.left
        self.oldTop = self.rect.top
    #移动
    def move(self):
        #先记录移动之前的坐标
        self.oldLeft = self.rect.left
        self.oldTop = self.rect.top
        #判断坦克的方向进行移动
        if self.direction == 'L' and self.rect.left >0:
            self.rect.left -= self.speed
        if self.direction == "R" and self.rect.left < SCREEN_WIDTH-self.rect.width:
            self.rect.left += self.speed
        if self.direction == 'D' and self.rect.top < SCREEN_HEIGHT-self.rect.height:
            self.rect.top += self.speed
        if self.direction == 'U' and self.rect.top >0:
            self.rect.top -= self.speed

    def stay(self):
        self.rect.left = self.oldLeft
        self.rect.top = self.oldTop
    # 新增碰撞墙壁的方法
    def hitWalls(self):
        for wall in MainGame.WallList:
            if pygame.sprite.collide_rect(wall,self):
                self.stay()
    #射击
    def shot(self):
        return Bullet(self)
    #显示坦克的方法
    def diaplayTank(self):
        #获取展示的对象
        self.image = self.images[self.direction]
        #调用blit方法展示
        MainGame.window.blit(self.image,self.rect)
    #坦克
#我方坦克
class MyTank(Tank):
    def __init__(self,left,top):
        super().__init__(left,top)
    #新增主动碰撞到敌方坦克的方法
    def hitEnemyTank(self):
        for eTank in MainGame.enemyTankList:
            if pygame.sprite.collide_rect(self,eTank):
                self.stay()

#敌方坦克
class EnemyTank(Tank):
    def __init__(self,left,top,speed):
        super().__init__(left,top)
        #加载图片
        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]
        #区域
        self.rect = self.image.get_rect()
        #对left和top进行赋值
        self.rect.left = left
        self.rect.top = top
        #速度
        self.speed = speed
        #移动开关
        self.flag = True
        #步数
        self.step =20
    #随机生成敌方坦克的方向
    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:
            self.direction = self.randDirection()
            self.step = 20
        else:
            self.move()
            self.step -= 1

    def shot(self):
        num = random.randint(1,1000)
        if num <=15:
            return Bullet(self)
    def hitMyTank(self):
        if MainGame.my_tank and pygame.sprite.collide_rect(self,MainGame.my_tank):
            #让敌方坦克停下来
            self.stay()
#子弹类
class Bullet(BaseItem):
    def __init__(self,tank):
        #加载图片
        self.image =pygame.image.load('img/enemymissile.gif')
        #坦克的方向决定子弹的方向
        self.direction = tank.direction
        #获取区域
        self.rect = self.image.get_rect()
        #子弹的left和top与方向有关
        if self.direction == 'U':
            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+tank.rect.height
        elif self.direction == 'L':
            self.rect.left = tank.rect.left-self.rect.width
            self.rect.top = tank.rect.top+tank.rect.height/2-self.rect.height/2
        elif self.direction == 'R':
            self.rect.left = tank.rect.left+tank.rect.width
            self.rect.top = tank.rect.top+tank.rect.height/2-self.rect.height/2
        #子弹的速度
        self.speed = 6
        #子弹的死活
        self.live = True
        #开火音效
        if self == MyTank:
            Music('img/fire.wav').play()
    #移动
    def move(self):
        if self.direction == 'U' and self.rect.top > -self.rect.height:
            self.rect.top -= self.speed
        elif self.direction == 'D' and self.rect.top < SCREEN_HEIGHT:
            self.rect.top += self.speed
        elif self.direction == 'L' and self.rect.left > -self.rect.width:
            self.rect.left -= self.speed
        elif self.direction == 'R' and self.rect.left < SCREEN_WIDTH:
            self.rect.left += self.speed
        else:
            self.live = False
    #显示子弹的方法
    def display(self):
        #将图片surface加载到窗口
        MainGame.window.blit(self.image,self.rect)
    #新增我方子弹碰撞敌方坦克的方法
    def hitEnemyTank(self):
        for eTank in MainGame.enemyTankList:
            if pygame.sprite.collide_rect(self,eTank):
                #产生一个爆炸效果
                explode = Explode(eTank)
                #将爆炸效果加入到爆炸效果列表
                MainGame.ExplodeList.append(explode)
                self.live = False
                eTank.live = False
                #打中敌人音效
                Music('img/hit.wav').play()

    #新增敌方子弹与我方坦克的碰撞
    def hitPlayerTank(self):
        if pygame.sprite.collide_rect(self,MainGame.my_tank):
            # 产生爆炸效果，并加入到爆炸效果列表中
            explode = Explode(MainGame.my_tank)
            MainGame.ExplodeList.append(explode)
            #修改子弹状态
            self.live = False
            #修改我方坦克状态
            MainGame.my_tank.live = False
    # 新增子弹与墙壁的碰撞
    def hitWalls(self):
        for wall in MainGame.WallList:
            if pygame.sprite.collide_rect(self,wall):
                #修改子弹的live属性
                self.live = False
                wall.hp -= 1
                if wall.hp <= 0:
                    wall.live = False
                # 打中敌人音效
                Music('img/hit.wav').play()


#墙壁类
class Wall(BaseItem):
    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 Explode():
    def __init__(self,tank):
        self.rect = tank.rect
        self.step = 0
        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'),
        ]
        self.image = self.images[self.step]
        self.live = True
    #展示爆炸效果的方法
    def displayExplode(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.step = 0
            self.live = False
#音乐类
#我方坦克出生
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()

if __name__ == "__main__":
    MainGame().startGame()
    #MainGame().getTextSurface()


