用 Cocos Creator 做一个物理画线游戏!支持 UGC 关卡创作和微信关卡分享

2024-01-09 08:30

本文主要是介绍用 Cocos Creator 做一个物理画线游戏!支持 UGC 关卡创作和微信关卡分享,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

引言:在 3D 跑酷游戏和 3D 三消游戏之后,本次孙二喵带来了一个 2D 物理画线游戏源码,使用 Cocos Creator 3.6.2 开发。源码见文末。

7380f7d1bfa90ea5f039a275e669f1b5.gif

演示效果

物理画线是一种比较经典的 2D 游戏玩法,这几年也出了一系列的爆款产品。本文将从立项、游戏逻辑和具体功能点的实现,来讲解如何基于 Cocos Creator 3.x 开发一款物理画线游戏,并实现 UGC 关卡创作和微信关卡分享。

立项与准备

游戏立项

游戏的核心玩法是玩家通过画线保护自己的小鸡,让其免受黑洞中掉下的障碍小鸡、或地图上的其他障碍伤害。

69f65d4bc107be8144d8cd817261bb8f.jpeg

游戏关卡

考虑到制作成本,游戏美术使用了简单的手绘风格,用 paletton 选择类似纸张的颜色,拖动色盘,把比较顺眼的方案保存起来,确定游戏整体的风格。

2a38e63b33b3f16f11c409da5fb940e2.jpeg

色板中用到的颜色统一可以使用圆角矩形缩到最小(比如 15px,就输出成 15+15+2=32px,预留2个 px 给九宫格拉伸用),游戏所有的 UI 框架加起来就只有几 KB,减少显存的同时,还可以提高加载速度。

6ecec98d005956e5bc02437d3711fced.jpeg

考虑到 spine 专业版数千元的价格,游戏内的动画效果统一使用了 Cocos 内置的动画编辑器+序列帧动画。序列帧动画使用 PS 制作,在画好我们的角色后,PS 内复制数个分组,调整角色的五官,输出序列帧,一些相似的做了剔除,减少动画的体积占用。

6ad8cc15c63ff68de5e4a213ea3eae03.jpeg

在 Cocos 内制作序列帧动画比较简单。帧动画使用30帧,新建好动画,并在精灵上面创建好动画组件,在对应的关键帧替换图片即可。

80be5c227d44f7012d8b52cb972ff358.jpeg

制作好的序列帧动画无需进行合并,拖入到一个文件夹内,使用 Cocos 自带的自动图集打包即可。

cb8d3925cf7feef5eecc3dd66153e074.jpeg

自定义网格背景

考虑到游戏的背景是一个纸上世界、同时需要支持 UGC 和简单的 AI,我们需要一个图片背景+网格。然而使用图片背景+网格图片不够灵活,同时做出来的效果会比较死板,缺少随机性,因此我从 shadertoy 上移植了一个纸张网格的效果。

原 shader 的 for 循环比较多,且风格比较写实,这里进行了一定的简化。

c1f33cbc54300ced6f9fd928fa9767ff.jpeg

这里把 shader 中常用的属性都进行了暴露,整体风格调整到和色卡一致。

c23ac73571b128fb6d2fa027215949c5.jpeg

游戏内的3个场景(游戏界面、游戏内、游戏编辑)都用到了这个 shader 的图片作为背景,这里使用精灵图自带的颜色 a_color 来控制网格颜色。

11fccb941201dcf9bf5e8097be68e63d.jpeg

并使用了简单的脚本接受全局事件,可以修改网格的颜色(这里只修改了透明度)。

78d74b652286a53a396d1d9cd8818fe7.jpeg

效果如下:

0932bf28f02b367f685f4ca2baa6a351.gif

考虑到游戏的 UGC 地图编辑需要使用到格子,Astar 网格导航也需要。以图片的视觉方向为例,下图左是在 shader 里 uv 的 xy 方向,下图右是 astar 算法的格子序号从小到大。

ea8bb17411384212e85c31442d789c9b.jpeg

所以我们需要在 shader 里对格子进行转换。

604798948c0a3c74227c210d78d23b59.jpeg

同时考虑到算法简单,这里不做屏幕分辨率的适配了,默认的设计分辨率是 750x1334,支持的最大显示高度是 750x2.2倍=1650(绝大多数全面屏手机的最大高度)。

uv 统一后,我们需要设置一下网格显示,默认黄色是安全区域坐标,表示可以放置物体或者有物体,红色是危险区域,表示不可以放置物体。

a54fbfa1b007d0b7b4e014a4e5cc77a3.jpeg

