如何利用Python写个坦克大战


Posted in Python onNovember 18, 2020

前言

坦克大战是一款策略类的平面射击游戏,于 1985 年由 Namco 游戏公司发布,尽管时至今日已经有了很多衍生类的游戏,但这款游戏仍然受到了相当一部分人的欢迎,本文我们看一下如何使用 Python 来实现这款游戏,游戏实现主要用到的 Python 库为 pygame。

简介

坦克大战的组成主要包括:场景、坦克、子弹、食物、大本营,其本质就是一个塔防类的游戏,游戏目标为:守住大本营并且消灭敌方坦克,通常支持单双人模式,下面我们来看一下具体实现。

实现

首先,我们来实现游戏场景,场景的组成主要包括:石头墙、钢墙、冰、河流、树、地图,我们暂时做两个关卡,代码实现如下:

# 石头墙
class Brick(pygame.sprite.Sprite):
 def __init__(self):
 pygame.sprite.Sprite.__init__(self)
 self.brick = pygame.image.load('images/scene/brick.png')
 self.rect = self.brick.get_rect()
 self.being = False

# 钢墙
class Iron(pygame.sprite.Sprite):
 def __init__(self):
 pygame.sprite.Sprite.__init__(self)
 self.iron = pygame.image.load('images/scene/iron.png')
 self.rect = self.iron.get_rect()
 self.being = False

# 冰
class Ice(pygame.sprite.Sprite):
 def __init__(self):
 pygame.sprite.Sprite.__init__(self)
 self.ice = pygame.image.load('images/scene/ice.png')
 self.rect = self.ice.get_rect()
 self.being = False

# 河流
class River(pygame.sprite.Sprite):
 def __init__(self, kind=None):
 pygame.sprite.Sprite.__init__(self)
 if kind is None:
 self.kind = random.randint(0, 1)
 self.rivers = ['images/scene/river1.png', 'images/scene/river2.png']
 self.river = pygame.image.load(self.rivers[self.kind])
 self.rect = self.river.get_rect()
 self.being = False

# 树
class Tree(pygame.sprite.Sprite):
 def __init__(self):
 pygame.sprite.Sprite.__init__(self)
 self.tree = pygame.image.load('images/scene/tree.png')
 self.rect = self.tree.get_rect()
 self.being = False

