Python 坦克大战小游戏进阶 版本号v1.14

python初阶

'''
v1.14 实现墙壁类  以及 子弹与墙壁的碰撞
'''
import pygame,time,random
SCREEN_WIDTH = 900
SCREEN_HEIGHT = 550
VERSION = 'V1.14'
# v1.07新增 记录敌方坦克的数量
ENEMY_TANK_COUNT = 5
# 主逻辑类
class MainGame():
    # 游戏主窗口
    window = None
    # 我方坦克(唯一性)设置成类属性
    tank1 = None
    # v1.07新增存储敌方坦克的列表
    enemy_tanklist = []
    # v1.09 新增存储我方子弹的列表
    mybullet_list = []
    # v1.11 新增存储敌方子弹的列表
    enemybullet_list = []
    # v1.13 新增 存储爆炸效果的列表
    explode_list = []
    # v.14 新增 创建存储墙壁的列表
    wall_list = []
    def startGame(self):
        # 调用窗口初始化方法
        pygame.display.init()
        # 在窗口左上角设置游戏标题
        pygame.display.set_caption('坦克大战'+VERSION)
        # 创建一个窗口屏幕显示表面
        MainGame.window = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
        # 调用创建我方坦克的方法
        self.createMytank()
        # 调用创建敌方坦克的方法
        self.createEnemytank()
        # v1.14 新增 调用创建墙壁的方法
        self.createWalls()
        while True:
            # 填充窗口背景色
            MainGame.window.fill((100,100,200))
            # 将获取的事件类型在填充完窗口背景色后时刻处于循环中
            self.getEvents()
            # v1.14 新增 调用展示墙壁的方法
            self.showWalls()
            # 展示我方坦克
            self.showMytank()
            # 调用展示敌方坦克的方法
            self.showEnemyTank()
            # v1.09 新增调用展示我方子弹的方法
            self.showMyBullet()
            # v1.11 新增调用展示敌方子弹的方法
            self.showEnemyBullet()
            # v1.13 调用展示爆炸效果的方法
            self.showExplode()
            # 更新
            pygame.display.update()
            # v1.06 新增程序休眠,优化坦克的移动速度
            time.sleep(0.025)
    # 获取所有事件处理的方法
    def getEvents(self):
        # 获取队列中的所有事件,遍历事件,对type为QUIT和KEYDOWN的两种事件类型进行处理
        eventList = pygame.event.get()
        # 遍历所有事件
        for e in eventList:
            # 当事件类型是QUIT时,退出游戏
            if e.type == pygame.QUIT:
                self.showMytank()
                # 退出游戏
                self.gameOver()
            #  当事件类型是KEYDOWN时,进行细化处理
            elif e.type == pygame.KEYDOWN:
                # 按下键盘上的向上按键时的处理
                if e.key == pygame.K_UP:
                    print('向上移动')
                    MainGame.tank1.direction = 'U'
                    # v1.06修改坦克的移动状态
                    MainGame.tank1.stop = False
                # 按下键盘上的向下按键时的处理
                elif e.key == pygame.K_DOWN:
                    print('向下移动')
                    MainGame.tank1.direction = 'D'
                    # v1.06修改坦克的移动状态
                    MainGame.tank1.stop = False
                # 按下键盘上的向左按键时的处理
                elif e.key == pygame.K_LEFT:
                    print('向左移动')
                    MainGame.tank1.direction = 'L'
                    MainGame.tank1.stop = False
                # 按下键盘上的向右按键时的处理
                elif e.key == pygame.K_RIGHT:
                    print('向右移动')
                    MainGame.tank1.direction = 'R'
                    MainGame.tank1.stop = False
                # 按下键盘上的空格按键时的处理
                elif e.key == pygame.K_SPACE:
                    print('biubiu~')
                    # v1.09 新增调用发射方法,并将子弹装进列表
                    b = MainGame.tank1.shoot()
                    # v1.11 新增我方子弹数量控制
                    if len(MainGame.mybullet_list) < 3:
                        MainGame.mybullet_list.append(b)
                    print('子弹的数量%d'%len(MainGame.mybullet_list))
            #v1.06新增按键松开的事件处理
            elif e.type == pygame.KEYUP:
                if e.key == pygame.K_UP or e.key == pygame.K_DOWN or\
                    e.key == pygame.K_LEFT or e.key == pygame.K_RIGHT:
                    # 将坦克的移动状态改为停止
                    MainGame.tank1.stop = True
    # 创建我方坦克
    def createMytank(self):
        # 创建我方坦克并赋予其位置属性坐标
        MainGame.tank1 = MyTank(SCREEN_WIDTH/2,SCREEN_HEIGHT/3*2)
    #展示我方坦克
    def showMytank(self):
        MainGame.tank1.displayTank()
        # v1.08 新增将 我方坦克移动代码 移动位置
        if not MainGame.tank1.stop:
            # 我方坦克移动
            MainGame.tank1.move()
    # v1.07创建敌方坦克
    def createEnemytank(self):
        # 循环创建敌方坦克
        for i in range(ENEMY_TANK_COUNT):
            num = random.randint(1,7)
            # v1.08新增 随机速度
            randomspeed = random.randint(3,10)
            # 创建第一个敌方坦克,出现位置为y=150,x随机出现在(100-700),坦克移动的随机速度是randomspeed
            # v1.08新增调用修改后的init方法
            etank = EnemyTank(100*num,150,randomspeed)
            # 创建敌方坦克列表,存入所有的敌方坦克
            MainGame.enemy_tanklist.append(etank)
    # v1.07展示敌方坦克
    def showEnemyTank(self):
        # 遍历展示敌方坦克
        for etank in MainGame.enemy_tanklist:
            #v1.12 新增 根据敌方坦克状态,进行相关业务处理
            if etank.live:
               etank.displayTank()
               # v1.08 新增敌方坦克的移动
               etank.move()
               # v1.11 新增敌方坦克射击,并把敌方子弹加入列表
               b = etank.shoot()
               # if b != None:或 if b:  即在敌方坦克重写射击方法中,如果随机概率是5%,把敌方子弹添加到敌方子弹列表中
               if b != None:
                   MainGame.enemybullet_list.append(b)
            else:
               MainGame.enemy_tanklist.remove(etank)
    # v1.09 展示我方子弹的方法
    def showMyBullet(self):
        for b in MainGame.mybullet_list:
            # 如果子弹活着,展示并移动子弹
            if b.live:
                b.displayBullet()
                # v1.10 新增调用子弹的移动方法
                b.move()
                #如果子弹死亡,移除子弹,给子弹列表腾空间,保证打到墙上的子弹消失
                #v1.12 新增调用是否打中敌方坦克
                b.hitEnemyTank()
                # v1.14 新增 调用是否打中墙壁的方法
                b.hitWall()
            else:
                MainGame.mybullet_list.remove(b)
    # v1.11 新增展示敌方子弹方法
    def showEnemyBullet(self):
        for b in MainGame.enemybullet_list:
            if b.live:
                b.displayBullet()
                b.move()
                # v1.14 新增 调用是否打中墙壁的方法
                b.hitWall()
            else:
                MainGame.enemybullet_list.remove(b)
    # v1.13 展示爆炸效果
    def showExplode(self):
        for e in MainGame.explode_list:
            if e.live:
                e.displayExplode()
            else:
                MainGame.explode_list.remove(e)
    # v1.14 创建墙壁的方法
    def createWalls(self):
        for i in range(1,7):
            w = Wall(130*i,300)
            MainGame.wall_list.append(w)
    # v1.14 展示墙壁的方法
    def showWalls(self):
        for wall in MainGame.wall_list:
            wall.displayWall()

    def gameOver(self):
        exit()