定义好颜色和颜色的顺序,在 shader 中使用简单的 aabb 四个方向进行判断,在范围内的就会把颜色改成黄色安全色或者红色警告色。

56749dc4801da5b380b55685e122048e.jpeg

同时 shader 把 worley 褶皱效果也加进材质的宏里,方便自定义开关。

36d85dd7515aa2d338f8379d68356d14.jpeg

如果需要使用自己的图片作为背景,可以打开 Use_Texture 的宏,使用 750x1650 的背景拖即可。

有了上述的准备工作,我们就可以开始地图编辑器的制作了。

地图编辑

在地图编辑之前,我们先确定整体的网格大小为75像素,设计的最大分辨率是 750x1650,也就是 10x22 个格子,这里定义一个全局的 class 去记录下这些配置。

272cb781a1e80b5d4bab129dec659a82.jpeg

每个物品的格子数量,可以用物体的图片长和宽分别除以75,然后四舍五入。

bce26cf66e915e9975e29464049d53a3.jpeg

如尖刺,是 60x148 分辨率,正好是 1*2 个格子

这部分数据我们在初始化物体时候会提前处理,避免重复计算。

fcff2e93451ebdd6f0ac26acf2596e6b.jpeg

接下来根据格子的奇数或者偶数决定落点的位置,可以分为 x 和 y 两周轴向分开处理。

如果是偶数就不需要做偏移,在格子中间落点即可,如果是奇数,需要偏移1个格子单位,同时偶数的格子用 Math.floor 求最小的整数格子,奇数用 Math.round 四舍五入求最近的格子。

e7666b0c081342b7b27471b0bdf01ca4.jpeg

检测上使用了 map 做查询,当检测到数据时候我们要把有碰撞的格子范围乘0.1,这样格子的 x 范围从 0-10,变成了 0-1,y 范围从 0-22,变成了 0-2.2,正好和我们 shader 的 uv 对应(shader 内部对原始的 uv.y 也乘了2.2,并不是 0-1了)。

3eac7e1e27db8c407b553e9090a30728.jpeg

当我们检测到碰撞体时候,当前物体的周围就会变红,存在碰撞体的周围位置会表黄。

游戏内定义了几种物体的名字的枚举,当他们的名字一致时候,初始化时候就会标记为是画线工具,删除工具或者旋转工具,当使用这些工具检测到结果时候,就会对选中物体标亮并进行对应操作。

当保存关卡时候,我们只需要记录物件的格子开始和结束范围,也就是之前 map 保存的数据,同时记录物件的 scale.x 和 scale.y 记录左右和上下方向的旋转,保存为 json 数据,再把 json 数据 Stringify 即可。

3571f7a271243066216eb4e42210090d.jpeg

在地图编辑器和游戏内读取关卡都采用相同的逻辑,如果是 runtime 时候,我们会顺便初始化一下 Astar Graph 里的网格权重。

5d09ad29263c64d21eabbadd2bee1a69.jpeg

这样即便是在复杂的关卡中,障碍小鸡也可以精准定位我们的游戏角色。

513691a5ac2e4acfc84ad01a3119c36b.gif

玩法核心逻辑

画线算法

下面介绍游戏的核心逻辑部分。

游戏的核心逻辑是使用 Graphics 画线,并把画线的路径点记录下来,同时我们的地图编辑器也会使用到这个功能来画辅助线。

这里使用了曼哈顿距离来记录移动的距离。当距离大于设定值,我们就会存储一次路径点,同时使用 graphics 绘制一次路径。

82606c437fe269df82367c2ac011bf32.jpeg

游戏环境和编辑器环境使用了不同的长度设置,编辑器会更短,来保证储存的关卡长度足够小。

画线的第一个点,我们使用了开销最低的 testPoint,记录是否存在碰撞体。第二个点开始,从上个点到当前点发射一条射线进行检测。

48181a2de48c3c65007d613811e5085f.jpeg

需要注意的是,这里的坐标点需要使用物体的世界坐标。

当画线结束,就可以根据路径点去生成碰撞体。这里直接使用了 polygon 多边形生成碰撞体,已经生成的碰撞体在关卡开始的时候,会回收使用到的 vec2 类,减少 GC。

我们首先把每2个点连成一条线,再对比每条线之间方向向量的斜率。考虑到性能,这里没有使用三角函数,斜率在一定范围内,就判断为是平行的,只会去推第二条线的最后一个点。

8b9817b24c2f6ae2ba12e508330a37bb.jpeg

这样我们参与计算的路径点就可以减少 30%-40%,我们用优化过的路径点再来算需要生成的 polygon 多边形,这里把起始点定为1,结束点定为2,其他中间点是0。