# 地图
class Map():
 def __init__(self, stage):
 self.brickGroup = pygame.sprite.Group()
 self.ironGroup = pygame.sprite.Group()
 self.iceGroup = pygame.sprite.Group()
 self.riverGroup = pygame.sprite.Group()
 self.treeGroup = pygame.sprite.Group()
 if stage == 1:
 self.stage1()
 elif stage == 2:
 self.stage2()
 # 关卡一
 def stage1(self):
 for x in [2, 3, 6, 7, 18, 19, 22, 23]:
 for y in [2, 3, 4, 5, 6, 7, 8, 9, 10, 17, 18, 19, 20, 21, 22, 23]:
 self.brick = Brick()
 self.brick.rect.left, self.brick.rect.top = 3 + x * 24, 3 + y * 24
 self.brick.being = True
 self.brickGroup.add(self.brick)
 for x in [10, 11, 14, 15]:
 for y in [2, 3, 4, 5, 6, 7, 8, 11, 12, 15, 16, 17, 18, 19, 20]:
 self.brick = Brick()
 self.brick.rect.left, self.brick.rect.top = 3 + x * 24, 3 + y * 24
 self.brick.being = True
 self.brickGroup.add(self.brick)
 for x in [4, 5, 6, 7, 18, 19, 20, 21]:
 for y in [13, 14]:
 self.brick = Brick()
 self.brick.rect.left, self.brick.rect.top = 3 + x * 24, 3 + y * 24
 self.brick.being = True
 self.brickGroup.add(self.brick)
 for x in [12, 13]:
 for y in [16, 17]:
 self.brick = Brick()
 self.brick.rect.left, self.brick.rect.top = 3 + x * 24, 3 + y * 24
 self.brick.being = True
 self.brickGroup.add(self.brick)
 for x, y in [(11, 23), (12, 23), (13, 23), (14, 23), (11, 24), (14, 24), (11, 25), (14, 25)]:
 self.brick = Brick()
 self.brick.rect.left, self.brick.rect.top = 3 + x * 24, 3 + y * 24
 self.brick.being = True
 self.brickGroup.add(self.brick)
 for x, y in [(0, 14), (1, 14), (12, 6), (13, 6), (12, 7), (13, 7), (24, 14), (25, 14)]:
 self.iron = Iron()
 self.iron.rect.left, self.iron.rect.top = 3 + x * 24, 3 + y * 24
 self.iron.being = True
 self.ironGroup.add(self.iron)
 # 关卡二
 def stage2(self):
 for x in [2, 3, 6, 7, 18, 19, 22, 23]:
 for y in [2, 3, 4, 5, 6, 7, 8, 9, 10, 17, 18, 19, 20, 21, 22, 23]:
 self.brick = Brick()
 self.brick.rect.left, self.brick.rect.top = 3 + x * 24, 3 + y * 24
 self.brick.being = True
 self.brickGroup.add(self.brick)
 for x in [10, 11, 14, 15]:
 for y in [2, 3, 4, 5, 6, 7, 8, 11, 12, 15, 16, 17, 18, 19, 20]:
 self.brick = Brick()
 self.brick.rect.left, self.brick.rect.top = 3 + x * 24, 3 + y * 24
 self.brick.being = True
 self.brickGroup.add(self.brick)
 for x in [4, 5, 6, 7, 18, 19, 20, 21]:
 for y in [13, 14]:
 self.brick = Brick()
 self.brick.rect.left, self.brick.rect.top = 3 + x * 24, 3 + y * 24
 self.brick.being = True
 self.brickGroup.add(self.brick)
 for x in [12, 13]:
 for y in [16, 17]:
 self.brick = Brick()
 self.brick.rect.left, self.brick.rect.top = 3 + x * 24, 3 + y * 24
 self.brick.being = True
 self.brickGroup.add(self.brick)
 for x, y in [(11, 23), (12, 23), (13, 23), (14, 23), (11, 24), (14, 24), (11, 25), (14, 25)]:
 self.brick = Brick()
 self.brick.rect.left, self.brick.rect.top = 3 + x * 24, 3 + y * 24
 self.brick.being = True
 self.brickGroup.add(self.brick)
 for x, y in [(0, 14), (1, 14), (12, 6), (13, 6), (12, 7), (13, 7), (24, 14), (25, 14)]:
 self.iron = Iron()
 self.iron.rect.left, self.iron.rect.top = 3 + x * 24, 3 + y * 24
 self.iron.being = True
 self.ironGroup.add(self.iron)
 def protect_home(self):
 for x, y in [(11, 23), (12, 23), (13, 23), (14, 23), (11, 24), (14, 24), (11, 25), (14, 25)]:
 self.iron = Iron()
 self.iron.rect.left, self.iron.rect.top = 3 + x * 24, 3 + y * 24
 self.iron.being = True
 self.ironGroup.add(self.iron)

我们接着看大本营的实现,大本营的实现相对比较简单,其本质就是一个标识物,代码实现如下:

class Home(pygame.sprite.Sprite):
 def __init__(self):
 pygame.sprite.Sprite.__init__(self)
 self.homes = ['images/home/home1.png', 'images/home/home2.png', 'images/home/home_destroyed.png']
 self.home = pygame.image.load(self.homes[0])
 self.rect = self.home.get_rect()
 self.rect.left, self.rect.top = (3 + 12 * 24, 3 + 24 * 24)
 self.alive = True
 # 大本营置为摧毁状态
 def set_dead(self):
 self.home = pygame.image.load(self.homes[-1])
 self.alive = False

再接着看食物的实现,食物主要用来提升坦克能力,如:坦克升级、增加生命等,代码实现如下:

