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

小雁子学Python 2021-10-27 16:37:31
Python 游戏 开发 模块 pygame

前言

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

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

开发工具

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 += 1
if 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, 2
pygame.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, 2
if len(conversation) > 3: height = 3
if len(conversation) > 5: height = 4
if len(conversation) > 7: height = 5
pygame.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 * 30
screen.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
# 计算谁可以win
if round(monster[1] / diff_our) <= round(self.life_value / diff_monster):
return True
return 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 += 1
if update_count > update_interval:
update_count = 0
if 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_hero
if monster[1] <= 0: return
screen.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, 320
for idx in range(3, 6):
rects[idx].top, rects[idx].right = 78 + (idx - 3) * 95, 655
for fr, rect in zip(font_renders, rects):
screen.blit(fr, rect)
# --刷新
pygame.display.flip()
clock.tick(self.cfg.FPS)

原理其实很简单,由我方的勇士先发起一次攻击,然后再由怪物发起一次攻击,以此类推,该过程中战斗面板实时更新当前勇士和怪物的状态。最终的效果如下图所示:

在这里插入图片描述
本期完整源代码可以私信获取~

文章到这里就结束了,感谢你的观看,Python29个小游戏系列,下篇文章分享魔塔小游戏呀(4)

为了感谢读者们,我想把我最近收藏的一些编程干货分享给大家,回馈每一个读者,希望能帮到你们。

往期回顾

Python从零开始带大家实现一个魔塔小游戏(1)

Python从零开始带大家实现一个魔塔小游戏(2)

版权声明
本文为[小雁子学Python]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_43649691/article/details/120965377

  1. 【算法学习】237. 删除链表中的节点(java / c / c++ / python / go)
  2. 【算法学习】1672. 最富有客户的资产总量(java / c / c++ / python / go / rust)
  3. 【算法学习】771. 宝石与石头(java / c / c++ / python / go / rust)
  4. 【算法学习】02.03. 删除中间节点(java / c / c++ / python / go)
  5. 【算法学习】1769. 移动所有球到每个盒子所需的最小操作数(java / c / c++ / python / go / rust)
  6. 【算法学习】1486. 数组异或操作(java / c / c++ / python / go / rust)
  7. 【算法学习】LCP 44. 开幕式焰火(java / c / c++ / python / go / rust)
  8. 【算法学习】剑指 Offer 58 - II. 左旋转字符串(java / c / c++ / python / go / rust)
  9. python的学校疑问难题求解
  10. 大学python题 作业题 基础题
  11. Python字典的知识,输出的样例为,最高分:89
  12. python写入文件失败且程序提前中止
  13. 用Python写一个学生字典,帮帮忙
  14. Python,能不能帮帮忙,真的不会
  15. [python] yield 和 readline() 的使用问题
  16. python安装找不到问题救救孩子
  17. python中循环结构完成数字游戏
  18. 如何用python实现多列vlookup(excle操作)
  19. python语言deLong‘s test:通过统计学的角度来比较两个ROC曲线、检验两个ROC曲线的差异是否具有统计显著性
  20. LPC55S69 MicroPython模组和库函数
  21. LPC55S69 IoT Kit专属 Micropython模组和库函数简介
  22. 安装LPC55S69 MicroPython模块是遇到的CDC Interface驱动问题
  23. 使用soundcard在Python中操作声卡
  24. 自动化快速上手--Python(7)--【字典】--每天半小时
  25. Python之循环结构【包括列表、for语句、range()函数、while语句、循环嵌套、break、continue、算法优化等】
  26. Python模块安装与异常处理详解(numpy、pygame、matplotlib等)
  27. Python__init__.py作用
  28. python 爬取网页时出现多种错误
  29. Python中关于大量绘制速度曲线的问题
  30. python-async的安装和使用方法
  31. Matlab的fread(fild,1,int32)迁移到python变成什么
  32. 想用python开发一个音频过滤器,请指导?
  33. python使用openpyxl读取Excel文件显示No such file or directory
  34. xmoji虚拟头像交互如何使用python(像深度学习)制作?
  35. python 打开页面页面的链接,为什么总是报错呀?
  36. Python中DataLoader的batch_size、shuffle的疑惑。
  37. python安装pymssql库,可以import,但无法调用函数
  38. 【Python学习教程】常用的8个Python数据可视化库!
  39. python处理csv中的时间
  40. 数据结构,元音统计(Python)
  41. python的site-packages复制直接到其他电脑环境上能用吗
  42. Pycharm如何给项目配置python解释器
  43. conda创建python虚拟环境
  44. Python selenium的爬虫无法完整爬取整个页面的内容
  45. 高清版!这18张 Python 数据科学速查表,让你的代码变得更强大!
  46. python代码不会敲,请好心老哥帮助我一下
  47. Python敲七输出符合的个数
  48. Python 有人能给提供简单的思路嘛
  49. python单次运行写入csv成功,循环写入失败
  50. python利用os模块进行增量备份
  51. 【算法学习】807. 保持城市天际线(java / c / c++ / python / go / rust)
  52. 如何利用python输出等腰杨辉三角
  53. python按键执行倒计时小程序不能实现要求,要怎么改才好?
  54. Python request模块post请求的问题
  55. Django连接已有Oracle时的主键设置问题,没主键无法查询怎么办?
  56. 如何用python的dictionary编写一个联系人通讯录程序
  57. 如果Python里range反向输出,不输出步长会怎么样?
  58. 一个关于Python pip的问题: 出现Cannot open \python\Scripts\pip-script.py报错
  59. 富婆闺蜜非让我用Python给她写个淘宝双十一抢购脚本,那只能安排了
  60. 【全网最全】python正则表达式大全,所有讲解都在这,包教包会,学不会找我!