基于Python实现炸弹人小游戏

目录
  • 前言
  • 效果展示
  • 开发工具
  • 环境搭建
  • 原理简介
  • 主要代码

前言

今天用Python实现的是一个炸弹人小游戏,废话不多说,让我们愉快地开始吧~

效果展示

开发工具

Python版本: 3.6.4

相关模块:

pygame模块;

以及一些Python自带的模块。

环境搭建

安装Python并添加到环境变量,pip安装需要的相关模块即可。

原理简介

游戏规则:

玩家通过↑↓←→键控制角色zelda(绿色)行动,当玩家按下空格键时,则可以在当前位置放置炸弹。其他角色(dk和batman)则由电脑控制进行随机行动。所有角色被炸弹产生的火焰灼烧时(包括自己放置的炸弹),都将损失一定生命值;所有角色吃到水果时,均可恢复一定数值的生命值。另外,墙可以阻止炸弹产生的火焰进一步扩散。

当我方角色zelda生命值为0时,游戏失败;当电脑方所有角色生命值为0时,游戏胜利,进入下一关。

逐步实现:

首先,我们来明确一下该游戏包含哪些游戏精灵类:

  • 炸弹类
  • 角色类
  • 墙类
  • 背景类
  • 水果类

主要代码

墙类和背景类很好定义,只需要可以导入图片,然后把图片绑定到指定位置就行了:

'''墙类'''
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 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))

炸弹类则需要有倒计时提示功能,以及倒计时结束之后在炸弹杀伤范围内产生火焰特效(穷,估计只值1毛钱的特效T_T,大家多担待):

'''炸弹类'''
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

因为炸弹类和角色类每帧都要绑定到游戏屏幕上,所以一些倒计时操作就合并地写到draw函数里了,当然最好是重新写一个函数来实现该功能,那样代码结构看起来会更清晰一些。

接下来,我们在.map文件中设计我们的游戏地图:

然后通过一个地图解析类来解析.map文件,这样每次切换关卡时只需要重新导入一个新的.map文件就行了,同时这样也方便游戏后续进行扩展:

'''.map文件解析器'''
class mapParser():
  def __init__(self, mapfilepath, bg_paths, wall_paths, blocksize, **kwargs):
    self.instances_list = self.__parse(mapfilepath)
    self.bg_paths = bg_paths
    self.wall_paths = wall_paths
    self.blocksize = blocksize
    self.height = len(self.instances_list)
    self.width = len(self.instances_list[0])
    self.screen_size = (blocksize * self.width, blocksize * self.height)
  '''地图画到屏幕上'''
  def draw(self, screen):
    for j in range(self.height):
      for i in range(self.width):
        instance = self.instances_list[j][i]
        if instance == 'w':
          elem = Wall(self.wall_paths[0], [i, j], self.blocksize)
        elif instance == 'x':
          elem = Wall(self.wall_paths[1], [i, j], self.blocksize)
        elif instance == 'z':
          elem = Wall(self.wall_paths[2], [i, j], self.blocksize)
        elif instance == '0':
          elem = Background(self.bg_paths[0], [i, j], self.blocksize)
        elif instance == '1':
          elem = Background(self.bg_paths[1], [i, j], self.blocksize)
        elif instance == '2':
          elem = Background(self.bg_paths[2], [i, j], self.blocksize)
        else:
          raise ValueError('instance parse error in mapParser.draw...')
        elem.draw(screen)
  '''随机获取一个空地'''
  def randomGetSpace(self, used_spaces=None):
    while True:
      i = random.randint(0, self.width-1)
      j = random.randint(0, self.height-1)
      coordinate = [i, j]
      if used_spaces and coordinate in used_spaces:
        continue
      instance = self.instances_list[j][i]
      if instance in ['0', '1', '2']:
        break
    return coordinate
  '''根据坐标获取元素类型'''
  def getElemByCoordinate(self, coordinate):
    return self.instances_list[coordinate[1]][coordinate[0]]
  '''解析.map文件'''
  def __parse(self, mapfilepath):
    instances_list = []
    with open(mapfilepath) as f:
      for line in f.readlines():
        instances_line_list = []
        for c in line:
          if c in ['w', 'x', 'z', '0', '1', '2']:
            instances_line_list.append(c)
        instances_list.append(instances_line_list)
    return instances_list

OK,做完这些准备工作,就可以开始写游戏主循环啦: 

'''游戏主程序'''
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 -                         
(0)