# 食物类
class Food(pygame.sprite.Sprite):
 def __init__(self):
 pygame.sprite.Sprite.__init__(self)
 # 消灭当前所有敌人
 self.food_boom = 'images/food/food_boom.png'
 # 当前所有敌人静止一段时间
 self.food_clock = 'images/food/food_clock.png'
 # 使得坦克子弹可碎钢板
 self.food_gun = 'images/food/food_gun.png'
 # 使得大本营的墙变为钢板
 self.food_iron = 'images/food/food_gun.png'
 # 坦克获得一段时间的保护罩
 self.food_protect = 'images/food/food_protect.png'
 # 坦克升级
 self.food_star = 'images/food/food_star.png'
 # 坦克生命 + 1
 self.food_tank = 'images/food/food_tank.png'
 # 所有食物
 self.foods = [self.food_boom, self.food_clock, self.food_gun, self.food_iron, self.food_protect, self.food_star, self.food_tank]
 self.kind = None
 self.food = None
 self.rect = None
 # 是否存在
 self.being = False
 # 存在时间
 self.time = 1000
 # 生成食物
 def generate(self):
 self.kind = random.randint(0, 6)
 self.food = pygame.image.load(self.foods[self.kind]).convert_alpha()
 self.rect = self.food.get_rect()
 self.rect.left, self.rect.top = random.randint(100, 500), random.randint(100, 500)
 self.being = True

再接着看坦克的实现,坦克包括我方坦克和敌方坦克,我方坦克由玩家自己控制移动、射击等操作,敌方坦克实现自动移动、射击等操作,代码实现如下:

