zoukankan      html  css  js  c++  java
  • 用 Python 写个坦克大战

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

    简介

    很多人学习python,不知道从何学起。
    很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
    很多已经做案例的人,却不知道如何去学习更加高深的知识。
    那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!
    QQ群:1097524789

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

    实现

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

    # 石头墙
    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 实现了坦克大战的基本功能,还有待完善,有兴趣的话,可以对游戏做进一步的完善和扩展。

  • 相关阅读:
    windows系统切换jdk,修改java_home无效情况
    Cannot instantiate interface org.springframework.context.ApplicationListener
    MySQL分组查询获取每个学生前n条分数记录(分组查询前n条记录)
    ASP.NET Web API 使用Swagger生成在线帮助测试文档,支持多个GET
    EF TO MYSQL 无法查询中文的解决方法
    HttpWebRequest post请求获取webservice void数据信息
    This implementation is not part of the Windows Platform FIPS validated cryptographic algorithms. 此实现不是 Windows 平台 FIPS 验证的加密算法的一部分 解决方案
    MySQL 5.7.13解压版安装记录 mysql无法启动教程
    C# udpclient 发送数据断网后自动连接的方法
    汽车XX网站秒杀抢购代码
  • 原文地址:https://www.cnblogs.com/shann001/p/13202436.html
Copyright © 2011-2022 走看看