如何利用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生成指定长度的随机数密码
Jan 23 Python
Python探索之修改Python搜索路径
Oct 25 Python
django文档学习之applications使用详解
Jan 29 Python
解决python2 绘图title,xlabel,ylabel出现中文乱码的问题
Jan 29 Python
python 并发编程 阻塞IO模型原理解析
Aug 20 Python
django xadmin中form_layout添加字段显示方式
Mar 30 Python
Python引入多个模块及包的概念过程解析
Sep 21 Python
python中如何打包用户自定义模块
Sep 23 Python
python中的split、rsplit、splitlines用法说明
Oct 23 Python
python如何在word中存储本地图片
Apr 07 Python
python用tkinter开发的扫雷游戏
Jun 01 Python
python获取带有返回值的多线程
May 02 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
PHP中使用sleep造成mysql读取失败的案例和解决方法
2014/08/21 PHP
php采用ajax数据提交post与post常见方法总结
2014/11/10 PHP
PHP实现发送邮件的方法(基于简单邮件发送类)
2015/12/17 PHP
在PHP站点的页面上添加Facebook评论插件的实例教程
2016/01/08 PHP
Mac版PhpStorm之XAMPP整合apache服务器配置的图文教程详解
2016/10/13 PHP
php 二维数组时间排序实现代码
2016/11/19 PHP
删除PHP数组中头部、尾部、任意元素的实现代码
2017/04/10 PHP
PHP通过调用新浪API生成t.cn格式短网址链接的方法详解
2019/02/20 PHP
JavaScript实现Flash炫光波动特效
2015/05/14 Javascript
详解JavaScript对Date对象的操作问题(生成一个倒数7天的数组)
2015/10/01 Javascript
jQuery技巧之让任何组件都支持类似DOM的事件管理
2016/04/05 Javascript
谈谈Vue.js——vue-resource全攻略
2017/01/16 Javascript
vue中用动态组件实现选项卡切换效果
2017/03/25 Javascript
Bootstrap table使用方法汇总
2017/11/17 Javascript
写给小白看的JavaScript异步
2017/11/29 Javascript
vue中element组件样式修改无效的解决方法
2018/02/03 Javascript
Vue实现购物车详情页面的方法
2019/08/20 Javascript
js实现橱窗展示效果
2020/01/11 Javascript
在Python中使用全局日志时需要注意的问题
2015/05/06 Python
python web基础之加载静态文件实例
2018/03/20 Python
解决webdriver.Chrome()报错:Message:'chromedriver' executable needs to be in Path
2019/06/12 Python
python小白切忌乱用表达式
2020/05/29 Python
浅谈python opencv对图像颜色通道进行加减操作溢出
2020/06/03 Python
PyCharm中关于安装第三方包的三个建议
2020/09/17 Python
Expedia英国:全球最大的在线旅游公司
2017/09/07 全球购物
非凡女性奢华谦虚风格:The Modist
2017/10/28 全球购物
俄罗斯花园种植材料批发和零售网上商店:Беккер
2019/07/22 全球购物
企业负责人任命书
2014/06/05 职场文书
2014年体育工作总结
2014/11/24 职场文书
先进集体申报材料
2014/12/25 职场文书
2015年宣传部工作总结范文
2015/03/31 职场文书
力克胡哲观后感
2015/06/10 职场文书
2019年12月24日平安夜祝福语集锦
2019/12/24 职场文书
React列表栏及购物车组件使用详解
2021/06/28 Javascript
聊聊SpringBoot自动装配的魔力
2021/11/17 Java/Android
Windows Server 2019 域控制器安装图文教程
2022/04/28 Servers