# 我方坦克类
class myTank(pygame.sprite.Sprite):
 def __init__(self, player):
 pygame.sprite.Sprite.__init__(self)
 # 玩家编号(1/2)
 self.player = player
 # 不同玩家用不同的坦克(不同等级对应不同的图)
 if player == 1:
 self.tanks = ['images/myTank/tank_T1_0.png', 'images/myTank/tank_T1_1.png', 'images/myTank/tank_T1_2.png']
 elif player == 2:
 self.tanks = ['images/myTank/tank_T2_0.png', 'images/myTank/tank_T2_1.png', 'images/myTank/tank_T2_2.png']
 else:
 raise ValueError('myTank class -> player value error.')
 # 坦克等级(初始0)
 self.level = 0
 # 载入(两个tank是为了轮子特效)
 self.tank = pygame.image.load(self.tanks[self.level]).convert_alpha()
 self.tank_0 = self.tank.subsurface((0, 0), (48, 48))
 self.tank_1 = self.tank.subsurface((48, 0), (48, 48))
 self.rect = self.tank_0.get_rect()
 # 保护罩
 self.protected_mask = pygame.image.load('images/others/protect.png').convert_alpha()
 self.protected_mask1 = self.protected_mask.subsurface((0, 0), (48, 48))
 self.protected_mask2 = self.protected_mask.subsurface((48, 0), (48, 48))
 # 坦克方向
 self.direction_x, self.direction_y = 0, -1
 # 不同玩家的出生位置不同
 if player == 1:
 self.rect.left, self.rect.top = 3 + 24 * 8, 3 + 24 * 24
 elif player == 2:
 self.rect.left, self.rect.top = 3 + 24 * 16, 3 + 24 * 24
 else:
 raise ValueError('myTank class -> player value error.')
 # 坦克速度
 self.speed = 3
 # 是否存活
 self.being = True
 # 有几条命
 self.life = 3
 # 是否处于保护状态
 self.protected = False
 # 子弹
 self.bullet = Bullet()
 # 射击
 def shoot(self):
 self.bullet.being = True
 self.bullet.turn(self.direction_x, self.direction_y)
 if self.direction_x == 0 and self.direction_y == -1:
 self.bullet.rect.left = self.rect.left + 20
 self.bullet.rect.bottom = self.rect.top - 1
 elif self.direction_x == 0 and self.direction_y == 1:
 self.bullet.rect.left = self.rect.left + 20
 self.bullet.rect.top = self.rect.bottom + 1
 elif self.direction_x == -1 and self.direction_y == 0:
 self.bullet.rect.right = self.rect.left - 1
 self.bullet.rect.top = self.rect.top + 20
 elif self.direction_x == 1 and self.direction_y == 0:
 self.bullet.rect.left = self.rect.right + 1
 self.bullet.rect.top = self.rect.top + 20
 else:
 raise ValueError('myTank class -> direction value error.')
 if self.level == 0:
 self.bullet.speed = 8
 self.bullet.stronger = False
 elif self.level == 1:
 self.bullet.speed = 12
 self.bullet.stronger = False
 elif self.level == 2:
 self.bullet.speed = 12
 self.bullet.stronger = True
 elif self.level == 3:
 self.bullet.speed = 16
 self.bullet.stronger = True
 else:
 raise ValueError('myTank class -> level value error.')
 # 等级提升
 def up_level(self):
 if self.level < 3:
 self.level += 1
 try:
 self.tank = pygame.image.load(self.tanks[self.level]).convert_alpha()
 except:
 self.tank = pygame.image.load(self.tanks[-1]).convert_alpha()
 # 等级降低
 def down_level(self):
 if self.level > 0:
 self.level -= 1
 self.tank = pygame.image.load(self.tanks[self.level]).convert_alpha()
 # 向上
 def move_up(self, tankGroup, brickGroup, ironGroup, myhome):
 self.direction_x, self.direction_y = 0, -1
 # 先移动后判断
 self.rect = self.rect.move(self.speed*self.direction_x, self.speed*self.direction_y)
 self.tank_0 = self.tank.subsurface((0, 0), (48, 48))
 self.tank_1 = self.tank.subsurface((48, 0), (48, 48))
 # 是否可以移动
 is_move = True
 # 地图顶端
 if self.rect.top < 3:
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False
 # 撞石头/钢墙
 if pygame.sprite.spritecollide(self, brickGroup, False, None) or \
 pygame.sprite.spritecollide(self, ironGroup, False, None):
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False
 # 撞其他坦克
 if pygame.sprite.spritecollide(self, tankGroup, False, None):
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False
 # 大本营
 if pygame.sprite.collide_rect(self, myhome):
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False
 return is_move
 # 向下
 def move_down(self, tankGroup, brickGroup, ironGroup, myhome):
 self.direction_x, self.direction_y = 0, 1
 # 先移动后判断
 self.rect = self.rect.move(self.speed*self.direction_x, self.speed*self.direction_y)
 self.tank_0 = self.tank.subsurface((0, 48), (48, 48))
 self.tank_1 = self.tank.subsurface((48, 48), (48, 48))
 # 是否可以移动
 is_move = True
 # 地图底端
 if self.rect.bottom > 630 - 3:
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False
 # 撞石头/钢墙
 if pygame.sprite.spritecollide(self, brickGroup, False, None) or \
 pygame.sprite.spritecollide(self, ironGroup, False, None):
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False
 # 撞其他坦克
 if pygame.sprite.spritecollide(self, tankGroup, False, None):
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False
 # 大本营
 if pygame.sprite.collide_rect(self, myhome):
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False
 return is_move
 # 向左
 def move_left(self, tankGroup, brickGroup, ironGroup, myhome):
 self.direction_x, self.direction_y = -1, 0
 # 先移动后判断
 self.rect = self.rect.move(self.speed*self.direction_x, self.speed*self.direction_y)
 self.tank_0 = self.tank.subsurface((0, 96), (48, 48))
 self.tank_1 = self.tank.subsurface((48, 96), (48, 48))
 # 是否可以移动
 is_move = True
 # 地图左端
 if self.rect.left < 3:
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False
 # 撞石头/钢墙
 if pygame.sprite.spritecollide(self, brickGroup, False, None) or \
 pygame.sprite.spritecollide(self, ironGroup, False, None):
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False
 # 撞其他坦克
 if pygame.sprite.spritecollide(self, tankGroup, False, None):
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False 
 # 大本营
 if pygame.sprite.collide_rect(self, myhome):
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False
 return is_move
 # 向右
 def move_right(self, tankGroup, brickGroup, ironGroup, myhome):
 self.direction_x, self.direction_y = 1, 0
 # 先移动后判断
 self.rect = self.rect.move(self.speed*self.direction_x, self.speed*self.direction_y)
 self.tank_0 = self.tank.subsurface((0, 144), (48, 48))
 self.tank_1 = self.tank.subsurface((48, 144), (48, 48))
 # 是否可以移动
 is_move = True
 # 地图右端
 if self.rect.right > 630 - 3:
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False
 # 撞石头/钢墙
 if pygame.sprite.spritecollide(self, brickGroup, False, None) or \
 pygame.sprite.spritecollide(self, ironGroup, False, None):
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False
 # 撞其他坦克
 if pygame.sprite.spritecollide(self, tankGroup, False, None):
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False
 # 大本营
 if pygame.sprite.collide_rect(self, myhome):
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 is_move = False
 return is_move
 # 死后重置
 def reset(self):
 self.level = 0
 self.protected = False
 self.tank = pygame.image.load(self.tanks[self.level]).convert_alpha()
 self.tank_0 = self.tank.subsurface((0, 0), (48, 48))
 self.tank_1 = self.tank.subsurface((48, 0), (48, 48))
 self.rect = self.tank_0.get_rect()
 self.direction_x, self.direction_y = 0, -1
 if self.player == 1:
 self.rect.left, self.rect.top = 3 + 24 * 8, 3 + 24 * 24
 elif self.player == 2:
 self.rect.left, self.rect.top = 3 + 24 * 16, 3 + 24 * 24
 else:
 raise ValueError('myTank class -> player value error.')
 self.speed = 3