# 基本坦克类
# v1.12 新增基本坦克类调用精灵类
class BaseTank( pygame.sprite.Sprite):
    # 基本坦克属性 位置 方向 速度 图片
    def __init__(self):
        # v1.12 调用精灵类的初始化
        pygame.sprite.Sprite.__init__(self)
        self.direction = None
        self.rect = None
        self.images = None
        self.image = None
        self.speed = 0
        #v1.06新增属性,用来控制坦克是否移动
        self.stop = True
        # v1.12 新增基本属性,判断坦克是否还活着
        self.live = True
    # v1.08 优化移动
    def move(self):
        # 移动,基于在指定的方向移动
        if self.direction == 'U':
            if self.rect.centery > self.rect.height/2:
                self.rect.centery -= self.speed
        elif self.direction == 'D':
            if self.rect.centery < SCREEN_HEIGHT - self.rect.height/2:
                self.rect.centery += self.speed
        elif self.direction == 'L':
            if self.rect.centerx > self.rect.height/2:
                self.rect.centerx -= self.speed
        elif self.direction == 'R':
            if self.rect.centerx < SCREEN_WIDTH - self.rect.height/2:
                self.rect.centerx += self.speed
     # v1.09 新增射击方法
    def shoot(self):
        bullet = Bullet(self)
        return bullet
# 我方坦克类
class MyTank(BaseTank):
    def __init__(self,x,y):
        #引用父类属性
        super(MyTank, self).__init__()
        # 设置具体的图片集
        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 返回的是一个surface)
        self.image = self.images[self.direction]
        # 先基于图像获取坦克的位置和大小
        self.rect = self.image.get_rect()
        # 修改坦克坐标,改成自定义位置
        self.rect.centerx = x
        self.rect.centery = y
        # 设置坦克速度
        self.speed = 5
    #将我方坦克加入到窗口中
    def displayTank(self):
        self.image = self.images[self.direction]
        # 把坦克的图像(即表面)和位置放到另一个图像或表面窗口
        MainGame.window.blit(self.image,self.rect)

