Python炸弹人小游戏源代码

Python炸弹人小游戏源代码,使用键盘方向键移动小人,按空格放置炸弹,通过巧妙的放置炸弹来获得道具或消灭敌人。程序运行截图:
在这里插入图片描述
核心代码:

'''
Function:
	炸弹人小游戏
Author:
	Charles
微信公众号:
	Python代码大全
'''
import sys
import cfg
import random
import pygame
from modules.MAP import *
from modules.misc import *
from modules.Sprites import *


'''游戏主程序'''
def main(cfg):
	# 初始化
	pygame.init()
	pygame.mixer.init()
	pygame.mixer.music.load(cfg.BGMPATH)
	pygame.mixer.music.play(-1, 0.0)
	screen = pygame.display.set_mode(cfg.SCREENSIZE)
	pygame.display.set_caption('Bomber Man - 微信公众号: Python代码大全')
	# 开始界面
	Interface(screen, cfg, mode='game_start')
	# 游戏主循环
	font = pygame.font.SysFont('Consolas', 15)
	for gamemap_path in cfg.GAMEMAPPATHS:
		# -地图
		map_parser = mapParser(gamemap_path, bg_paths=cfg.BACKGROUNDPATHS, wall_paths=cfg.WALLPATHS, blocksize=cfg.BLOCKSIZE)
		# -水果
		fruit_sprite_group = pygame.sprite.Group()
		used_spaces = []
		for i in range(5):
			coordinate = map_parser.randomGetSpace(used_spaces)
			used_spaces.append(coordinate)
			fruit_sprite_group.add(Fruit(random.choice(cfg.FRUITPATHS), coordinate=coordinate, blocksize=cfg.BLOCKSIZE))
		# -我方Hero
		coordinate = map_parser.randomGetSpace(used_spaces)
		used_spaces.append(coordinate)
		ourhero = Hero(imagepaths=cfg.HEROZELDAPATHS, coordinate=coordinate, blocksize=cfg.BLOCKSIZE, map_parser=map_parser, hero_name='ZELDA')
		# -电脑Hero
		aihero_sprite_group = pygame.sprite.Group()
		coordinate = map_parser.randomGetSpace(used_spaces)
		aihero_sprite_group.add(Hero(imagepaths=cfg.HEROBATMANPATHS, coordinate=coordinate, blocksize=cfg.BLOCKSIZE, map_parser=map_parser, hero_name='BATMAN'))
		used_spaces.append(coordinate)
		coordinate = map_parser.randomGetSpace(used_spaces)
		aihero_sprite_group.add(Hero(imagepaths=cfg.HERODKPATHS, coordinate=coordinate, blocksize=cfg.BLOCKSIZE, map_parser=map_parser, hero_name='DK'))
		used_spaces.append(coordinate)
		# -炸弹bomb
		bomb_sprite_group = pygame.sprite.Group()
		# -用于判断游戏胜利或者失败的flag
		is_win_flag = False
		# -主循环
		screen = pygame.display.set_mode(map_parser.screen_size)
		clock = pygame.time.Clock()
		while True:
			dt = clock.tick(cfg.FPS)
			for event in pygame.event.get():
				if event.type == pygame.QUIT:
					pygame.quit()
					sys.exit(-1)
				# --↑↓←→键控制上下左右, 空格键丢炸弹
				elif event.type == pygame.KEYDOWN:
					if event.key == pygame.K_UP:
						ourhero.move('up')
					elif event.key == pygame.K_DOWN:
						ourhero.move('down')
					elif event.key == pygame.K_LEFT:
						ourhero.move('left')
					elif event.key == pygame.K_RIGHT:
						ourhero.move('right')
					elif event.key == pygame.K_SPACE:
						if ourhero.bomb_cooling_count <= 0:
							bomb_sprite_group.add(ourhero.generateBomb(imagepath=cfg.BOMBPATH, digitalcolor=cfg.YELLOW, explode_imagepath=cfg.FIREPATH))
			screen.fill(cfg.WHITE)
			# --电脑Hero随机行动
			for hero in aihero_sprite_group:
				action, flag = hero.randomAction(dt)
				if flag and action == 'dropbomb':
					bomb_sprite_group.add(hero.generateBomb(imagepath=cfg.BOMBPATH, digitalcolor=cfg.YELLOW, explode_imagepath=cfg.FIREPATH))
			# --吃到水果加生命值(只要是Hero, 都能加)
			ourhero.eatFruit(fruit_sprite_group)
			for hero in aihero_sprite_group:
				hero.eatFruit(fruit_sprite_group)
			# --游戏元素都绑定到屏幕上
			map_parser.draw(screen)
			for bomb in bomb_sprite_group:
				if not bomb.is_being:
					bomb_sprite_group.remove(bomb)
				explode_area = bomb.draw(screen, dt, map_parser)
				if explode_area:
					# --爆炸火焰范围内的Hero生命值将持续下降
					if ourhero.coordinate in explode_area:
						ourhero.health_value -= bomb.harm_value
					for hero in aihero_sprite_group:
						if hero.coordinate in explode_area:
							hero.health_value -= bomb.harm_value
			fruit_sprite_group.draw(screen)
			for hero in aihero_sprite_group:
				hero.draw(screen, dt)
			ourhero.draw(screen, dt)
			# --左上角显示生命值
			pos_x = showText(screen, font, text=ourhero.hero_name+'(our):'+str(ourhero.health_value), color=cfg.YELLOW, position=[5, 5])
			for hero in aihero_sprite_group:
				pos_x, pos_y = pos_x+15, 5
				pos_x = showText(screen, font, text=hero.hero_name+'(ai):'+str(hero.health_value), color=cfg.YELLOW, position=[pos_x, pos_y])
			# --我方玩家生命值小于等于0/电脑方玩家生命值均小于等于0则判断游戏结束
			if ourhero.health_value <= 0:
				is_win_flag = False
				break
			for hero in aihero_sprite_group:
				if hero.health_value <= 0:
					aihero_sprite_group.remove(hero)
			if len(aihero_sprite_group) == 0:
				is_win_flag = True
				break
			pygame.display.update()
			clock.tick(cfg.FPS)
		if is_win_flag:
			Interface(screen, cfg, mode='game_switch')
		else:
			break
	Interface(screen, cfg, mode='game_end')


