Python游戏开发之魔塔小游戏的实现
作者:Cooci 发布时间:2022-08-26 16:14:35
标签:Python,魔塔,游戏
前言
这一期我们继续完善我们的魔塔小游戏。
废话不多说,让我们愉快地开始吧~
开发工具
Python版本: 3.7.4
相关模块:
cpgames模块;
以及一些python自带的模块。
环境搭建
安装Python并添加到环境变量,pip安装需要的相关模块即可。
原理简介
本期我们实现一些之前还没实现的功能,以及做一些功能优化(部分内容为了测试方便,我会把人物设置成无敌状态)。首先,是拾取物品等游戏事件的提示效果,核心代码如下:
'''游戏事件提示'''
def showinfo(self, screen):
if self.obtain_tips is None: return
self.show_obtain_tips_count += 1
if self.show_obtain_tips_count > self.max_obtain_tips_count:
self.show_obtain_tips_count = 0
self.obtain_tips = None
# 画框
left, top = self.cfg.BLOCKSIZE // 2, 100
width, height = self.cfg.SCREENSIZE[0] // self.cfg.BLOCKSIZE - 1, 2
pygame.draw.rect(screen, (199, 97, 20), (left - 4, top - 4, self.cfg.BLOCKSIZE * width + 8, self.cfg.BLOCKSIZE * height + 8), 7)
for col in range(width):
for row in range(height):
image = self.resource_loader.images['mapelements']['0'][0]
image = pygame.transform.scale(image, (self.cfg.BLOCKSIZE, self.cfg.BLOCKSIZE))
screen.blit(image, (left + col * self.cfg.BLOCKSIZE, top + row * self.cfg.BLOCKSIZE))
# 文字
if isinstance(self.obtain_tips, list):
assert len(self.obtain_tips) == 2
font = pygame.font.Font(self.fontpath, 30)
font_render1 = font.render(self.obtain_tips[0], True, (255, 255, 255))
font_render2 = font.render(self.obtain_tips[1], True, (255, 255, 255))
rect1 = font_render1.get_rect()
rect2 = font_render2.get_rect()
rect1.midtop = left + width * self.cfg.BLOCKSIZE // 2, top + 10
rect2.midtop = left + width * self.cfg.BLOCKSIZE // 2, top + 10 + self.blocksize
screen.blit(font_render1, rect1)
screen.blit(font_render2, rect2)
else:
font = pygame.font.Font(self.fontpath, 40)
font_render = font.render(self.obtain_tips, True, (255, 255, 255))
rect = font_render.get_rect()
rect.midtop = left + width * self.cfg.BLOCKSIZE // 2, top + height * self.cfg.BLOCKSIZE // 2 - 20
screen.blit(font_render, rect)
效果:
'''显示商店'''
def showbuyinterface(self, screen, scenes, shop_type):
# 购买函数
def buy(hero, coins_cost=0, experience_cost=0, add_life_value=0, add_attack_power=0, add_defense_power=0, add_level=0, add_yellow_keys=0, add_purple_keys=0, add_red_keys=0):
if hero.num_coins < coins_cost: return
if hero.experience < experience_cost: return
if add_yellow_keys < 0 and hero.num_yellow_keys < 1: return
if add_purple_keys < 0 and hero.num_purple_keys < 1: return
if add_red_keys < 0 and hero.num_red_keys < 1: return
hero.num_coins -= coins_cost
hero.experience -= experience_cost
hero.life_value += add_life_value + 1000 * add_level
hero.attack_power += add_attack_power + 7 * add_level
hero.defense_power += add_defense_power + 7 * add_level
hero.level += add_level
hero.num_yellow_keys += add_yellow_keys
hero.num_purple_keys += add_purple_keys
hero.num_red_keys += add_red_keys
# 选项定义
# --第三层商店
if self.map_level_pointer == 3 and shop_type == 'buy_from_shop':
choices_dict = {
'增加 800 点生命(25 金币)': lambda: buy(self.hero, coins_cost=25, add_life_value=800),
'增加 4 点攻击(25 金币)': lambda: buy(self.hero, coins_cost=25, add_attack_power=4),
'增加 4 点防御(25 金币)': lambda: buy(self.hero, coins_cost=25, add_defense_power=4),
'离开商店': lambda: buy(self.hero),
}
id_image = self.resource_loader.images['mapelements']['22'][0]
# --第十一层商店
elif self.map_level_pointer == 11 and shop_type == 'buy_from_shop':
choices_dict = {
'增加 4000 点生命(100 金币)': lambda: buy(self.hero, coins_cost=100, add_life_value=4000),
'增加 20 点攻击(100 金币)': lambda: buy(self.hero, coins_cost=100, add_attack_power=20),
'增加 20 点防御(100 金币)': lambda: buy(self.hero, coins_cost=100, add_defense_power=20),
'离开商店': lambda: buy(self.hero),
}
id_image = self.resource_loader.images['mapelements']['22'][0]
# --第五层神秘老人
elif self.map_level_pointer == 5 and shop_type == 'buy_from_oldman':
choices_dict = {
'提升一级(100 经验)': lambda: buy(self.hero, experience_cost=100, add_level=1),
'增加 5 点攻击(30 经验)': lambda: buy(self.hero, experience_cost=30, add_attack_power=5),
'增加 5 点防御(30 经验)': lambda: buy(self.hero, experience_cost=30, add_defense_power=5),
'离开商店': lambda: buy(self.hero),
}
id_image = self.resource_loader.images['mapelements']['26'][0]
# --第十三层神秘老人
elif self.map_level_pointer == 13 and shop_type == 'buy_from_oldman':
choices_dict = {
'提升 * (270 经验)': lambda: buy(self.hero, experience_cost=270, add_level=1),
'增加 17 点攻击(95 经验)': lambda: buy(self.hero, experience_cost=95, add_attack_power=17),
'增加 17 点防御(95 经验)': lambda: buy(self.hero, experience_cost=95, add_defense_power=17),
'离开商店': lambda: buy(self.hero),
}
id_image = self.resource_loader.images['mapelements']['26'][0]
# --第五层商人
elif self.map_level_pointer == 5 and shop_type == 'buy_from_businessman':
choices_dict = {
'购买 1 把黄钥匙(10 金币)': lambda: buy(self.hero, coins_cost=10, add_yellow_keys=1),
'购买 1 把蓝钥匙(50 金币)': lambda: buy(self.hero, coins_cost=50, add_purple_keys=1),
'购买 1 把红钥匙(100 金币)': lambda: buy(self.hero, coins_cost=100, add_red_keys=1),
'离开商店': lambda: buy(self.hero),
}
id_image = self.resource_loader.images['mapelements']['27'][0]
# --第十二层商人
elif self.map_level_pointer == 12 and shop_type == 'buy_from_businessman':
choices_dict = {
'卖出 1 把黄钥匙(7 金币)': lambda: buy(self.hero, coins_cost=-7, add_yellow_keys=-1),
'卖出 1 把蓝钥匙(35 金币)': lambda: buy(self.hero, coins_cost=-35, add_purple_keys=-1),
'卖出 1 把红钥匙(70 金币)': lambda: buy(self.hero, coins_cost=-70, add_red_keys=-1),
'离开商店': lambda: buy(self.hero),
}
id_image = self.resource_loader.images['mapelements']['27'][0]
id_image = pygame.transform.scale(id_image, (self.cfg.BLOCKSIZE, self.cfg.BLOCKSIZE))
# 主循环
clock, selected_idx = pygame.time.Clock(), 1
font = pygame.font.Font(self.cfg.FONT_PATHS_NOPRELOAD_DICT['font_cn'], 20)
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:
QuitGame()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
list(choices_dict.values())[selected_idx-1]()
if selected_idx == 4: return
elif event.key == pygame.K_w or event.key == pygame.K_UP:
selected_idx = max(selected_idx - 1, 1)
elif event.key == pygame.K_s or event.key == pygame.K_DOWN:
selected_idx = min(selected_idx + 1, 4)
# --对话框
# ----底色
width, height = 8, 3
left, bottom = self.hero.rect.left + self.hero.rect.width // 2 - width // 2 * self.cfg.BLOCKSIZE, self.hero.rect.bottom
for col in range(width):
for row in range(height):
image = self.resource_loader.images['mapelements']['0'][0]
image = pygame.transform.scale(image, (self.cfg.BLOCKSIZE, self.cfg.BLOCKSIZE))
screen.blit(image, (left + col * self.cfg.BLOCKSIZE, bottom + row * self.cfg.BLOCKSIZE))
# ----边框
pygame.draw.rect(screen, (199, 97, 20), (left - 4, bottom - 4, self.cfg.BLOCKSIZE * width + 8, self.cfg.BLOCKSIZE * height + 8), 7)
# ----展示选项
for idx, choice in enumerate(['请选择:'] + list(choices_dict.keys())):
if selected_idx == idx and idx > 0:
choice = '➤' + choice
font_render = font.render(choice, True, (255, 0, 0))
elif idx > 0:
choice = ' ' + choice
font_render = font.render(choice, True, (255, 255, 255))
else:
font_render = font.render(choice, True, (255, 255, 255))
rect = font_render.get_rect()
rect.left, rect.top = left + self.cfg.BLOCKSIZE + 20, bottom + 10 + idx * 30
screen.blit(font_render, rect)
# ----展示头像
screen.blit(id_image, (left + 10, bottom + 10))
# --刷新
pygame.display.flip()
clock.tick(self.cfg.FPS)
即,商店主要包括三种类型:一种的明面上的商店,用金币进行交易,可以获得生命值、攻击力和防御力的提升;一种是商人,用金币进行交易,可以获得/出售不同颜色的钥匙;还有一种是神秘老人,用经验值进行交易,可以获得等级、攻击力和防御力的提示。效果如下
接着,我们来实现一下地图中可以捡到的一些宝物的特效,主要包括风之罗盘、圣光徽、星光神榔和幸运十字架。
其中,风之罗盘用于在已经走过的楼层间进行跳跃,代码实现如下:
'''显示关卡跳转'''
def showjumplevel(self, screen, scenes):
# 主循环
clock, selected_level = pygame.time.Clock(), 1
font = pygame.font.Font(self.cfg.FONT_PATHS_NOPRELOAD_DICT['font_cn'], 20)
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:
QuitGame()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
return selected_level
elif event.key == pygame.K_w or event.key == pygame.K_UP:
selected_level = max(selected_level - 1, 0)
elif event.key == pygame.K_s or event.key == pygame.K_DOWN:
selected_level = min(selected_level + 1, self.max_map_level_pointer)
# --对话框
# ----底色
width, height = 11, 4
left, top = self.cfg.SCREENSIZE[0] // 2 - width // 2 * self.cfg.BLOCKSIZE, self.cfg.SCREENSIZE[1] // 2 - height * self.cfg.BLOCKSIZE
for col in range(width):
for row in range(height):
image = self.resource_loader.images['mapelements']['0'][0]
image = pygame.transform.scale(image, (self.cfg.BLOCKSIZE, self.cfg.BLOCKSIZE))
screen.blit(image, (left + col * self.cfg.BLOCKSIZE, top + row * self.cfg.BLOCKSIZE))
# ----边框
pygame.draw.rect(screen, (199, 97, 20), (left - 4, top - 4, self.cfg.BLOCKSIZE * width + 8, self.cfg.BLOCKSIZE * height + 8), 7)
# ----展示选项
for idx in list(range(self.max_map_level_pointer+1)):
if selected_level == idx:
text = f'➤第 {idx} 层'
font_render = font.render(text, True, (255, 0, 0))
else:
text = f' 第 {idx} 层'
font_render = font.render(text, True, (255, 255, 255))
rect = font_render.get_rect()
rect.left, rect.top = left + 20 + idx // 6 * self.cfg.BLOCKSIZE * 2, top + 20 + (idx % 6) * 30
screen.blit(font_render, rect)
# --刷新
pygame.display.flip()
clock.tick(self.cfg.FPS)
效果:
然后是圣光徽,用于查看怪物的基本情况,代码实现如下:
'''显示关卡怪物信息'''
def showforecastlevel(self, screen, scenes):
# 主循环
clock = pygame.time.Clock()
font = pygame.font.Font(self.cfg.FONT_PATHS_NOPRELOAD_DICT['font_cn'], 20)
monsters = self.map_parser.getallmonsters()
if len(monsters) < 1: return
monsters_show_pointer, max_monsters_show_pointer = 1, round(len(monsters) / 4)
show_tip_text, show_tip_text_count, max_show_tip_text_count = True, 1, 15
return_flag = False
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:
QuitGame()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_l:
return_flag = True
elif event.key == pygame.K_SPACE:
monsters_show_pointer = monsters_show_pointer + 1
if monsters_show_pointer > max_monsters_show_pointer: monsters_show_pointer = 1
elif event.type == pygame.KEYUP:
if event.key == pygame.K_l and return_flag:
return
# --对话框
# ----底色
width, height = 14, 5
left, top = self.cfg.SCREENSIZE[0] // 2 - width // 2 * self.cfg.BLOCKSIZE, self.cfg.SCREENSIZE[1] // 2 - height * self.cfg.BLOCKSIZE
for col in range(width):
for row in range(height):
image = self.resource_loader.images['mapelements']['0'][0]
image = pygame.transform.scale(image, (self.cfg.BLOCKSIZE, self.cfg.BLOCKSIZE))
screen.blit(image, (left + col * self.cfg.BLOCKSIZE, top + row * self.cfg.BLOCKSIZE))
# ----边框
pygame.draw.rect(screen, (199, 97, 20), (left - 4, top - 4, self.cfg.BLOCKSIZE * width + 8, self.cfg.BLOCKSIZE * height + 8), 7)
# ----展示选项
for idx, monster in enumerate(monsters[(monsters_show_pointer-1)*4: monsters_show_pointer*4]):
id_image = self.resource_loader.images['mapelements'][monster[6]][0]
id_image = pygame.transform.scale(id_image, (self.cfg.BLOCKSIZE - 10, self.cfg.BLOCKSIZE - 10))
screen.blit(id_image, (left + 10, top + 20 + idx * self.cfg.BLOCKSIZE))
text = f'名称: {monster[0]} 生命: {monster[1]} 攻击: {monster[2]} 防御: {monster[3]} 金币: {monster[4]} 经验: {monster[5]} 损失: {self.hero.winmonster(monster)[1]}'
font_render = font.render(text, True, (255, 255, 255))
rect = font_render.get_rect()
rect.left, rect.top = left + 15 + self.cfg.BLOCKSIZE, top + 30 + idx * self.cfg.BLOCKSIZE
screen.blit(font_render, rect)
# ----操作提示
show_tip_text_count += 1
if show_tip_text_count == max_show_tip_text_count:
show_tip_text_count = 1
show_tip_text = not show_tip_text
if show_tip_text:
tip_text = '空格键'
font_render = font.render(tip_text, True, (255, 255, 255))
rect.left, rect.bottom = self.cfg.BLOCKSIZE * width + 30, self.cfg.BLOCKSIZE * (height + 1) + 10
screen.blit(font_render, rect)
# --刷新
pygame.display.flip()
clock.tick(self.cfg.FPS)
效果:
然后我们来实现一下幸运十字架,把它交给序章中的仙子,可以将自身的所有能力提升一些(攻击防御和生命值)。
# 定义所有对话
if self.hero.has_cross:
conversations = [
['仙子, 我已经将那个十字架找到了.'],
['你做得很好. 那么现在我就开始', '授予你更强的力量! 咪啦哆咪哔...', '好了, 我已经将你现在的能力提升了!', '记住: 如果你没有足够的实力的话,', '不要去第二十一层. 在那一层里,', '你所有宝物的法力都会失去作用.']
]
self.hero.has_cross = False
self.hero.life_value = int(self.hero.life_value * 4 / 3)
self.hero.attack_power = int(self.hero.attack_power * 4 / 3)
self.hero.defense_power = int(self.hero.defense_power * 4 / 3)
来源:https://segmentfault.com/a/1190000041384376