先计算出2个点之前的方向向量。

6203bc293196cdd8f680e5eb6cd07cb1.jpeg

再计算方向向量上,2个垂直方向的向量,分别乘以我们线段一半的宽度,最后起始点和结束点分辨加上这2个向量,就可以得到3个或者4个路径点,可以构建出一个三角形或者平行四边形(考虑到起始点和结束点可能贴边,这里使用了三角形,避免碰撞冲突的修正)。

生成了多边形的路径点后,我们需要额外 apply() 一下,我们所有的 vec2 都从 VecPool 单例内存储,减少 GC。

这里额外支持了 Graphic 的自定义材质,玩家可以在游戏内更换画笔的颜色。

163cda5fb668fcf66fda4d07bd58b8ab.jpeg

我们把材质的颜色和材质名在入口脚本里进行配置,商店和 gameplay 根据配置进行加载即可。

ad3468c6750f4da2a0ed9fb998b5a351.jpeg

感谢社区大佬的 Shader~

419507f9bf5e06c00927fad82f968505.gif

状态机

画好线后,就可以通知障碍出发去攻击我们的角色了。

411bc96f0440b33d0928e2a247e69cff.jpeg

这里使用了 Cocos 原本的 update,当切换状态时候会先执行 onEnter 方法,再执行 onUpdate 方法,这里可以把当前状态和之前状态传入,方便做逻辑切换,这里会记录下 dt 和 duration 时长,方便继承状态机的类使用。

小黑子的 AI 继承了 FSM 状态机,整个状态比较简单,只有寻路和攻击两个状态。

7fde549bfddc4e08adeccf39345aacf5.jpeg

寻路阶段使用了 Astar 算法,每找到一个路径点,就会向下一个路径点前进,寻路时候会使用人物的方向向量乘以一定距离,来检测是否存在物理画线。

20b8ee26b2d6875c6518b22acf0c2d11.jpeg

当检测到物理画线的时候就会对物理画线的 rigidbody2d 进行攻击,对 rigidbody2d 施加速度向量,就可以出现线条被抬起来的行为了。

64fd2d4f444002f1622ee0cf96567d59.jpeg

我们会在 x 方向上做左右的随机,y 方向以向上围住,也会随机一定的数值。

39aeaca52e96278cdf7efb080664349b.gif

小鸡的状态机就相对比较简单,只有基本的碰撞检测,当检测到危险的碰撞体就会触发受伤然后游戏失败。

cb8df6b33de474d21d0a86c6428ec3d8.jpeg

寻路导航

这里使用到了和之前 EasyNavmesh 同款的 A* 导航算法,不同的是我们使用了一个单例进行管理。

6c2a7a77409b6223119921e777abfb97.jpeg

这里把 Astar 翻译成了 TS 版本,方法都加了强类型判断,同时把距离算法改成了曼哈顿距离。

fc7a7f0db72aa6270426962b010a2011.jpeg

游戏内 FSM 同样使用了曼哈顿距离,当我们的路径点走完,且离目标超过2个格子距离时候就会再次寻路一次。

558f732e2966264a94ce371822c27358.jpeg

到这里整个游戏大的逻辑就分解完了,下面介绍一下游戏关卡分享的逻辑。

关卡分享逻辑

游戏内拍照

游戏内把物体和 UI 分辨分成了 Default 和 UI_2D 分组,并创建了2个相机,Screencam 平时的可见分组为空,只有当拍照时候才能看到 Default 分组。

e1b6db8a4cfd6b7f12522399ff4a6e22.png

截图后一瞬间,我们会读取相机 RenderTexture 的像素点,并把角色的偏移量传进来,保证截图范围不会太大,同时保证相机对着角色不会出框。

b7134525477ddd23e3f49c8f0c11bbb8.gif

关卡分享逻辑

关卡分享并没有使用云服务器,这里使用了微信分享里的 query 参数,query 最大可以存储2048长度的 string(测试中4096也可以跑,担心部分手机可能存在兼容问题,这里最大设置成了2046)。

ecf81652af4de5b1801f4668516c290e.jpeg

我们在分享时候可以把当前关卡都转换成 string,放到 query 里。

665a3ff7e7f03c9d58782fe216d3140f.jpeg

当我们分享给其他玩家,其他玩家打开后,在游戏初始化和微信 onshow 时候就会检测到是否有对应的 query。

微信的 getLaunchOption 是第一次进入游戏时候会有的,wx.onShow 是后台切换回来触发的时间,当检测到 query 且 query 内的关卡数据有效,就可以初始化这个关卡了。