# 敌方坦克类
class enemyTank(pygame.sprite.Sprite):
 def __init__(self, x=None, kind=None, is_red=None):
 pygame.sprite.Sprite.__init__(self)
 # 用于给刚生成的坦克播放出生特效
 self.born = True
 self.times = 90
 # 坦克的种类编号
 if kind is None:
 self.kind = random.randint(0, 3)
 else:
 self.kind = kind
 # 所有坦克
 self.tanks1 = ['images/enemyTank/enemy_1_0.png', 'images/enemyTank/enemy_1_1.png', 'images/enemyTank/enemy_1_2.png', 'images/enemyTank/enemy_1_3.png']
 self.tanks2 = ['images/enemyTank/enemy_2_0.png', 'images/enemyTank/enemy_2_1.png', 'images/enemyTank/enemy_2_2.png', 'images/enemyTank/enemy_2_3.png']
 self.tanks3 = ['images/enemyTank/enemy_3_0.png', 'images/enemyTank/enemy_3_1.png', 'images/enemyTank/enemy_3_2.png', 'images/enemyTank/enemy_3_3.png']
 self.tanks4 = ['images/enemyTank/enemy_4_0.png', 'images/enemyTank/enemy_4_1.png', 'images/enemyTank/enemy_4_2.png', 'images/enemyTank/enemy_4_3.png']
 self.tanks = [self.tanks1, self.tanks2, self.tanks3, self.tanks4]
 # 是否携带食物(红色的坦克携带食物)
 if is_red is None:
 self.is_red = random.choice((True, False, False, False, False))
 else:
 self.is_red = is_red
 # 同一种类的坦克具有不同的颜色, 红色的坦克比同类坦克多一点血量
 if self.is_red:
 self.color = 3
 else:
 self.color = random.randint(0, 2)
 # 血量
 self.blood = self.color
 # 载入(两个tank是为了轮子特效)
 self.tank = pygame.image.load(self.tanks[self.kind][self.color]).convert_alpha()
 self.tank_0 = self.tank.subsurface((0, 48), (48, 48))
 self.tank_1 = self.tank.subsurface((48, 48), (48, 48))
 self.rect = self.tank_0.get_rect()
 # 坦克位置
 if x is None:
 self.x = random.randint(0, 2)
 else:
 self.x = x
 self.rect.left, self.rect.top = 3 + self.x * 12 * 24, 3
 # 坦克是否可以行动
 self.can_move = True
 # 坦克速度
 self.speed = max(3 - self.kind, 1)
 # 方向
 self.direction_x, self.direction_y = 0, 1
 # 是否存活
 self.being = True
 # 子弹
 self.bullet = Bullet()
 # 射击
 def shoot(self):
 self.bullet.being = True
 self.bullet.turn(self.direction_x, self.direction_y)
 if self.direction_x == 0 and self.direction_y == -1:
 self.bullet.rect.left = self.rect.left + 20
 self.bullet.rect.bottom = self.rect.top - 1
 elif self.direction_x == 0 and self.direction_y == 1:
 self.bullet.rect.left = self.rect.left + 20
 self.bullet.rect.top = self.rect.bottom + 1
 elif self.direction_x == -1 and self.direction_y == 0:
 self.bullet.rect.right = self.rect.left - 1
 self.bullet.rect.top = self.rect.top + 20
 elif self.direction_x == 1 and self.direction_y == 0:
 self.bullet.rect.left = self.rect.right + 1
 self.bullet.rect.top = self.rect.top + 20
 else:
 raise ValueError('enemyTank class -> direction value error.')
 # 随机移动
 def move(self, tankGroup, brickGroup, ironGroup, myhome):
 self.rect = self.rect.move(self.speed*self.direction_x, self.speed*self.direction_y)
 is_move = True
 if self.direction_x == 0 and self.direction_y == -1:
 self.tank_0 = self.tank.subsurface((0, 0), (48, 48))
 self.tank_1 = self.tank.subsurface((48, 0), (48, 48))
 if self.rect.top < 3:
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 self.direction_x, self.direction_y = random.choice(([0, 1], [0, -1], [1, 0], [-1, 0]))
 is_move = False
 elif self.direction_x == 0 and self.direction_y == 1:
 self.tank_0 = self.tank.subsurface((0, 48), (48, 48))
 self.tank_1 = self.tank.subsurface((48, 48), (48, 48))
 if self.rect.bottom > 630 - 3:
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 self.direction_x, self.direction_y = random.choice(([0, 1], [0, -1], [1, 0], [-1, 0]))
 is_move = False
 elif self.direction_x == -1 and self.direction_y == 0:
 self.tank_0 = self.tank.subsurface((0, 96), (48, 48))
 self.tank_1 = self.tank.subsurface((48, 96), (48, 48))
 if self.rect.left < 3:
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 self.direction_x, self.direction_y = random.choice(([0, 1], [0, -1], [1, 0], [-1, 0]))
 is_move = False
 elif self.direction_x == 1 and self.direction_y == 0:
 self.tank_0 = self.tank.subsurface((0, 144), (48, 48))
 self.tank_1 = self.tank.subsurface((48, 144), (48, 48))
 if self.rect.right > 630 - 3:
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 self.direction_x, self.direction_y = random.choice(([0, 1], [0, -1], [1, 0], [-1, 0]))
 is_move = False
 else:
 raise ValueError('enemyTank class -> direction value error.')
 if pygame.sprite.spritecollide(self, brickGroup, False, None) \
 or pygame.sprite.spritecollide(self, ironGroup, False, None) \
 or pygame.sprite.spritecollide(self, tankGroup, False, None):
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 self.direction_x, self.direction_y = random.choice(([0, 1], [0, -1], [1, 0], [-1, 0]))
 is_move = False
 if pygame.sprite.collide_rect(self, myhome):
 self.rect = self.rect.move(self.speed*-self.direction_x, self.speed*-self.direction_y)
 self.direction_x, self.direction_y = random.choice(([0, 1], [0, -1], [1, 0], [-1, 0]))
 is_move = False
 return is_move
 # 重新载入坦克
 def reload(self):
 self.tank = pygame.image.load(self.tanks[self.kind][self.color]).convert_alpha()
 self.tank_0 = self.tank.subsurface((0, 48), (48, 48))
 self.tank_1 = self.tank.subsurface((48, 48), (48, 48))

