news 2026/4/16 15:24:37

零基础:100个小案例玩转Python游戏开发!第三节:对对碰游戏(下)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
零基础:100个小案例玩转Python游戏开发!第三节:对对碰游戏(下)

在零基础:100个小案例玩转Python游戏开发!第三节:对对碰游戏(上)中,我们学会了游戏引擎的基本原理,并介绍了游戏界面和游戏场景的编辑,还学会了如何通过点击事件进行场景切换,下面我们来进行游戏战斗场景的制作。

本节内容需要先更新 PyMe至 1.5.4.8+ 版本

下载地址 : https://pyme.lanzoum.com/ivKAe3cps8he

在这个场景中,我们设置了两个层(GameLayer),背景(BG)层放置了一个棋盘背景图片,格子(Tile)层创建了一个二维网格,并让它左上角与棋盘内部的左上角对齐,有了这些格子,我们可以将图标填充在格子里,这样就可以方便的对齐和放置图标啦。

场景事件

选中图层Tile,然后在右上角面板中选择“事件响应”,这时会切换到图层的事件编辑列表,我们在左边可以看到以下事件:

  • Load:当前层加载完成

  • Update:每一帧更新时

  • Render:每一帧渲染时

  • Destroy:当前层被销毁时

  • PickDown:鼠标点击时

  • PickUp:鼠标抬起始

  • PickTile:鼠标点击到格子上时

  • ...其它事件

这些事件和之前我们做界面控件事件的用法类似,只需要双击右边“对应函数”栏位就可以进入到代码编辑器,在这里我们双击Load事件右边的对应函数栏位。

进入到代码编辑器中,会进入当前场景类的实现代码,光标停在函数on_Tile_Load,代表Tile层加载完成后调用的函数。

在PyMe中的游戏,主要依靠GameFun.py来提供所有的游戏引擎支撑,它的使用和开发软件时的Fun函数库类似,只不过GameFun是用于游戏的。我们可以花点时间看一下GameFun.py文件,找到GameScene和GameLayer类,分别了解它们有什么函数功能,这将有助于我们更加理解下面的工作。

比如,我们在这里需要获取到当前Tile层的格子信息,并将图片资源设置到格子里。

def on_Tile_Load(self): tileImages = ["bag","barrel","beans","bottle","eggplant","fire","flower","glove","grass","hat","house","kettle","milk","paling","peach","pot","shoe","shovel","straw","waterpipe"] tileResIndexDict = {} tileImageCount = len(tileImages) for i in range(tileImageCount): tileResIndexDict[i] = self.AddLayerResNode(tileImages[i]+".png") #先把要放置的图片的索引加入到一个列表中,每个图片索引必须为2的倍数 tileImageIndexList = [] TileLayer = self.GetLayer("Tile") TiledMap = TileLayer.GetGameNode(0) #因为图片索引必须为2的倍数,这里取一半行数,每一格子存两个相同的图片索引 HalfRows = TiledMap.Tile_Row // 2 for TileY in range(0,HalfRows): for TileX in range(0,TiledMap.Tile_Col): randNumber = GameFun.RandNumber(0,tileImageCount-1) tileImageIndexList.append(randNumber) tileImageIndexList.append(randNumber) #把有图片都放置完毕后,写个算法把tileImageIndexList打乱 tileImageIndexList = GameFun.Shuffle(tileImageIndexList) TileLayer = self.GetLayer("Tile") TiledMap = TileLayer.GetGameNode(0) for TileY in range(0,TiledMap.Tile_Row): for TileX in range(0,TiledMap.Tile_Col): TileIndex = TileY * TiledMap.Tile_Col + TileX ResIndex = tileImageIndexList[TileIndex] TiledMap.SetTileObject(TileX,TileY,tileResIndexDict[ResIndex])

在这段代码中,我们有一些重要的函数需要记一下:

  • AddLayerResNode:为场景加入资源并返回资源ID

  • GetLayer:取得当前场景中对应的GameLayer

  • GetGameNode:取得GameLayer中对应的GameNode,这里因为Tile层会创建一个TiledMap作为第一个GameNode,所以参数填0.

  • SetTileObject :为TiledMap的指定单元格设置对应的图片资源ID。