猜你喜欢
- 本文实例讲述了python使用正则表达式分析网页中的图片并进行替换的方法。分享给大家供大家参考。具体分析如下:这段代码分析网页中的所有图片表
- 言MySQL 8.0 从第一版release 到现在已经走过了4个年头了,8.0版本在功能和代码上做了相当大的改进和重构。和DBA圈子里的朋
- APScheduler简介在平常的工作中几乎有一半的功能模块都需要定时任务来推动,例如项目中有一个定时统计程序,定时爬出网站的URL程序,定
- 写这段代码的原因是昨天项目中遇到的一个问题。一同事要求 写一个效果要求鼠标掠过表格行该行颜色改变以突出显示。这个倒不难,那哥们直接为每个Tr
- 1. 新建.py文件# pip install kafka-pythonfrom kafka import KafkaConsumerimp
- 往mysql数据库中插入数据。以前常用INSERT INTO 表名 (列名1,列名2…) VALUES(列值1,列值2);如果在PHP程序中
- 本文实例讲述了Python开发SQLite3数据库相关操作。分享给大家供大家参考,具体如下:'''SQLite数据库
- 通常我们在制作上图的时候,会分别给四个div加上不同的css属性,来实现中间间隔。但我们更希望的是不需要对html标签做标识,直接能通过cs
- 女友让我给她论文的图片上加上字母序号,本来觉得是个很简单的事情,但那个白底黑字的圆圈序号却难住了我, 试了几个常用的软件,都不行。后来用 P
- 本文实例为大家分享了python学生信息管理系统的具体代码,供大家参考,具体内容如下#编译环境为python3 #学生信息管理系统包括基本的
- 我们先简单的了解一些http的知识,从而理解该协议的无状态特性。然后,学习一些关于cookie的基本操作。最后,我会一步步阐述如何使用一些简
- 在写 Python 代码的时候,一个很好的编码实践就是使得你的代码简洁,易懂。组织代码,设置变量,以及给函数有意义的名字,都是几个不错的方法
- 1、代码from aip import AipFaceimport cv2import timeimport base64from PIL
- 一、条件语句条件语句能够改变Python程序的执行流程,是执行这个代码块还是另一个代码块。凡是需要判断来确定下一步如何执行的程序都要使用条件
- 安装一些必要的环境1.下载go sdk (本人装的是1.9) 2.下载golang3.下载git 因为有些依赖 要用 go get 去git
- 目录1.用途2.语法3.实操1.用途通常,如果发生错误,脚本就会立即停止,并在控制台将错误打印出来。有了这个语句就可以捕获错误并执行合理操作
- 1. 一些常用的 MySQL 命令#连接MySQLmysql -h 127.0.0.1 -u UserName -p pwd -
- 先来看一下效果吧,只要有足够的照片素材,捕获女神的心就指日可待怎么样,看起来还可以吧下面就一起来完成吧数据准备首先是测试图片的获取,毕竟萝卜
- 本文实例为大家分享了Python实现24点小游戏的具体代码,供大家参考,具体内容如下玩法:通过加减乘除操作,小学生都没问题的。源码分享:im
- 本文实例为大家分享了python实现简单tftp的具体代码,供大家参考,具体内容如下tftp是基于udp的协议实现简单的tftp,首先要有t