'''run'''
if __name__ == '__main__':
	while True:
		main(cfg)

sprites.py

'''
Function:
	定义必要的游戏精灵类
Author:
	Charles
微信公众号:
	Python代码大全
'''
import copy
import random
import pygame


'''墙类'''
class Wall(pygame.sprite.Sprite):
	def __init__(self, imagepath, coordinate, blocksize, **kwargs):
		pygame.sprite.Sprite.__init__(self)
		self.image = pygame.image.load(imagepath)
		self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
		self.rect = self.image.get_rect()
		self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
		self.coordinate = coordinate
		self.blocksize = blocksize
	'''画到屏幕上'''
	def draw(self, screen):
		screen.blit(self.image, self.rect)
		return True


'''背景类'''
class Background(pygame.sprite.Sprite):
	def __init__(self, imagepath, coordinate, blocksize, **kwargs):
		pygame.sprite.Sprite.__init__(self)
		self.image = pygame.image.load(imagepath)
		self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
		self.rect = self.image.get_rect()
		self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
		self.coordinate = coordinate
		self.blocksize = blocksize
	'''画到屏幕上'''
	def draw(self, screen):
		screen.blit(self.image, self.rect)
		return True


'''水果类'''
class Fruit(pygame.sprite.Sprite):
	def __init__(self, imagepath, coordinate, blocksize, **kwargs):
		pygame.sprite.Sprite.__init__(self)
		self.kind = imagepath.split('/')[-1].split('.')[0]
		if self.kind == 'banana':
			self.value = 5
		elif self.kind == 'cherry':
			self.value = 10
		else:
			raise ValueError('Unknow fruit <%s>...' % self.kind)
		self.image = pygame.image.load(imagepath)
		self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
		self.rect = self.image.get_rect()
		self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
		self.coordinate = coordinate
		self.blocksize = blocksize
	'''画到屏幕上'''
	def draw(self, screen):
		screen.blit(self.image, self.rect)
		return True