这就是运行的效果:

格子点击事件

没错,下面我们选中PickTile事件并双击“对应函数”栏位,将会进入到当前Tile层的格子被点选的事件函数:

具体代码如下:

def on_Tile_PickTile(self,tx,ty): TileLayer = self.GetLayer("Tile") TiledMap = TileLayer.GetGameNode(0) resID = TiledMap.GetTileObject(tx,ty) userData = TiledMap.GetUserData("last_tile") if userData: last_tx,last_ty = userData last_resID = TiledMap.GetTileObject(last_tx,last_ty) if last_resID == resID: TiledMap.DelTileObject(last_tx,last_ty) TiledMap.DelTileObject(tx,ty) TiledMap.SetUserData("last_tile",None) #如果格子为空 if TiledMap.IsEmpty() == True: UILayer = self.GetLayer("UI") UIInstance = UILayer.GetGameNode(0) Image_1 = UIInstance.GetChildByName("Image_1") Image_1.SetVisible(True) else: TiledMap.SetUserData("last_tile",[tx,ty]) else: TiledMap.SetUserData("last_tile",[tx,ty])

在这段代码中,我们也有一些重要的函数需要记一下:

  • GetUserData:取得属于GameNode的用户变量

  • SetUserData:为GameNode设置用户自定义变量

  • GetTileObject:取得TiledMap上的对应格子的元素资源ID

  • DelTileObject :为TiledMap的指定单元格删除图片资源ID

  • IsEmpty:判断TiledMap的格子是否都为空

果然,再次运行时,用鼠标点击两个相同的图标,就会清掉哦~

胜利与失败

当游戏开始后,如果我们能在指定时间内将图标都消除掉,就弹出胜利界面,如果没有在指定时间内将图标都消除掉,就弹出失败界面。我们可以双击进入Resources\UI文件夹,然后在文件资源栏中用鼠标右键点击空白处,通过弹出菜单创建界面BattleUI。

在BattleUI中,我们首先选中Form_1,设置显示样式为“空心”,这样可以不显示Form_1,然后从左边控件工具条拖动创建一个Image对象,并设置图片背景为胜利图片win.png,放置在中间,然后把“Hello,World"放置在顶部居中,修改文字内容为:“时间:100秒”,此时我们可以看到,Label文字显示为乱码,这是因为pygame的默认系统字体不支持中文,我们需要使用ttf字体来显示中文。

在字体属性栏中双击,然后在弹出字体编辑框中点击“导入TTF文件”,找到一个可用的ttf字体加入。

点击“打开”按钮,就可以在文字编辑框的“字体名称”下拉列表框中找到对应的TTF字体名称,选择它后点击“确定”按钮,这时后当前Label的字体就能够正常显示中文啦!

搞定界面后,返回游戏场景,创建一个UI层,然后在右下角导入界面BattleUI。

选中UI层,再选中BattleUI后在场景中点击一下,就可以创建出界面,并在下方的位置栏设置对齐0,0位置。

我们默认情况是不应该显示胜利图片的,所以回到BattleUI中将Image的显示属性设置为“隐藏”保存,并将倒计时文字改为黑色,使用平坦样式边框,设置透明度128,再次回到Battle场景,这时就只显示倒计时啦~

那么,下面我们要做的,就是为当前的UI层,在右上角双击Load和Update事件,分别在Load和Update中添加函数:

在这段代码中,重要的函数如下:

def on_UI_Load(self): import time starttime = time.time() self.SetUserData("second",100) self.SetUserData("time",starttime) def on_UI_Update(self): import time currtime = time.time() starttime = self.GetUserData("time") second = self.GetUserData("second") offsettime = currtime - starttime if offsettime > 1 and second > 0: UILayer = self.GetLayer("UI") UIInstance = UILayer.GetGameNode(0) #获取标题文字 Label_2 = UIInstance.GetChildByName("Label_2") second = second - 1 Label_2.SetText(str("时间: %d" %second)) if second <= 0 : #设置中间的图片为失败 Image_1 = UIInstance.GetChildByName("Image_1") Image_1.SetImage("Fail.png") Image_1.SetVisible(True) else: self.SetUserData("time",currtime) self.SetUserData("second",second)
  • GetChildByName:通过名称取得子节点