再接着看子弹的实现,子弹的主要属性包括:方向、速度、是否存活、是否为加强版等,代码实现如下:

# 子弹类
class Bullet(pygame.sprite.Sprite):
 def __init__(self):
 pygame.sprite.Sprite.__init__(self)
 # 子弹四个方向(上下左右)
 self.bullets = ['images/bullet/bullet_up.png', 'images/bullet/bullet_down.png', 'images/bullet/bullet_left.png', 'images/bullet/bullet_right.png']
 # 子弹方向(默认向上)
 self.direction_x, self.direction_y = 0, -1
 self.bullet = pygame.image.load(self.bullets[0])
 self.rect = self.bullet.get_rect()
 # 在坦克类中再赋实际值
 self.rect.left, self.rect.right = 0, 0
 # 速度
 self.speed = 6
 # 是否存活
 self.being = False
 # 是否为加强版子弹(可碎钢板)
 self.stronger = False
 # 改变子弹方向
 def turn(self, direction_x, direction_y):
 self.direction_x, self.direction_y = direction_x, direction_y
 if self.direction_x == 0 and self.direction_y == -1:
 self.bullet = pygame.image.load(self.bullets[0])
 elif self.direction_x == 0 and self.direction_y == 1:
 self.bullet = pygame.image.load(self.bullets[1])
 elif self.direction_x == -1 and self.direction_y == 0:
 self.bullet = pygame.image.load(self.bullets[2])
 elif self.direction_x == 1 and self.direction_y == 0:
 self.bullet = pygame.image.load(self.bullets[3])
 else:
 raise ValueError('Bullet class -> direction value error.')
 # 移动
 def move(self):
 self.rect = self.rect.move(self.speed*self.direction_x, self.speed*self.direction_y)
 # 到地图边缘后消失
 if (self.rect.top < 3) or (self.rect.bottom > 630 - 3) or (self.rect.left < 3) or (self.rect.right > 630 - 3):
 self.being = False

