导语

上一期我们主要带大家写了勇士类,以及勇士与一些简单的地图元素接触时所触发的事件:

童年经典回忆 | 从零开始带大家用Python撸一个魔塔小游戏呀(2)

这一期我们会带大家进一步复现我们的魔塔小游戏,主要内容为进一步完成和其他更为复杂的地图元素接触时可以触发的事件。

废话不多说,让我们愉快地开始吧~

相关文件

相关游戏素材(图片和音频等)源于网络,侵歉删。

对了大家可以关注小编的公众号哟~~
有很多资源可以领取的哟!!

Python日志

开发工具

Python版本:3.7.4
相关模块:
pygame模块;
以及一些python自带的模块。

环境搭建

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

原理介绍

上一期,我们实现了一些简单的勇士和地图元素接触时会触发的事件,就像下图这样:


显然,这个效果图是不完美的,比如左侧面板的时间显示和当前层的显示没有添加,这里我们可以先写几行代码添加一下:

# --左侧面板栏
font = pygame.font.Font(self.cfg.FONTPATH_CN, 20)
font_renders = [self.hero.font.render(str(self.map_level_pointer), True, (255, 255, 255)),font.render('游戏时间: ' + str(pygame.time.get_ticks() // 60000) + ' 分 ' + str(pygame.time.get_ticks() // 1000 % 60) + ' 秒', True, (255, 255, 255)),
]
rects = [fr.get_rect() for fr in font_renders]
rects[0].topleft = (150, 530)
rects[1].topleft = (75, 630)
for fr, rect in zip(font_renders, rects):screen.blit(fr, rect)

添加了这部分代码之后的效果是这样子的:

接着,就是上一期我们说的,在原版的游戏中,勇士和这个仙女碰撞的时候,会出现对话框,类似这样:
这部分内容该如何实现呢?首先,可以肯定的是对话框是由四个部分组成的,即矩形、矩形内填充的底色、左上角的人物图标以及文字内容。他们的实现思路分别应该是:

矩形: 调用pygame画矩形的函数pygame.draw.rect;
底色填充: 导入背景图中黑色的地砖来填充对话框;
左上角人物图标: pygame.image.load导入后画到对应的位置即可;
文字: 主要调用pygame.font.Font实现.

具体而言,我们的代码实现如下:

'''仙女和勇士对话'''
def showconversationheroandfairy(self, screen, scenes):# 对话框指针conversation_pointer = 0# 定义所有对话conversations = [['......'], ['你醒了!'], ['......', '你是谁? 我在哪里?'],['我是这里的仙子, 刚才你被这里的', '小怪打晕了.'],['......', '剑, 剑, 我的剑呢?'],['你的剑被他们抢走了, 我只来得及', '将你救出来.'],['那, 公主呢? 我是来救公主的.'],['公主还在里面, 你这样进去是打不', '过里面的小怪的.'],['那我怎么办, 我答应了国王一定要', '把公主救出来的,那我现在应该怎', '么办呢?'],['放心吧, 我把我的力量借给你, 你', '就可以打赢那些小怪了. 不过, 你', '得先去帮我去找一样东西,找到', '了再来这里找我.'],['找东西? 找什么东西?'],['是一个十字架, 中间有一颗红色的', '宝石.'],['那个东西有什么用吗?'],['我本是这座塔守护者, 可不久前, ', '从北方来了一批恶魔, 他们占领了', '这座塔,并将我的魔力封在了这', '个十字架里面, 如果你能将它带出', '塔来, 那我的魔力便会慢慢地恢复, ', '到那时我便可以把力量借给你去', '救公主了. 要记住, 只有用我的魔力', '才可以打开二十一层的门.'],['......', '好吧,我试试看'],['刚才我去看过了, 你的剑被放在三', '楼, 你的盾在五楼上, 而那个十字', '架被放在七楼. 要到七楼, 你得', '先取回你的剑和盾. 另外在塔里的', '其他楼层上, 还有一些存放了好几百', '年的宝剑和宝物,如果得到它们,', '对于你对付这里面的怪物将有很大', '的帮助.'],['可是, 我怎么进去呢?'],['我这里有三把钥匙, 你先拿去, 在', '塔里面还有很多这样的钥匙, 你一', '定要珍惜使用. 勇敢的去吧,勇士!']]# 主循环clock = pygame.time.Clock()while True:screen.fill((0, 0, 0))screen.blit(self.background_images['gamebg'], (0, 0))self.map_parser.draw(screen)for scene in scenes:screen.blit(scene[0], scene[1])self.hero.draw(screen)# --按键检测for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()elif event.type == pygame.KEYDOWN:if event.key == pygame.K_SPACE:conversation_pointer += 1if conversation_pointer >= len(conversations): return# --画对话框conversation = conversations[conversation_pointer]font = pygame.font.Font(self.cfg.FONTPATH_CN, 20)# ----勇士if conversation_pointer % 2 == 0:left, top, width, height = 510, 430, 7, 2pygame.draw.rect(screen, (199, 97, 20), (left - 4, top - 4, self.cfg.BLOCKSIZE * width + 8, self.cfg.BLOCKSIZE * height + 8), 7)id_image = self.hero.images['down']# ----仙子else:left, top, width, height = 300, 250, 7, 2if len(conversation) > 3: height = 3if len(conversation) > 5: height = 4if len(conversation) > 7: height = 5pygame.draw.rect(screen, (199, 97, 20), (left - 4, top - 4, self.cfg.BLOCKSIZE * width + 8, self.cfg.BLOCKSIZE * height + 8), 7)id_image = pygame.image.load(self.cfg.MAPELEMENTSPATHS['24'][0])# ----底色filepath = self.cfg.MAPELEMENTSPATHS['0'][0]for col in range(width):for row in range(height):image = pygame.image.load(filepath)image = pygame.transform.scale(image, (self.cfg.BLOCKSIZE, self.cfg.BLOCKSIZE))screen.blit(image, (left + col * self.cfg.BLOCKSIZE, top + row * self.cfg.BLOCKSIZE))# ----左上角图标screen.blit(id_image, (left + 10, top + 10))# ----对话框中的文字for idx, text in enumerate(conversation):font_render = font.render(text, True, (255, 255, 255))rect = font_render.get_rect()rect.left, rect.top = left + self.cfg.BLOCKSIZE + 20, top + 10 + idx * 30screen.blit(font_render, rect)# --刷新pygame.display.flip()clock.tick(self.cfg.FPS)

具体的效果图如下:

接下来,我们需要实现的就是和怪物战斗的场景啦。按照原版游戏的设定,当勇士接触到地图上的怪物时,如果勇士可以击败该怪物,则自动触发战斗模式:

要实现这个功能,我们需要先定义地图上所有怪物的生命值,攻击力和防御力数值。具体而言,代码定义如下(数值全部来源于原游戏,收集起来可费劲了图片,别看代码就写了这么点):

# 地图上所有怪物的属性: 名字, 生命值, 攻击力, 防御力
self.monsters_dict = {'40': ('绿头怪', 50, 20, 1),'41': ('红头怪', 70, 15, 2),'42': ('小蝙蝠', 100, 20, 5),'43': ('青头怪', 200, 35, 10),'44': ('骷髅人', 110, 25, 5),'45': ('骷髅士兵', 150, 40, 20),'46': ('兽面人', 300, 75, 45),'47': ('初级卫兵', 450, 150, 90),'48': ('大蝙蝠', 150, 65, 30),'49': ('红蝙蝠', 550, 160, 90),'50': ('白衣武士', 1300, 300, 150),'51': ('怪王', 700, 250, 125),'52': ('红衣法师', 500, 400, 260),'53': ('红衣魔王', 15000, 1000, 1000),'54': ('金甲卫士', 850, 350, 200),'55': ('金甲队长', 900, 750, 650),'56': ('骷髅队长', 400, 90, 50),'57': ('灵法师', 1500, 830, 730),'58': ('灵武士', 1200, 980, 900),'59': ('冥灵魔王', 30000, 1700, 1500),'60': ('麻衣法师', 250, 120, 70),'61': ('冥战士', 2000, 680, 590),'62': ('冥队长', 2500, 900, 850),'63': ('初级法师', 125, 50, 25),'64': ('高级法师', 100, 200, 110),'65': ('石头怪人', 500, 115, 65),'66': ('兽面战士', 900, 450, 330),'67': ('双手剑士', 1200, 620, 520),'68': ('冥卫兵', 1250, 500, 400),'69': ('高级卫兵', 1500, 560, 460),'70': ('影子战士', 3100, 1150, 1050),'188': ('血影', 99999, 5000, 4000),'198': ('魔龙', 99999, 9999, 5000),
}

其中,字典的键值和第一期童年经典回忆 | 从零开始带大家撸一个魔塔小游戏呀(1)中定义地图的地图文件里的数字对应的地图元素的含义是一致的。接下来,为了实现和原版一样的功能,我们需要写个函数判断一下勇士当前的状态是否可以击败怪物:

'''判断勇士是否可以打赢怪物'''
def winmonster(self, monster):# 如果攻击力低于怪物防御力, monster: [名字, 生命值, 攻击力, 防御力]if self.attack_power <= monster[3]: return False# 如果防御力高于怪物攻击力if self.defense_power >= monster[2]: return True# 我方打怪物一次扣多少血diff_our = self.attack_power - monster[3]# 怪物打我方一次扣多少血diff_monster = monster[2] - self.defense_power# 计算谁可以winif round(monster[1] / diff_our) <= round(self.life_value / diff_monster):return Truereturn False

如果可以,则触发战斗场景。具体而言,我们已经做好了战斗的基础面板,每次只需要把对应的怪物、勇士以及他们各自的状态画上去即可,原理类似下图:


主要的代码实现如下:

'''战斗画面'''
def battle(self, monster, monster_image, map_parser, screen):monster = list(monster).copy()# 我方打怪物一次扣多少血diff_our = self.attack_power - monster[3]# 怪物打我方一次扣多少血diff_monster = monster[2] - self.defense_power# 更新战斗面板的频率update_count, update_interval, update_hero = 0, 10, False# 主循环clock = pygame.time.Clock()font = pygame.font.Font(self.cfg.FONTPATH_CN, 40)while True:screen.fill((0, 0, 0))screen.blit(self.background_images['gamebg'], (0, 0))map_parser.draw(screen)for scene in self.cur_scenes:screen.blit(scene[0], scene[1])self.draw(screen)# --按键检测for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()# --更新战斗面板update_count += 1if update_count > update_interval:update_count = 0if update_hero:self.life_value = self.life_value - (monster[2] - self.defense_power)else:monster[1] = max(monster[1] - (self.attack_power - monster[3]), 0)update_hero = not update_heroif monster[1] <= 0: returnscreen.blit(self.background_images['battlebg'], (20, 40))screen.blit(monster_image, (90, 140))font_renders = [font.render(str(monster[1]), True, (255, 255, 255)),font.render(str(monster[2]), True, (255, 255, 255)),font.render(str(monster[3]), True, (255, 255, 255)),font.render(str(self.life_value), True, (255, 255, 255)),font.render(str(self.attack_power), True, (255, 255, 255)),font.render(str(self.defense_power), True, (255, 255, 255)),]rects = [fr.get_rect() for fr in font_renders]for idx in range(3):rects[idx].top, rects[idx].left = 78 + idx * 95, 320for idx in range(3, 6):rects[idx].top, rects[idx].right = 78 + (idx - 3) * 95, 655for fr, rect in zip(font_renders, rects):screen.blit(fr, rect)# --刷新pygame.display.flip()clock.tick(self.cfg.FPS)

原理其实很简单,由我方的勇士先发起一次攻击,然后再由怪物发起一次攻击,以此类推,该过程中战斗面板实时更新当前勇士和怪物的状态。最终的效果如下图所示:
差不多又水到4千字了,那么本期就先到这啦

本期完整源代码可以在这里获取到:

公众号Python日志

下期内容应该会是本系列教程最有意思的一部分,即对战效果和对话效果以及一些物品提示的实现,大家可以多多关注,第一次时间看到相关的推文呀~

童年经典回忆 | 从零开始带大家用Python撸一个魔塔小游戏呀(3)相关推荐

  1. 童年经典回忆 | 从零开始带大家用Python撸一个魔塔小游戏呀(2)

    导语 上一期我们带大家完成了魔塔游戏每一层的初始化画面的制作: 童年经典回忆 | 从零开始带大家用Python撸一个魔塔小游戏呀(1) 这一期我们会带大家进一步复现我们的魔塔小游戏,主要内容包括英雄类 ...

  2. 童年经典回忆 | 从零开始带大家用Python撸一个魔塔小游戏呀(1)

    相关文件 相关游戏素材(图片和音频等)源于网络,侵歉删. 需要源代码的小伙伴私信小编,或者关注小编的公众号[Python日志] 开发工具 Python版本:3.7.4 相关模块: pygame模块: ...

  3. 玩过八音符游戏吗?今天教大家用python做一个八音符游戏

    先来看一下效果图: 需要用到的东西 Python3.6 cocos2d模块 pyaudio模块 以及一些Python自带的模块 cocos2d模块用于搭建游戏框架 pyaudio模块用于获得麦克风的声 ...

  4. 今天带大家用Python制作一个FlappyBird(飞翔的小鸟)的小游戏

    相关文件 源码分享,问题解答!! 关注小编,私信小编领取哟! 当然别忘了一件三连哟~~ 对了大家可以关注小编的公众号哟~~ 有很多资源可以领取的哟!! 大家也可以去b站看我的一些教学视频哟!! 更多P ...

  5. python自动填写小程序表单_新年好!教大家用Python写一个自动回复拜年信息的小程序!...

    原标题:新年好!教大家用Python写一个自动回复拜年信息的小程序! 过年期间,想必大家都收到很多拜年信息吧!有没有也被拜年短信(大部分是群发)搞得很焦虑?不回复似乎显得很没有礼貌,一一回复又累心劳神 ...

  6. python制作阴阳师脚本_利用python制作一个阴阳师小游戏

    利用python制作一个阴阳师小游戏 发布时间:2020-11-27 13:59:49 来源:亿速云 阅读:84 这期内容当中小编将会给大家带来有关利用python制作一个阴阳师小游戏,文章内容丰富且 ...

  7. Python游戏开发,Pygame模块,Python从零开始带大家实现一个魔塔小游戏

    开发工具 Python版本: 3.7.4 相关模块: pygame模块: 以及一些python自带的模块. 环境搭建 安装Python并添加到环境变量,pip安装需要的相关模块即可. 原理简介 首先, ...

  8. python连连看小游戏_利用Python制作一个连连看小游戏,边学边玩!

    导语 今天我们将制作一个连连看小游戏,让我们愉快地开始吧~ 开发工具 Python版本:3.6.4 相关模块: pygame模块: 以及一些Python自带的模块 环境搭建 安装Python并添加到环 ...

  9. 请用python编写一个斗地主小游戏,并给出完整代码

    很高兴为您服务!这是一个使用Python编写的斗地主小游戏的完整代码:# 导入必备模块 import random# 定义一副牌 poker = ['A', 2, 3, 4, 5, 6, 7, 8, ...

最新文章

  1. iOS scrollToItemAtIndexPath 无效的解决方案
  2. 【51CTO学院三周年】遇到
  3. const应用和作用
  4. Entity Framework
  5. [转]JS脚本抢腾讯云学生1元代金券
  6. java中void_关于java中void的用法?
  7. php是走什么协议,TCP是什么协议
  8. Latex 加空格的方法
  9. 充分掌握网络工作原理及底层实现 大家都做什么项目啊?
  10. POJ-3468-A Simple Problem with integers
  11. 3 步理清 Python 数据分析关键点,新手必看
  12. SpringMvc通过ajax完成上传到oss上
  13. 龙蜥社区第十次运营委员会议顺利召开!
  14. AI文件资源导出方法
  15. w7怎么修改计算机用户名,教您电脑用户名怎么修改
  16. 上海某马培训软件测试工程师第01期就业班课程
  17. Python 身体质量指数BMI
  18. 一个想法照进现实-《IT连》创业项目:创业时该不该用新手程序员
  19. 三星 scx-4021S 一体机 M2-1317错误怎么消除?
  20. 津津有味:你吃内脏吗?除了凳子腿儿,我什么都吃

热门文章

  1. 浅谈软件开发人员的职业发展规划
  2. 如何分离伴奏和人声?分享三个好用的软件
  3. QQ、暴风、迅雷去广告教程
  4. (UESTCOJ 1004)8球胜负(eight)
  5. 【sdx12】sdx12获取Serial Number操作方法及源码分享Serial Number的寄存器地址
  6. MOBILEYE: Vision-based ACC with a Single Camera
  7. 面向对象编程(以Java语言为例)
  8. 运营型CRM系统(运营型客户关系管理)只是针对于运营的吗?
  9. Matlab 2019b打开没有编辑器、发布和视图
  10. oracle asc 汉字,oracle中chr()和ascii()函数(附常用字符与ascii对照表)