'''炸弹类'''
class Bomb(pygame.sprite.Sprite):
	def __init__(self, imagepath, coordinate, blocksize, digitalcolor, explode_imagepath, **kwargs):
		pygame.sprite.Sprite.__init__(self)
		self.image = pygame.image.load(imagepath)
		self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
		self.explode_imagepath = explode_imagepath
		self.rect = self.image.get_rect()
		# 像素位置
		self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
		# 坐标(元素块为单位长度)
		self.coordinate = coordinate
		self.blocksize = blocksize
		# 爆炸倒计时
		self.explode_millisecond = 6000 * 1 - 1
		self.explode_second = int(self.explode_millisecond / 1000)
		self.start_explode = False
		# 爆炸持续时间
		self.exploding_count = 1000 * 1
		# 炸弹伤害能力
		self.harm_value = 1
		# 该炸弹是否还存在
		self.is_being = True
		self.font = pygame.font.SysFont('Consolas', 20)
		self.digitalcolor = digitalcolor
	'''画到屏幕上'''
	def draw(self, screen, dt, map_parser):
		if not self.start_explode:
			# 爆炸倒计时
			self.explode_millisecond -= dt
			self.explode_second = int(self.explode_millisecond / 1000)
			if self.explode_millisecond < 0:
				self.start_explode = True
			screen.blit(self.image, self.rect)
			text = self.font.render(str(self.explode_second), True, self.digitalcolor)
			rect = text.get_rect(center=(self.rect.centerx-5, self.rect.centery+5))
			screen.blit(text, rect)
			return False
		else:
			# 爆炸持续倒计时
			self.exploding_count -= dt
			if self.exploding_count > 0:
				return self.__explode(screen, map_parser)
			else:
				self.is_being = False
				return False
	'''爆炸效果'''
	def __explode(self, screen, map_parser):
		explode_area = self.__calcExplodeArea(map_parser.instances_list)
		for each in explode_area:
			image = pygame.image.load(self.explode_imagepath)
			image = pygame.transform.scale(image, (self.blocksize, self.blocksize))
			rect = image.get_rect()
			rect.left, rect.top = each[0] * self.blocksize, each[1] * self.blocksize
			screen.blit(image, rect)
		return explode_area
	'''计算爆炸区域'''
	def __calcExplodeArea(self, instances_list):
		explode_area = []
		# 区域计算规则为墙可以阻止爆炸扩散, 且爆炸范围仅在游戏地图范围内
		for ymin in range(self.coordinate[1], self.coordinate[1]-5, -1):
			if ymin < 0 or instances_list[ymin][self.coordinate[0]] in ['w', 'x', 'z']:
				break
			explode_area.append([self.coordinate[0], ymin])
		for ymax in range(self.coordinate[1]+1, self.coordinate[1]+5):
			if ymax >= len(instances_list) or instances_list[ymax][self.coordinate[0]] in ['w', 'x', 'z']:
				break
			explode_area.append([self.coordinate[0], ymax])
		for xmin in range(self.coordinate[0], self.coordinate[0]-5, -1):
			if xmin < 0 or instances_list[self.coordinate[1]][xmin] in ['w', 'x', 'z']:
				break
			explode_area.append([xmin, self.coordinate[1]])
		for xmax in range(self.coordinate[0]+1, self.coordinate[0]+5):
			if xmax >= len(instances_list[0]) or instances_list[self.coordinate[1]][xmax] in ['w', 'x', 'z']:
				break
			explode_area.append([xmax, self.coordinate[1]])
		return explode_area