最后,我们看一下程序的主要初始化代码,如下所示:

# 初始化
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((630, 630))
pygame.display.set_caption("TANK")
# 加载图片
bg_img = pygame.image.load("images/others/background.png")
# 加载音效
add_sound = pygame.mixer.Sound("audios/add.wav")
add_sound.set_volume(1)
bang_sound = pygame.mixer.Sound("audios/bang.wav")
bang_sound.set_volume(1)
blast_sound = pygame.mixer.Sound("audios/blast.wav")
blast_sound.set_volume(1)
fire_sound = pygame.mixer.Sound("audios/fire.wav")
fire_sound.set_volume(1)
Gunfire_sound = pygame.mixer.Sound("audios/Gunfire.wav")
Gunfire_sound.set_volume(1)
hit_sound = pygame.mixer.Sound("audios/hit.wav")
hit_sound.set_volume(1)
start_sound = pygame.mixer.Sound("audios/start.wav")
start_sound.set_volume(1)
# 开始界面
num_player = show_start_interface(screen, 630, 630)
# 播放游戏开始的音乐
start_sound.play()
# 关卡
stage = 0
num_stage = 2
# 游戏是否结束
is_gameover = False
# 时钟
clock = pygame.time.Clock()

实现效果

看一下实现效果:

如何利用Python写个坦克大战

再说一下玩家一、二的操作键,玩家一、二移动键分别为:WASD、←→↑↓,玩家一、二射击键分别为:J、0。

总结

本文我们使用 Python 实现了坦克大战的基本功能,还有待完善,有兴趣的话,可以对游戏做进一步的完善和扩展。