d49000b59697d4995accf41541260411.jpeg

游戏内显示好友 UGC 关卡效果:

2a7aba87fe194d9146731bbdc2871ace.gif

资源链接

  • 源码下载:

https://store.cocos.com/app/detail/4240

  • 在线体验:

http://learncocos.com/chick

  • 论坛专贴:

https://forum.cocos.org/t/topic/142673

demo 源码现已发布到 Cocos Store,希望可以对大家有所帮助!如有疑问或者其他想交流的,欢迎移步论坛专贴。

往期精彩

d02b42314c3191892b8bb7f25589849b.png

34edce0f6bd47cf29774ac669b79dc45.png

60141ee0c52642f2dd3e7bf110c2f3cd.png126d398f83c5ec4895a7c2d12ba3c104.gif

这篇关于用 Cocos Creator 做一个物理画线游戏!支持 UGC 关卡创作和微信关卡分享的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/586504

相关文章

Python中你不知道的gzip高级用法分享

《Python中你不知道的gzip高级用法分享》在当今大数据时代,数据存储和传输成本已成为每个开发者必须考虑的问题,Python内置的gzip模块提供了一种简单高效的解决方案,下面小编就来和大家详细讲... 目录前言:为什么数据压缩如此重要1. gzip 模块基础介绍2. 基本压缩与解压缩操作2.1 压缩文

java向微信服务号发送消息的完整步骤实例

《java向微信服务号发送消息的完整步骤实例》:本文主要介绍java向微信服务号发送消息的相关资料,包括申请测试号获取appID/appsecret、关注公众号获取openID、配置消息模板及代码... 目录步骤1. 申请测试系统2. 公众号账号信息3. 关注测试号二维码4. 消息模板接口5. Java测试

Go语言代码格式化的技巧分享

《Go语言代码格式化的技巧分享》在Go语言的开发过程中,代码格式化是一个看似细微却至关重要的环节,良好的代码格式化不仅能提升代码的可读性,还能促进团队协作,减少因代码风格差异引发的问题,Go在代码格式... 目录一、Go 语言代码格式化的重要性二、Go 语言代码格式化工具:gofmt 与 go fmt(一)

k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)

《k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)》本文记录在K8s上运行的MySQL/MariaDB备份方案,通过工具容器执行mysqldump,结合定时任务实... 目录前言一、获取需要备份的数据库的信息二、备份步骤1.准备工作(X86)1.准备工作(arm)2.手

SQL Server修改数据库名及物理数据文件名操作步骤

《SQLServer修改数据库名及物理数据文件名操作步骤》在SQLServer中重命名数据库是一个常见的操作,但需要确保用户具有足够的权限来执行此操作,:本文主要介绍SQLServer修改数据... 目录一、背景介绍二、操作步骤2.1 设置为单用户模式(断开连接)2.2 修改数据库名称2.3 查找逻辑文件名

Python虚拟环境与Conda使用指南分享

《Python虚拟环境与Conda使用指南分享》:本文主要介绍Python虚拟环境与Conda使用指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、python 虚拟环境概述1.1 什么是虚拟环境1.2 为什么需要虚拟环境二、Python 内置的虚拟环境工具

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

华为鸿蒙HarmonyOS 5.1官宣7月开启升级! 首批支持名单公布

《华为鸿蒙HarmonyOS5.1官宣7月开启升级!首批支持名单公布》在刚刚结束的华为Pura80系列及全场景新品发布会上,除了众多新品的发布,还有一个消息也点燃了所有鸿蒙用户的期待,那就是Ha... 在今日的华为 Pura 80 系列及全场景新品发布会上,华为宣布鸿蒙 HarmonyOS 5.1 将于 7

Python基于微信OCR引擎实现高效图片文字识别

《Python基于微信OCR引擎实现高效图片文字识别》这篇文章主要为大家详细介绍了一款基于微信OCR引擎的图片文字识别桌面应用开发全过程,可以实现从图片拖拽识别到文字提取,感兴趣的小伙伴可以跟随小编一... 目录一、项目概述1.1 开发背景1.2 技术选型1.3 核心优势二、功能详解2.1 核心功能模块2.

如何基于Python开发一个微信自动化工具

《如何基于Python开发一个微信自动化工具》在当今数字化办公场景中,自动化工具已成为提升工作效率的利器,本文将深入剖析一个基于Python的微信自动化工具开发全过程,有需要的小伙伴可以了解下... 目录概述功能全景1. 核心功能模块2. 特色功能效果展示1. 主界面概览2. 定时任务配置3. 操作日志演示