'''角色类'''
class Hero(pygame.sprite.Sprite):
	def __init__(self, imagepaths, coordinate, blocksize, map_parser, **kwargs):
		pygame.sprite.Sprite.__init__(self)
		self.imagepaths = imagepaths
		self.image = pygame.image.load(imagepaths[-1])
		self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
		self.rect = self.image.get_rect()
		self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
		self.coordinate = coordinate
		self.blocksize = blocksize
		self.map_parser = map_parser
		self.hero_name = kwargs.get('hero_name')
		# 生命值
		self.health_value = 50
		# 炸弹冷却时间
		self.bomb_cooling_time = 5000
		self.bomb_cooling_count = 0
		# 随机移动冷却时间(仅AI电脑用)
		self.randommove_cooling_time = 100
		self.randommove_cooling_count = 0
	'''角色移动'''
	def move(self, direction):
		self.__updateImage(direction)
		if direction == 'left':
			if self.coordinate[0]-1 < 0 or self.map_parser.getElemByCoordinate([self.coordinate[0]-1, self.coordinate[1]]) in ['w', 'x', 'z']:
				return False
			self.coordinate[0] = self.coordinate[0] - 1
		elif direction == 'right':
			if self.coordinate[0]+1 >= self.map_parser.width or self.map_parser.getElemByCoordinate([self.coordinate[0]+1, self.coordinate[1]]) in ['w', 'x', 'z']:
				return False
			self.coordinate[0] = self.coordinate[0] + 1
		elif direction == 'up':
			if self.coordinate[1]-1 < 0 or self.map_parser.getElemByCoordinate([self.coordinate[0], self.coordinate[1]-1]) in ['w', 'x', 'z']:
				return False
			self.coordinate[1] = self.coordinate[1] - 1
		elif direction == 'down':
			if self.coordinate[1]+1 >= self.map_parser.height or self.map_parser.getElemByCoordinate([self.coordinate[0], self.coordinate[1]+1]) in ['w', 'x', 'z']:
				return False
			self.coordinate[1] = self.coordinate[1] + 1
		else:
			raise ValueError('Unknow direction <%s>...' % direction)
		self.rect.left, self.rect.top = self.coordinate[0] * self.blocksize, self.coordinate[1] * self.blocksize
		return True
	'''随机行动(AI电脑用)'''
	def randomAction(self, dt):
		# 冷却倒计时
		if self.randommove_cooling_count > 0:
			self.randommove_cooling_count -= dt
		action = random.choice(['left', 'left', 'right', 'right', 'up', 'up', 'down', 'down', 'dropbomb'])
		flag = False
		if action in ['left', 'right', 'up', 'down']:
			if self.randommove_cooling_count <= 0:
				flag = True
				self.move(action)
				self.randommove_cooling_count = self.randommove_cooling_time
		elif action in ['dropbomb']:
			if self.bomb_cooling_count <= 0:
				flag = True
				self.bomb_cooling_count = self.bomb_cooling_time
		return action, flag
	'''生成炸弹'''
	def generateBomb(self, imagepath, digitalcolor, explode_imagepath):
		return Bomb(imagepath=imagepath, coordinate=copy.deepcopy(self.coordinate), blocksize=self.blocksize, digitalcolor=digitalcolor, explode_imagepath=explode_imagepath)
	'''画到屏幕上'''
	def draw(self, screen, dt):
		# 冷却倒计时
		if self.bomb_cooling_count > 0:
			self.bomb_cooling_count -= dt
		screen.blit(self.image, self.rect)
		return True
	'''吃水果'''
	def eatFruit(self, fruit_sprite_group):
		eaten_fruit = pygame.sprite.spritecollide(self, fruit_sprite_group, True, None)
		for fruit in eaten_fruit:
			self.health_value += fruit.value
	'''更新角色朝向'''
	def __updateImage(self, direction):
		directions = ['left', 'right', 'up', 'down']
		idx = directions.index(direction)
		self.image = pygame.image.load(self.imagepaths[idx])
		self.image = pygame.transform.scale(self.image, (self.blocksize, self.blocksize))

完整程序代码下载地址:Python炸弹人小游戏源代码
更多Python源代码,请关注公众号:Python代码大全
在这里插入图片描述

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Python代码大全

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值