到此这篇关于如何利用Python写个坦克大战的文章就介绍到这了,更多相关Python写坦克大战内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
一个简单的python程序实例(通讯录)
Nov 29 Python
Python解析json之ValueError: Expecting property name enclosed in double quotes: line 1 column 2(char 1)
Jul 06 Python
Python多线程扫描端口代码示例
Feb 09 Python
Python处理命令行参数模块optpars用法实例分析
May 31 Python
Pandas统计重复的列里面的值方法
Jan 30 Python
Django实现文件上传下载
Oct 06 Python
Python 实现自动导入缺失的库
Oct 29 Python
python实现批量修改文件名
Mar 23 Python
pymysql之cur.fetchall() 和cur.fetchone()用法详解
May 15 Python
django 实现后台从富文本提取纯文本
Jul 02 Python
Python max函数中key的用法及原理解析
Jun 26 Python
Anaconda配置各版本Pytorch的实现
Aug 07 Python
python3访问字典里的值实例方法
Nov 18 #Python
让你相见恨晚的十个Python骚操作
Nov 18 #Python
python搜索算法原理及实例讲解
Nov 18 #Python
python的数学算法函数及公式用法
Nov 18 #Python
python3中TQDM库安装及使用详解
Nov 18 #Python
Python3中FuzzyWuzzy库实例用法
Nov 18 #Python
scrapy redis配置文件setting参数详解
Nov 18 #Python
You might like
火影忍者:三大瞳力之一的白眼,为什么没有写轮眼那么出色?
2020/03/02 日漫
PHP+DBM的同学录程序(1)
2006/10/09 PHP
使用HMAC-SHA1签名方法详解
2013/06/26 PHP
一个图片地址分解程序(用于PHP小偷程序)
2014/08/23 PHP
DEDE实现转跳属性文档在模板上调用出转跳地址
2016/11/04 PHP
JXTree对象,读取外部xml文件数据,生成树的函数
2007/04/02 Javascript
javascript中的undefined 与 null 的区别  补充篇
2010/03/17 Javascript
JS组件Bootstrap Table表格多行拖拽效果实现代码
2015/12/08 Javascript
理解javascript中DOM事件
2015/12/25 Javascript
AngularJs表单验证实例详解
2016/05/30 Javascript
详解为Angular.js内置$http服务添加拦截器的方法
2016/12/20 Javascript
JavaScript实现自定义媒体播放器方法介绍
2017/01/03 Javascript
vue2实现移动端上传、预览、压缩图片解决拍照旋转问题
2017/04/13 Javascript
JQuery 获取Dom元素的实例讲解
2017/07/08 jQuery
Vue.js实现网格列表布局转换方法
2017/08/25 Javascript
EasyUI Tree树组件无限循环的解决方法
2017/09/27 Javascript
在Vue中获取组件声明时的name属性方法
2018/09/12 Javascript
原生js实现trigger方法示例代码
2019/05/22 Javascript
js回溯法计算最佳旅行线路代码实例
2019/09/11 Javascript
Vue使用vue-draggable 插件在不同列表之间拖拽功能
2020/03/12 Javascript
微信小程序点击滚动到指定位置的实现
2020/05/22 Javascript
Js生成随机数/随机字符串的方法小结【5种方法】
2020/05/27 Javascript
python去除所有html标签的方法
2015/05/05 Python
PyCharm设置护眼背景色的方法
2018/10/29 Python
解决pyinstaller打包exe文件出现命令窗口一闪而过的问题
2018/10/31 Python
情人节快乐! python绘制漂亮玫瑰
2020/08/18 Python
Python使用QQ邮箱发送邮件报错smtplib.SMTPAuthenticationError
2019/12/20 Python
Python使用configparser库读取配置文件
2020/02/22 Python
Python数据正态性检验实现过程
2020/04/18 Python
普通大学毕业生自荐信
2013/11/04 职场文书
大学生操行评语大全
2014/12/31 职场文书
高考学习决心书
2015/02/04 职场文书
2015年行政管理人员工作总结
2015/10/15 职场文书
《初涉尘世》读后感3篇
2020/01/10 职场文书
阿里云日志过滤器配置日志服务
2022/04/09 Servers
vue代码分块和懒加载非必要资源文件
2022/04/11 Vue.js