# 敌方坦克类
class EnemyTank(BaseTank):
    # v1.08新增随机速度参数
    def __init__(self,x,y,randSpeed):
        # v1.08新增调用父类的初始化
        super(EnemyTank, self).__init__()
        # 设置具体的图片集
        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')
                       }
        # v1.07敌方坦克的初始方向为随机方向
        self.direction = self.randomDirection()
        # 设置坦克的图片(self.image 返回的是一个surface)
        self.image = self.images[self.direction]
        # 先基于图像获取坦克的位置和大小
        self.rect = self.image.get_rect()
        # 修改坦克坐标,改成自定义位置
        self.rect.centerx = x
        self.rect.centery = y
        # v1.08新增速度为参数传进来的速度
        self.speed = randSpeed
        # v1.08新增记录敌方坦克移动的步数
        self.step = 25
        # v1.07生成敌方坦克的随机方向
    def randomDirection(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'
    # v1.08新增重写父类中的移动move方法,方法中新增随机方向的处理
    def move(self):
        if self.step == 0:
            # 变换方向
            self.direction = self.randomDirection()
            # 将步数重新归置成25
            self.step = 25
        else:
            super(EnemyTank, self).move()
            self.step -= 1
    # v1.11 新增重写父类的射击方法
    def shoot(self):
        num = random.randint(1,100)
        if num <= 5:
            return super(EnemyTank, self).shoot()
    # 将敌方坦克加入到窗口中
    def displayTank(self):
        self.image = self.images[self.direction]
        # 把坦克的图像(即表面)和位置放到另一个图像或表面窗口
        MainGame.window.blit(self.image, self.rect)


#v1.09 新增实现子弹类
# v1.12 新增子弹类继承于精灵类
class Bullet(pygame.sprite.Sprite):
    def __init__(self,tank):
        # v1.12 新增调用精灵类的初始化
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load('img/enemymissile.gif')
        # 让子弹的方向和坦克的方向保持一致
        self.direction = tank.direction
        # 基于图像获取子弹的位置和区域大小  子弹的区域默认为左上角
        self.rect = self.image.get_rect()
        # 修改子弹的初始化位置(即子弹的方向和坦克的方向保持一致的情况下,确定子弹的中心点坐标,并且坐标也随坦克变动)
        if self.direction == 'U':
            self.rect.centerx = tank.rect.centerx
            self.rect.centery = tank.rect.centery - tank.rect.height/2 - self.rect.height/2
        elif self.direction == 'D':
            self.rect.centerx = tank.rect.centerx
            self.rect.centery = tank.rect.centery + tank.rect.height / 2 + self.rect.height / 2
        elif self.direction == 'L':
            self.rect.centerx = tank.rect.centerx - tank.rect.height/2 - self.rect.height/2
            self.rect.centery = tank.rect.centery
        elif self.direction == 'R':
            self.rect.centerx = tank.rect.centerx + tank.rect.height / 2 + self.rect.height / 2
            self.rect.centery = tank.rect.centery
        #v1.10 新增子弹移动速度
        self.speed = 11
        # v1.10 新增子弹的存活状态,用来记录子弹是否活着
        self.live = True
    # v1.12 新增 子弹是否碰撞到敌方坦克 方法
    def hitEnemyTank(self):
        for etank in MainGame.enemy_tanklist:
            # 调用pygame.sprite.collide_rect(left,right),判断子弹与敌方坦克的碰撞
            if pygame.sprite.collide_rect(self,etank):
                # v1.13 产生爆炸效果,并把爆炸效果装进爆炸效果列表
                explode = Explode(etank.rect)
                MainGame.explode_list.append(explode)
                # 修改子弹的状态
                self.live = False
                # 修改敌方坦克的状态
                etank.live = False
    # v1.14 新增 子弹碰撞墙壁的方法
    def hitWall(self):
        for wall in MainGame.wall_list:
            if pygame.sprite.collide_rect(self,wall):
                self.live = False
    # v1.10 新增子弹的移动方法
    def move(self):
        if self.direction == 'U':
            if self.rect.centery > self.rect.height/2:
                self.rect.centery -= self.speed
            else:
                self.live = False
        elif self.direction == 'D':
            if self.rect.centery < SCREEN_HEIGHT - self.rect.height/2:
                self.rect.centery += self.speed
            else:
                self.live = False
        elif self.direction == 'L':
            if self.rect.centerx > self.rect.height / 2:
                self.rect.centerx -= self.speed
            else:
                self.live = False
        elif self.direction == 'R':
            if self.rect.centerx < SCREEN_WIDTH - self.rect.height / 2:
                self.rect.centerx += self.speed
            else:
                self.live = False

    #将子弹的图像展示到游戏主窗口
    def displayBullet(self):
        MainGame.window.blit(self.image,self.rect)
#v1.13 新增 完善爆炸类
class Explode():
    def __init__(self,rect):
        # 指定一个区域进行爆炸效果的释放
        self.rect = 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')
                       ]
        # 记录图片的索引值
        self.step = 0
        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

#v1.14 完善墙壁类
class Wall(pygame.sprite.Sprite):
    def __init__(self,x,y):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load('img/steels.gif')
        self.rect = self.image.get_rect()
        self.rect.centerx = x
        self.rect.centery = y
    def displayWall(self):
        MainGame.window.blit(self.image,self.rect)
# 音效类
class Audio():
    pass
#创建一个主逻辑类的对象
game = MainGame()
# 开始游戏
game.startGame()

你可能感兴趣的:(Python 坦克大战小游戏进阶 版本号v1.14)