如何利用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中的模块和包概念介绍
Apr 13 Python
Python中正则表达式的详细教程
Apr 30 Python
Python安装第三方库的3种方法
Jun 21 Python
TensorFlow在MAC环境下的安装及环境搭建
Nov 14 Python
python实现隐马尔科夫模型HMM
Mar 25 Python
python实现反转部分单向链表
Sep 27 Python
使用PyCharm创建Django项目及基本配置详解
Oct 24 Python
Python随机生成身份证号码及校验功能
Dec 04 Python
python中的tcp示例详解
Dec 09 Python
解析Python的缩进规则的使用
Jan 16 Python
Django框架文件上传与自定义图片上传路径、上传文件名操作分析
May 10 Python
django 读取图片到页面实例
Mar 27 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面向对象的进阶学习(抽像类、接口、final、类常量)
2012/05/07 PHP
php获得url参数中具有&amp;的值的方法
2014/03/05 PHP
PHP的error_reporting错误级别变量对照表
2014/07/08 PHP
php简单计算页面加载时间的方法
2015/06/19 PHP
PHP读取汉字的点阵数据
2015/06/22 PHP
使用PHP json_decode可能遇到的坑与解决方法
2017/08/03 PHP
tp5框架的增删改查操作示例
2019/10/31 PHP
php反序列化长度变化尾部字符串逃逸(0CTF-2016-piapiapia)
2020/02/15 PHP
php操作redis命令及代码实例大全
2020/11/19 PHP
javascript之大字符串的连接的StringBuffer 类
2007/05/08 Javascript
jquery ui dialog ie8出现滚动条的解决方法
2010/12/06 Javascript
Query中click(),bind(),live(),delegate()的区别
2013/11/19 Javascript
使用js dom和jquery分别实现简单增删改
2014/09/11 Javascript
浅谈javascript原型链与继承
2015/07/13 Javascript
JavaScript 性能优化小结
2015/10/12 Javascript
Js自动截取字符串长度,添加省略号(……)的实现方法
2017/03/06 Javascript
JavaScript 实现 Tab 点击切换实例代码
2017/03/25 Javascript
Windows安装Node.js报错:2503、2502的解决方法
2017/10/25 Javascript
浅谈redux, koa, express 中间件实现对比解析
2019/05/23 Javascript
基于 vue-skeleton-webpack-plugin 的骨架屏实战
2019/08/05 Javascript
安装多版本Vue-CLI的实现方法
2020/03/24 Javascript
javascript实现倒计时关闭广告
2021/02/09 Javascript
python基础教程之对象和类的实际运用
2014/08/29 Python
Python随机读取文件实现实例
2017/05/25 Python
python如何爬取个性签名
2018/06/19 Python
使用Django2快速开发Web项目的详细步骤
2019/01/06 Python
基于selenium及python实现下拉选项定位select
2020/07/22 Python
详解CSS3中@media的实际使用
2015/08/04 HTML / CSS
美国玩具公司:U.S.Toy
2018/05/19 全球购物
管理心得体会
2013/12/28 职场文书
《童年》教学反思
2014/02/18 职场文书
周年庆典主持词
2014/04/02 职场文书
2014年大班保育员工作总结
2014/12/02 职场文书
辞职书格式样本
2015/02/26 职场文书
护林员个人总结
2015/03/04 职场文书
解决springboot druid数据库连接失败后一直重连的方法
2022/04/19 Java/Android