现在再次运行,已经可以看到倒计时的文字显示...呃,我有点后悔,开始时没有好好设计一下游戏的场景....

玩了一把,我得承认不是太容易。。。。

打包到手机上

在电脑上玩还是不如在手机上方便,所以我们可以选择打包为APK,在右上角先选一下Android模式,然后点击“发布”,这时提示说需要使用英文路径。。。。

我们先关闭项目返回项目管理界面,然后在“打开项目”页里右键单击,选择菜单项“工程另存为”,将其另存为“PMDDP”,这样就可以直接生成一个新的英文名项目了。

双击进入”PMDDP“项目,然后再次重新选择Android模式,并点击”发布“按钮,就可以打包成功了!

打包完成后,在当前工程上会生成PMDDP.apk。

我们将手机与电脑相连,并将APK安装到手机上。

现在看一下最终效果吧!

为什么PyMe是游戏开发入门神器?

经过这个项目的实践,相信您对于PyMe开发游戏的流程已经有所了解了,那我们来总结一下使用PyMe进行游戏开发的突出优点:

引擎支持
不用从零来写引擎渲染,直接基于工作流进行游戏开发。

工具强大
提供丰富的可视化编辑工具,使游戏开发工具流更加趋于商业游戏开发理念。

门槛较低
理解了基础的原理和事件函数编写方法,就可以上手开发,让游戏开发的门槛大大降底。

写在最后:编程也可以这么有趣

游戏开发最大的魅力在于:它让编程变成了创造世界的过程。每一行代码都是为这个世界添加新的规则,每一个函数都是赋予角色新的能力。

PyMe就像是我们手中的魔法棒,把抽象的代码变成了具象的体验。它降低了技术门槛,让我们这些初学者也能享受到创造的快乐。

所以,不要停下脚步!用PyMe继续创造更多有趣的游戏吧!无论是送给朋友当礼物,还是只是让自己开心,这都是编程带给我们的独特乐趣。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 9:23:01

12.17 脚本语言 kconfig详解

一&#xff0c;kconfig在linux驱动不可或缺&#xff0c;二&#xff0c;让我们一起来了解一下- - - &#xff0c;以下是官方文档翻译。<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewp…

作者头像 李华
网站建设 2026/4/16 11:05:52

EmotiVoice能否用于语音日记应用?私人化情绪记录

EmotiVoice能否用于语音日记应用&#xff1f;私人化情绪记录 在数字生活日益沉浸化的今天&#xff0c;人们不再满足于用文字或视频记录日常。越来越多用户开始寻求更私密、更具情感温度的方式来保存记忆——语音日记应运而生。它不像社交媒体那样追求曝光&#xff0c;而是强调“…

作者头像 李华
网站建设 2026/4/8 20:53:13

2025毕业论文AI工具实测:这款凭什么成为全程主力?

写论文的真正折磨&#xff1a;不是写不出&#xff0c;是工具选不对曾以为 AI 只是 “救急笔杆子”&#xff0c;直到真正扎进毕业论文的深海才发现&#xff1a;选题定方向、文献筛重点、正文保连贯、格式抠细节、引用核真伪…… 每个环节单独看不难&#xff0c;串起来却能把人磨…

作者头像 李华
网站建设 2026/4/16 11:04:13

小型房屋租赁|基于java+ vue小型房屋租赁系统(源码+数据库+文档)

小型房屋租赁 目录 基于springboot vue小型房屋租赁系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue小型房屋租赁系统 一、前言 博主介绍&…

作者头像 李华
网站建设 2026/4/15 21:10:07

医院设备|基于java + vue医院设备管理系统(源码+数据库+文档)

医院设备 目录 基于springboot vue医院设备系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue医院设备系统 一、前言 博主介绍&#xff1a;✌️大…

作者头像 李华