如何利用Python写个坦克大战

前言

坦克大战是一款策略类的平面射击游戏,于 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()

实现效果

看一下实现效果:

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

总结

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

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

(0)

相关推荐

  • python实现坦克大战

    本文实例为大家分享了python实现坦克大战的具体代码,供大家参考,具体内容如下 本游戏制作代码量较大 具体代码与图片声源可以在我的GitHub中下载 github地址 下面来看看然后利用python做一个坦克大战游戏 创建子弹类 import pygame class Bullet(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) self.bullet_up = pygame.imag

  • python实现坦克大战游戏 附详细注释

    本文实例为大家分享了python实现坦克大战的具体代码,供大家参考,具体内容如下 #功能实现游戏主窗口 import pygame,time,random#导入模块 _display = pygame.display#赋值给一个变量 调用时方便 color_red = pygame.Color(255,0,0)#同上 v class MainGame(object): screen_width = 900#游戏界面宽度 screen_height = 550#界面的高度 Tank_p1 = No

  • python实现简单坦克大战

    基于对面向对象编程的思想完成简单的坦克大战游戏.主要目的锻炼面相对象编程思想 同样的在使用python进行游戏编写时需要安装pygame模块 安装方法: pycharm安装方式:File --> setting 游戏中的主要对象有: 坦克父类:BaseTank 我方坦克:HeroTank 敌方坦克:EnemyTank 子弹类:Bullet 爆炸类:Explode 墙类:Wall 主进程:MainGame 定义一个精灵类: # 定义一个精灵类 class BaseItem(Sprite): def

  • python使用pygame模块实现坦克大战游戏

    本文实例为大家分享了pygame模块实现坦克大战游戏的具体代码,供大家参考,具体内容如下 首先,第一步,游戏简单素材的准备. 炮弹,炮弹,坦克移动.音乐-开火素材. 其次,思路整理. 我们需要几个类,分别是玩家类,敌人类,炮弹类及地图类,开始游戏界面以及结束界面,血条等等. 开始coding. 主函数,new一个对象(java乱入emmm),声明一个对象. # encoding : utf-8 # anthor : comi from gameloop import * from pygame

  • python+pygame实现坦克大战

    本文实例为大家分享了python+pygame实现坦克大战的具体代码,供大家参考,具体内容如下 一.首先导入pygame库 二.源码分享 #coding=utf-8 import pygame import time import random from pygame.sprite import Sprite SCREEN_WIDTH=800 SCREEN_HEIGHT=500 BG_COLOR=pygame.Color(0,0,0) TEXT_COLOR=pygame.Color(255,0,

  • 基于python实现坦克大战游戏

    本文实例为大家分享了python实现坦克大战游戏的具体代码,供大家参考,具体内容如下 游戏界面 pygame游戏引擎的安装 pip安装 windows + R --> cmd --> 命令行输入 pip install 模块名==版本号 pycharm中安装 File --> setting --> Project --> Project Interpreter --> 右侧 + install --> 搜索框输入pygame --> 下方 installP

  • python+pygame实现坦克大战小游戏的示例代码(可以自定义子弹速度)

    python+pygame实现坦克大战小游戏-可以自定义子弹速度: 运行环境–python3.7.pycharm: 源码需要请:点赞留言邮箱: 正常版子弹速度: 普通速度版 加速版子弹速度: 子弹加速版 另外还有多种道具,支持两人一起玩.main()方法如下: def main(): pygame.init() pygame.mixer.init() resolution = 630, 630 screen = pygame.display.set_mode(resolution) pygame

  • 如何利用Python写个坦克大战

    前言 坦克大战是一款策略类的平面射击游戏,于 1985 年由 Namco 游戏公司发布,尽管时至今日已经有了很多衍生类的游戏,但这款游戏仍然受到了相当一部分人的欢迎,本文我们看一下如何使用 Python 来实现这款游戏,游戏实现主要用到的 Python 库为 pygame. 简介 坦克大战的组成主要包括:场景.坦克.子弹.食物.大本营,其本质就是一个塔防类的游戏,游戏目标为:守住大本营并且消灭敌方坦克,通常支持单双人模式,下面我们来看一下具体实现. 实现 首先,我们来实现游戏场景,场景的组成主要

  • 利用Python写个简易版星空大战游戏

    目录 前言 一.游戏画面 二.游戏结束画面 三.游戏素材 四.游戏代码 五.核心代码 1.导入模块 2.动态星空背景函数 3.不定时产生敌机函数 4.飞碟的移动 5.子弹的移动 6.玩家射击函数 7.播放背景音乐与生成声效对象 8.新建屏幕 9.移动图章实现星星 10.哭脸 11.玩家 12.飞碟移动与子弹移动 13.敌机的碰撞检测 14.闯关成功把子弹删除 六.总结 前言 通过辣条最近观察,大家好像对划水摸鱼是情有独钟啊.于是乎我重操旧业又写上了这么一个简单版的星空大战小游戏. 当然了辣条的初

  • 如何利用python写GUI及生成.exe可执行文件

    目录 一.GUI(Graphical User Interface(图形用户接口)) 1.导入需要用到的包 2.获取文件夹中所有图片 3.定义一个类windows 4.创建窗口和frame 5.定义需要用到的函数(下一页.上一页等按钮要用到的) 6.创建按钮.画布,调用主程序 效果展示 完整代码 二.生成exe文件 1.安装pyinstaller 2.打包python程序 3.运行exe文件 4.常用命令参数 效果展示 执行exe应用 总结 一.GUI(Graphical User Interf

  • 利用Python写个摸鱼监控进程

    目录 监控键盘 监控鼠标 记录监控日志 完整代码 总结 继打游戏.看视频等摸鱼行为被监控后,现在打工人离职的倾向也会被监控. 有网友爆料称知乎正在低调裁员,视频相关部门几乎要裁掉一半.而在知乎裁员的讨论区,有网友表示企业安装了行为感知系统,该系统可以提前获知员工跳槽念头. 而知乎在否认了裁员计划的同时,也声明从未安装使用过网上所说的行为感知系统,今后也不会启用类似软件工具. 因为此事,深信服被推上风口浪尖,舆论关注度越来越高. 一时间,“打工人太难了”“毫无隐私可言”的讨论层出不穷. 今天就带大

  • 利用Python写了一个水果忍者小游戏

    目录 前言: 一.需要导入的包 二.窗口界面设置 三.随机生成水果位置 四.绘制字体 五.玩家生命的提示 六.游戏开始与结束的画面 七.游戏主循环 最后 前言: 水果忍者到家都玩过吧,但是Python写的水果忍者你肯定没有玩过.今天就给你表演一个新的,用Python写一个水果忍者.水果忍者的玩法很简单,尽可能的切开抛出的水果就行. 今天就用python简单的模拟一下这个游戏.在这个简单的项目中,我们用鼠标选择水果来切割,同时炸弹也会隐藏在水果中,如果切开了三次炸弹,玩家就会失败. 一.需要导入的

  • 利用python写api接口实战指南

    目录 一.操作步骤 二.源码举例 总结 一.操作步骤 导入:import flask,json 实例化:api = flask.Flask(name) 定义接口访问路径及访问方式:@api.route(’/index’,methods=[‘get/post/PUT/DELETE’]) 定义函数,注意需与路径的名称一致,设置返回类型并支持中文:def index(): return json.dumps(ren,ensure_ascii=False) 三种格式入参访问接口:5.1 url格式入参:

  • 如何利用Python写猜数字和字母的游戏

    目录 前言 猜数字游戏 猜字母游戏 前言 学完语法和正在学习语法的时候,我们可以在空闲的时候,写几个简单的小项目,今天我们就用最基础的语法看两个实战语法练习 猜数字游戏 项目游戏说明:让用户输入一个数字,然后系统自动产生一个序列里面的随机数,然后让用户猜,直到猜正确之后程序才会停止,不让就会一直运行. 涉及知识:while循环,条件语句,字符串定义,random模块(随机序列数的产生) 代码如下; # -*- coding : utf-8 -*- import random num = rand

随机推荐