相关推荐

  • 基于Python Pygame实现的画饼图游戏

    目录 导入包 配置基本参数 根据输入的数字改变扇形的个数 监听事件 这个游戏就是实现键盘上输入不同的数字,将圆分割成不同的几个部分,每部分用不同的颜色来实现. 导入包 导入随机包,pygame,系统包,time时间包用于时间暂停.math是用来确认弧度的. import random import pygame, sys, time import math from pygame.locals import * 配置基本参数 初始化pygame,设置窗口大小标题,设置圆心的x和y轴,圆的半径,线

  • python实现模拟数字的魔术游戏

    游戏介绍 在游戏中,魔术师要每位观众心里想一个三位数abc (a.b.c分别是百位.十位和个位数字),然后魔术师让观众心中记下acb.bac.bca.cab.cba五个数以及这5个数的和值.只要观众说出这个和是多少,则魔术师一定能猜出观众心里想的原数abc是多少.例如,观众甲说他计算的和值是1999,则魔术师立即说出他想的数是443,而观众乙说他计算的和值是1998,则魔术师说:"你算错了!". [输入] 输入一个正整数. [输出] 输出对应的三位数.如果对应的三位数不存在,则输出:&

  • Python实现打地鼠游戏

    目录 开发工具 相关模块 环境搭建 原理简介 主要代码 开发工具 python版本:3.6.4 相关模块 pygame:以及一些python自带的模块. 环境搭建 安装python并添加到环境变量,pip安装需要的相关模块即可. 原理简介 打地鼠的游戏规则相信大家都知道,这里就不多介绍了,反正就是不停地拿锤子打洞里钻出来的地鼠呗~首先,让我们确定一下游戏中有哪些元素.打地鼠打地鼠,地鼠当然得有啦,那我们就写个地鼠的游戏精灵类呗 显然,地鼠有被锤子击中和未被锤子击中这两种状态,所以需要加载两张图,

  • Python Pygame实现兔子猎人守护城堡游戏

    目录 效果图 主要代码 游戏初始化 主函数 运行  效果图 守卫类游戏大家应该玩过吧,什么植物大战僵尸呀,保卫萝卜呀,今天我们自己用python来写一个自己的守护类小游戏兔子猎人守护城堡,让大家看看效果图. 主要代码 下面我来说一下是怎么得到的将代码分享一下给大家 首先得将要用到的库导入进来 import cfg import math import random import pygame from modules.Sprites import * from modules.interface

  • Python实现问题回答小游戏

    目录 读取问题 绘制回答面板 回答问题 问题切换 完整代码 读取问题 如下所示,我们在文本中写了一个问题,然后将其读取出来. "黄河远上白云间,一片孤城万仞山."的作者是谁? 王之涣 李白 白居易 杜甫 file = open("1.txt", "r") question_coll = file.readlines() file.close() print(file) 运行之后发现报错,查询之后发现编码格式不正确. 设置了读取的编码格式发现可以读

  • python实现双人版坦克大战游戏

    游戏介绍: 双人版的<坦克大战>的基本规则是玩家消灭出现的敌方坦克保卫我方基地. 中间还会随机出现很多特殊道具吸收可获得相应的功能,消灭玩即可进入下一关. 方向键:上下左右移动即可.另一个方向键则是:WSAD. 环境配置: Python3. Pycharm .Pygame. 第三方库的安装:pip  install pygame 效果展示: 开始界面一一 开始即可上手玩游戏,还有背景音乐辅助!游戏玩儿起来更带感!  游戏界面-- 代码演示: 1)游戏主程序 import pygame impo

  • 基于Python实现炸弹人小游戏

    目录 前言 效果展示 开发工具 环境搭建 原理简介 主要代码 前言 今天用Python实现的是一个炸弹人小游戏,废话不多说,让我们愉快地开始吧~ 效果展示 开发工具 Python版本: 3.6.4 相关模块: pygame模块: 以及一些Python自带的模块. 环境搭建 安装Python并添加到环境变量,pip安装需要的相关模块即可. 原理简介 游戏规则: 玩家通过↑↓←→键控制角色zelda(绿色)行动,当玩家按下空格键时,则可以在当前位置放置炸弹.其他角色(dk和batman)则由电脑控制

  • 基于Python制作打地鼠小游戏

    效果展示 打地鼠小游戏 简介 打地鼠的游戏规则相信大家都知道,这里就不多介绍了,反正就是不停地拿锤子打洞里钻出来的地鼠呗~ 首先,让我们确定一下游戏中有哪些元素.打地鼠打地鼠,地鼠当然得有啦,那我们就写个地鼠的游戏精灵类呗: '''地鼠''' class Mole(pygame.sprite.Sprite): def __init__(self, image_paths, position, **kwargs): pygame.sprite.Sprite.__init__(self) self.

  • 基于Python实现射击小游戏的制作

    目录 1.游戏画面 1.1开始 1.2射击怪物 2.涉及知识点 3.代码 3.1发射声 3.2背景 3.3射击效果 4.经验总结 1.游戏画面 1.1开始 1.2射击怪物 2.涉及知识点 1.sprites 2.pygame混音器 3.图章 4.python基础语法 3.代码 3.1发射声 from sprites import * try: import pygame pygame.mixer.init() fire_sound = pygame.mixer.Sound("audio/发射声.

  • python实现大战外星人小游戏实例代码

    主程序 import pygame from pygame.sprite import Group from settings import Settings from game_stats import gameStats from ship import Ship from button import Button import game_functions as gf def run_game(): #初始化背景设置 pygame.init() #创建一个Settings实例,并将其储存在

  • 基于flask实现五子棋小游戏

    本文实例为大家分享了基于flask实现五子棋小游戏的具体代码,供大家参考,具体内容如下 前言 首先说明一下,本人方向是java后端,只因老师布置了一个作业,要用flask来做一个五子棋,没办法被逼上梁山,程序不太美观,但是应付作业还是够了的. 废话不多说,下面开锤! 首先整个程序是一个web应用,前端html+css+javaScript(有用到jquery)(基本都是现学的,所以程序很多注释也很丑),后端用的flask框架. 准备工作 **1.**python环境.安装flask **2.**

  • python PyGame五子棋小游戏

    目录 前言 五子棋小游戏 1.简介 2.环境准备 3.初始化环境 4.棋盘 5.黑白棋子 6.对局信息 7.AI 8.完善 总结 前言 PyGame 是一个专门设计来进行游戏开发设计的 Python 模块,允许实时电子游戏研发而无需被低级语言(如机器语言和汇编语言)束缚,使用起来非常的简单,非常适合新手拿来玩耍,本教程源码均基于 Python 3.x 版本. 五子棋小游戏 1.简介 五子棋是我们小时候经常玩的两人对弈策略小游戏,规则简单: 1.对局双方各执一色棋子,常为黑白两色:2.空棋盘开局:

  • 基于Python实现24点游戏的示例代码

    目录 1.前言 2.思路 3.代码 1.前言 24数大家之前玩过没有? 规则:一副扑克牌抽走大王,小王,K,Q,J(有的规则里面会抽走10,本文一律不抽走),之后在牌堆里随机抽取四张牌,将这四张牌加减乘除得到24. 如果再高级一点,还会有根号.阶乘.幂之类的算法,别问为啥不能幂运算,问就是懒,自己看思路自己实现去(bushi. 知识点:随机数,列表,嵌套判断,循环,死循环,都是新手接触的东西. 由于不能进行像根号,阶乘高级的运算,改版之后完全可以了. 话不多说,上思路 2.思路 1.随机生成四个

  • 基于Python实现成语填空游戏的示例代码

    目录 前言 一.环境准备 二.代码展示 三.效果展示 前言 成语填空想必大家都是十分熟悉的了,特别是有在上小学的家长肯定都有十分深刻的印象. 在我们的认知里看图猜成语不就是一些小儿科的东西吗? 当然了你也别小看了成语调控小游戏,有的时候知识储备不够,你还真的不一定猜得出来是什么?更重要的是有的时候给你这个提示你都看不懂,那你就拿他没办法.——小学语文必备 成语是小学语文非常重要的一个知识点,几乎是逢考必有,作为基础,自然是需要长期的积累,并且需要积累到一定的数量,有了一定的量才能够产生质变,对于

  • 使用Python写一个小游戏

    引言 最近python语言大火,除了在科学计算领域python有用武之地之外,在游戏.后台等方面,python也大放异彩,本篇博文将按照正规的项目开发流程,手把手教大家写个python小游戏,来感受下其中的有趣之处.本次开发的游戏叫做alien invasion. 安装pygame并创建能左右移动的飞船 安装pygame 本人电脑是windows 10.python3.6,pygame下载地址: 传送门 请自行下载对应python版本的pygame 运行以下命令 $ pip install wh

  • python实现猜拳小游戏

    用python实现猜拳小游戏,供大家参考,具体内容如下 本练习旨在养成良好的编码习惯和练习逻辑思考. 1.使用python版本: 3.7.3: 2.代码内容实现如下 #!/usr/bin/env python # -*- coding: utf-8 -*- """ 简单实现猜拳小游戏,默认每回合 五局 Version: 0.1 Author: smartbabble Date: 2018-03-12 """ from random import

随机推荐