diff --git a/tank.py b/tank.py new file mode 100644 index 0000000..ce522c9 --- /dev/null +++ b/tank.py @@ -0,0 +1,588 @@ +import pygame,time,random +from pygame.sprite import Sprite +#定义常量 +SCREEN_WIDTH = 750 +SCREEN_HEIGHT= 500 +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) -> None: + pass + #创建敌方坦克 + def createEnemyTank(self): + top = 100 + for i in range(MainGame.enemyCount): + left = random.randint(0,600) + speed = random.randint(1,4) + 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() + #调用检测敌方坦克是否与我方坦克发生碰撞 + if MainGame.myTank and MainGame.myTank.live: + enemyTank.enemyTank_hit_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.bullet_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.bullet_hit_wall() + else: + #从子弹列表删除 + MainGame.enemyBulletList.remove(enemyBullet) + + #循环遍历爆炸效果列表展示爆炸效果 + def displayExplodeList(self): + for explode in MainGame.explodeList: + #判断是否存活 + if explode.live: + #展示 + explode.displayExplode() + else: + #从爆炸效果列表中移除 + MainGame.explodeList.remove(explode) + + #创建我方坦克 + def createMyTank(self): + MainGame.myTank = MyTank(350,300) + #添加音效 + music = Music('./img/start.wav') + #播放 + music.playMusic() + + #创建墙壁 + def createWall(self): + top = 220 + for i in range(6): + #初始化墙壁 + wall = Wall(i*130,top) + #添加到墙壁列表 + MainGame.wallList.append(wall) + + #加载墙壁 + def displayWallList(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.02) + #给窗口设置填充色 + MainGame.window.fill(BG_COLOR) + #添加文字信息提示 + textSurface = self.getTextSurface('敌方坦克剩余数量%d'%len(MainGame.enemyList)) + #主窗口显示文字信息 + MainGame.window.blit(textSurface,(10,10)) + #添加事件监听 + self.getEvent() + + #调用坦克的显示方法 + 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() + #调用检测我方坦克是否与敌方坦克发生碰撞 + MainGame.myTank.myTank_hit_enemyTank() + + + #加载敌方坦克 + self.displayEnemyTank() + + #加载我方坦克发射的子弹 + self.displayMyBullet() + + #加载敌方坦克发射的子弹 + self.displayEnemyBullet() + + #加载爆炸效果 + self.displayExplodeList() + + #加载墙壁 + self.displayWallList() + pygame.display.update() + + + #结束游戏 + def endGame(self): + print('谢谢使用,欢迎再次使用') + exit() + + #添加文字信息提示 + def getTextSurface(self,text): + #初始化字体模块 + pygame.font.init() + #获取所有字体 + # print(pygame.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_LEFT: + print('按下左键,坦克向左移动') + #修改我方坦克的方向 + MainGame.myTank.direction='L' + #修改坦克移动开关 + MainGame.myTank.stop=False + + elif event.key == pygame.K_RIGHT: + print('按下右键,坦克向右移动') + #修改我方坦克的方向 + MainGame.myTank.direction='R' + #修改坦克移动开关 + MainGame.myTank.stop=False + + elif event.key == pygame.K_UP: + print('按下上键,坦克向上移动') + #修改我方坦克的方向 + MainGame.myTank.direction='U' + #修改坦克移动开关 + MainGame.myTank.stop=False + + elif event.key == pygame.K_DOWN: + print('按下下键,坦克向下移动') + #修改我方坦克的方向 + MainGame.myTank.direction='D' + #修改坦克移动开关 + MainGame.myTank.stop=False + + elif event.key == pygame.K_SPACE: + print('发射子弹') + #子弹列表的数量如果小于3,可以初始化子弹 + if len(MainGame.myBulletList)<3: + #初始化子弹 + myBullet = Bullet(MainGame.myTank) + MainGame.myBulletList.append(myBullet) + #添加音效 + music = Music('./img/fire.wav') + music.playMusic() + + + + #判断键盘键是否松开 + if event.type == pygame.KEYUP: + if event.key == pygame.K_LEFT or event.key == pygame.K_UP or event.key == pygame.K_RIGHT or event.key == pygame.K_DOWN: + if MainGame.myTank and MainGame.myTank.live: + MainGame.myTank.stop = True + + +class Tank(BaseItem): + def __init__(self,left,top) -> None: + #保存加载的图片 + 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 = 'D' + #根据坦克方向,获取加载的图片 + 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 = 5 + + #坦克移动开关 + self.stop = True + + #生存状态 + self.live = True + + #移动之前的位置 + self.oldleft = self.rect.left + self.oldtop = self.rect.top + + #展示坦克的方法 + def displayTank(self): + self.image = self.images.get(self.direction) + #调用blit方法展示坦克 + MainGame.window.blit(self.image,self.rect) + + #移动坦克 + def move(self): + #记录移动之前的位置 + self.oldleft = self.rect.left + self.oldtop = self.rect.top + #判断坦克的方向 + if self.direction == 'L': + if self.rect.left>0: + self.rect.left -= self.speed + elif self.direction == 'R': + if self.rect.left+self.rect.height0: + self.rect.top -= self.speed + elif self.direction == 'D': + if self.rect.top+self.rect.height None: + #调用父类的初始方法 + super(MyTank,self).__init__(left,top) + + #检测我方坦克是否与敌方坦克发生碰撞 + def myTank_hit_enemyTank(self): + #循环遍历敌方坦克列表 + for enemyTank in MainGame.enemyList: + if pygame.sprite.collide_rect(self,enemyTank): + self.stay() + +#敌方坦克 +class EnemyTank(Tank): + def __init__(self,left,top,speed) -> None: + #调用父类的初始化方法 + super(EnemyTank,self).__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.get(self.direction) + #获取矩形区域 + self.rect = self.image.get_rect() + #设置left top + self.rect.left = left + self.rect.top = top + self.speed = speed + + #步数 + self.step = 60 + + #随机生成方向 + 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 = 60 + else: + self.move() + #步数递减 + self.step-=1 + + def shot(self): + #随机生成100以内的数 + num = random.randint(0,100) + if num<10: + return Bullet(self) + + #检测敌方坦克是否与我方坦克发生碰撞 + def enemyTank_hit_myTank(self): + if pygame.sprite.collide_rect(self,MainGame.myTank): + self.stay() + + +#子弹类 +class Bullet(BaseItem): + def __init__(self,tank) -> None: + #加载图片 + 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 / 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 + 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 == 'U': + if self.rect.top>0: + self.rect.top -= self.speed + else: #碰到墙壁 + self.live = False + elif self.direction == 'D': + if self.rect.top + self.rect.height < SCREEN_HEIGHT: + self.rect.top += self.speed + else: + self.live = False + elif self.direction == 'L': + if self.rect.left>0: + self.rect.left -= self.speed + else: + self.live = False + elif self.direction == 'R': + 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 bullet_hit_wall(self): + #循环遍历墙壁列表 + for wall in MainGame.wallList: + if pygame.sprite.collide_rect(self,wall): + #设置子弹生存状态修改 + self.live = False + #让墙壁的生命值减减 + wall.hp -=1 + #判断墙壁生命值是否小于等于0 + if wall.hp<=0: + #设置墙壁的生存状态 + wall.live = False + +#墙壁类 +class Wall(): + def __init__(self,left,top) -> None: + #加载墙壁图片 + self.image = pygame.image.load('./img/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) -> None: + #爆炸的位置是当前子弹击中坦克的位置 + 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'), + ] + self.step = 0 + self.image = self.images[self.step] + #生存状态 + self.live = True + + + #展示爆炸效果 + def displayExplode(self): + if self.step None: + self.filename = filename + #初始化混合器 + pygame.mixer.init() + #加载音乐 + pygame.mixer.music.load(self.filename) + + #播放音乐 + def playMusic(self): + pygame.mixer.music.play() + +#主方法 +if __name__ == '__main__': + #调用主类中startGame() + MainGame().startGame()