《Cocos 游戏开发入门》14.3 经济与掉落表
击杀之后掉什么、掉多少、连掉十次不出稀有怎么办?本节为 mini2d 搭一套掉落系统:用权重表表达概率、上线前算清期望值、用保底机制兜住坏运气,并讲清伪随机与真随机的取舍与可复现的种子 PRNG;末节对照 Cocos Creator 3.8 的 math.randomRange 与随机整数 API。
tag
击杀之后掉什么、掉多少、连掉十次不出稀有怎么办?本节为 mini2d 搭一套掉落系统:用权重表表达概率、上线前算清期望值、用保底机制兜住坏运气,并讲清伪随机与真随机的取舍与可复现的种子 PRNG;末节对照 Cocos Creator 3.8 的 math.randomRange 与随机整数 API。
技能不该是一坨 if-else。本节为 mini2d 拆出「效果」原子——伤害、加速、无敌、吸附——用生命周期钩子与叠加规则把它们组合成技能,再用一份 JSON 配置表驱动,让策划改数值不必改代码;末节对照 Cocos Creator 3.8 的 JsonAsset 与 resources.load 加载配置。
同一份《方块冲刺》产物要发到三个目标:H5、微信小游戏、原生。本节先对照三端的包体与能力约束,再分别给出 H5 的静态托管与 CDN 缓存策略、微信小游戏 4MB 首包限制下的分包方案、原生 WebView 壳与平台 API 桥接,最后写一层纯 TS 平台抽象把差异收敛到一处。
《方块冲刺》里伤害、治疗、状态变更散落各处即时生效,谁先执行谁就赢,顺序一抖动就出双杀与负血量。本节为 mini2d 写一条结算管线:把变更入队、按优先级与序列号确定性排序、同一帧内统一 flush,再用事件冒泡串起受击、死亡与掉落;末节对照 Cocos Creator 3.8 的 Node.emit 与 executionOrder。
敌人会寻路了,关卡却还是手画的。本节把《方块冲刺》的关卡抽成 JSON:字段设计、加载校验、随机种子保证可复现;再用约束满足生成「必定可通关」的关卡,用随距离递增的障碍密度做难度曲线;末节对照 Cocos Creator 3.8 的 TiledMap 与 Sprite 装配。
玩家报的「偶发 bug」怎么变成一条测试?本节讲确定性回放:把每帧输入位录成可序列化序列,用固定随机种子消灭不确定性,再逐帧喂回固定步长,把一个 bug 复现写成回归用例;末节诚实交代 Cocos Creator 3.8 里能测什么、为何整局回放做不到。
上一节的敌人会追玩家,但会一头撞在墙上。本节为 mini2d 手写网格 A*:开放集与关闭集、g/h/f 三份代价、可替换的启发函数;再讲路径平滑与导航网格的简化思路;末节对照 Cocos Creator 3.8 的 TiledMap / TiledLayer,把地图格子读成寻路输入。
单测证明逻辑对,却证明不了画面对。本节把《方块冲刺》搬进无头浏览器:用 vite 打单文件 bundle,用确定性入口 renderAt(stepCount) 保证同一步数同一张图,讲清 waitUntil: 'networkidle' 为何必需,并用像素采样与页面错误断言补上端到端这一环。
把《方块冲刺》从源码变成可发布的 bundle:用 vite.config.ts 配好 assetsInlineLimit、cssCodeSplit 与按需拆包,再写一个 Node 脚本把 dist 目录按代码/图片/音频/数据分类统计体积,用 zlib 预估 gzip 后大小,最后把体积预算做成 CI 门禁,超限即失败。
逻辑对不等于画面对,但逻辑错一定全盘皆错。本节用 FakeTime 假时钟与固定步长,把《方块冲刺》的核心逻辑变成可断言事实:1 秒恰好 59 步、死亡螺旋上限 5 步、重力落地停在 y=40、金币只吃一次,再用 RecordingRenderer 断言绘制序列,最后说明 Cocos 脚本为何难单测。
上一章的 StateMachine 管的是游戏阶段,这一章要管的是敌人。本节先给《方块冲刺》的追击怪手写 FSM:状态、转移、条件三者分离;再写一棵行为树,用选择/顺序/装饰/叶子四类节点把行为拆成可组合的积木,最后给出两套方案在同一只敌人身上的取舍对照。
玩家在手机和电脑各存了一份进度,两份对不上怎么办?本节为 mini2d 抽象统一的存储接口,用时间戳、版本与校验和检测本地/云端冲突,实现本地优先、云端优先、逐字段合并三种策略,并给出可解释的提示;末节对照 Cocos Creator 3.8 的 sys.platform 与平台存储差异。
存档是玩家最舍不得丢的数据,但字段会随版本增删。本节为 mini2d 设计带版本号的存档结构,实现 v1→v2→v3 的迁移函数链、字段增删的兼容策略,以及校验和损坏恢复;末节对照 Cocos Creator 3.8 的 sys.localStorage 读写与 JSON 序列化。
《方块冲刺》跑起来了,但加载、主菜单、游戏、暂停、结算全靠布尔标志拼凑。本节为 mini2d 写一个状态机:统一的进入/退出钩子、状态栈做暂停恢复、用转移表挡住非法跳转;末节对照 Cocos Creator 3.8 的 director 场景切换与 game 前后台事件。
资源拉进来了,还得知道什么时候放它走:用引用计数跟踪谁在用一份资源,实现 retain/release 与零引用回收,讲清循环引用为何会泄漏、如何排查,再补一层 LRU 缓存兜住内存上限;末节对照 Cocos Creator 3.8 的 addRef / decRef / releaseAsset。
清单能列出要拉哪些资源,接下来把它们真正并发拉进来:写一个限制并发数的 Promise 池,按字节加权汇报总进度,区分首屏预加载与按需加载,再加失败重试与降级占位;末节对照 Cocos Creator 3.8 的 resources.load 与 preload。
把散落的图片、音频、图集收进一份清单:定义 manifest 数据结构与 UUID 命名,用依赖闭包算出「加载一个资源要连带拉哪些」,再做拓扑排序得到可预加载顺序,最后给出 Cocos Creator 3.8 的 Bundle 与 resources 对照。
前两节的音频在桌面浏览器跑得好好的,一上手机就出问题:首次进游戏没声音、切到后台再回来 BGM 断了、iOS 静音键开着就完全没声。本节讲清浏览器的自动播放策略,用首次用户交互解锁 AudioContext,用 visibilitychange 处理切后台暂停与回前台恢复,并给出 Cocos Creator 3.8 的对照。
上一节解决了音效的并发问题,但一条 BGM 加几十条音效,音量该怎么统一控制?本节给 mini2d 搭出主音量/BGM/音效三级总线,讲清 gain 相乘的数学,实现 BGM 交叉淡入淡出与切歌,并给出静音状态与用户偏好的 localStorage 持久化;末节对照 Cocos Creator 3.8。
画面之外,《方块冲刺》还缺声音。本节给 mini2d 写出音频层:用 HTMLAudioElement 封装播放实例,用对象池复用元素避免反复创建,处理同时播放上限与最旧/最轻抢占策略,并给出统一的 play/stop/setVolume 接口;末节对照 Cocos Creator 3.8 的 AudioSource、AudioClip 与 playOneShot。