From e6eed22b17c53085ebbc58dfa6471489776c3969 Mon Sep 17 00:00:00 2001 From: ppsn2fcoq <2140496638@qq.com> Date: Fri, 25 Apr 2025 20:56:39 +0800 Subject: [PATCH] ADD file via upload --- tank_.py | 318 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 tank_.py diff --git a/tank_.py b/tank_.py new file mode 100644 index 0000000..e987caf --- /dev/null +++ b/tank_.py @@ -0,0 +1,318 @@ +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() + 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) + + 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('坦克大战1.05') # 设置窗口标题 + 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() + if not MainGame.myTank.stop: + MainGame.myTank.move() + MainGame.myTank.tank_hit_wall() # 检测与墙壁碰撞 + MainGame.myTank.myTank_hit_enemyTank() # 检测与敌方坦克碰撞 + else: + del MainGame.myTank + MainGame.myTank = None + + 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() + font = pygame.font.SysFont('kaiti', 18) + return font.render(text, True, TEXT_COLOR) + + 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: + if event.key == pygame.K_ESCAPE: + self.createMyTank() + if MainGame.myTank and MainGame.myTank.live: + if event.key == pygame.K_LEFT: + MainGame.myTank.direction = 'L' + MainGame.myTank.stop = False + elif event.key == pygame.K_RIGHT: + MainGame.myTank.direction = 'R' + MainGame.myTank.stop = False + elif event.key == pygame.K_UP: + MainGame.myTank.direction = 'U' + MainGame.myTank.stop = False + elif event.key == pygame.K_DOWN: + MainGame.myTank.direction = 'D' + MainGame.myTank.stop = False + elif event.key == pygame.K_SPACE and len(MainGame.myBulletList) < 3: + MainGame.myBulletList.append(Bullet(MainGame.myTank)) + if event.type == pygame.KEYUP: + if event.key in (pygame.K_LEFT, pygame.K_UP, pygame.K_RIGHT, 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[self.direction] + self.rect = self.image.get_rect() + self.rect.left, self.rect.top = left, top + self.speed = 5 + self.stop = True + self.live = True + self.oldleft, self.oldtop = left, top + + def displayTank(self): # 显示坦克 + MainGame.window.blit(self.images[self.direction], self.rect) + + def move(self): # 移动坦克 + self.oldleft, self.oldtop = self.rect.left, self.rect.top + if self.direction == 'L' and self.rect.left > 0: + self.rect.left -= self.speed + elif self.direction == 'R' and self.rect.left + self.rect.height < SCREEN_WIDTH: + self.rect.left += self.speed + elif self.direction == 'U' and self.rect.top > 0: + self.rect.top -= self.speed + elif self.direction == 'D' and self.rect.top + self.rect.height < SCREEN_HEIGHT: + self.rect.top += self.speed + + def shot(self): # 发射子弹 + return Bullet(self) + + def stay(self): # 保持原位 + self.rect.left, self.rect.top = self.oldleft, self.oldtop + + def tank_hit_wall(self): # 坦克碰撞墙壁检测 + for wall in MainGame.wallList: + if pygame.sprite.collide_rect(self, wall): + self.stay() + +class MyTank(Tank): + def __init__(self, left, top) -> None: + super().__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().__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() + self.rect.left, self.rect.top = left, top + self.speed, self.step = speed, 60 + + def randDirection(self): # 随机生成方向 + return ['U', 'D', 'L', 'R'][random.randint(0, 3)] + + def randMove(self): # 随机移动 + if self.step <= 0: + self.direction, self.step = self.randDirection(), 60 + else: + self.move() + self.step -= 1 + + def shot(self): # 敌方射击 + return Bullet(self) if random.randint(0, 100) < 10 else None + + 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() + 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.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, self.live = 6, True + + def displayBullet(self): # 显示子弹 + MainGame.window.blit(self.image, self.rect) + + def move(self): # 子弹移动 + if self.direction == 'U' and self.rect.top > 0: + self.rect.top -= self.speed + elif self.direction == 'D' and self.rect.top + self.rect.height < SCREEN_HEIGHT: + self.rect.top += self.speed + elif self.direction == 'L' and self.rect.left > 0: + self.rect.left -= self.speed + elif self.direction == 'R' and 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, self.live = False, False + MainGame.explodeList.append(Explode(enemyTank)) + + def enemyBullet_hit_myTank(self): # 敌方子弹命中检测 + if MainGame.myTank and MainGame.myTank.live and pygame.sprite.collide_rect(self, MainGame.myTank): + self.live, MainGame.myTank.live = False, False + MainGame.explodeList.append(Explode(MainGame.myTank)) + + def bullet_hit_wall(self): # 子弹碰撞墙壁检测 + for wall in MainGame.wallList: + if pygame.sprite.collide_rect(self, wall): + self.live, wall.hp = False, wall.hp-1 + 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() + self.rect.left, self.rect.top = left, top + self.live, self.hp = True, 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(f'./img/blast{i}.gif') for i in range(5)] + self.step, self.live = 0, True + + def displayExplode(self): # 显示爆炸动画 + if self.step < len(self.images): + MainGame.window.blit(self.images[self.step], self.rect) + self.step += 1 + else: + self.live = False + +if __name__ == '__main__': + MainGame().startGame() \ No newline at end of file