资讯动态

Cocos Creator抓娃娃机实战:物理系统与概率判定完整实现

发布时间:2026/10/17 1:37:54 来源:尧图企业网站定制
简介这份资源是面向Cocos Creator初学者与TypeScript入门开发者的抓娃娃小游戏实战示例帮助读者理解2D休闲游戏的完整开发流程。项目围绕爪子移动、抓取判定、积分与概率算法等核心逻辑展开并涉及物理碰撞模拟、UI交互事件、动画系统与资源管理等模块同时预留了对接后端接口的能力便于扩展排行榜或多人同步功能。压缩包共992个文件以meta、json、png、anim、prefab、map等资源与配置为主另有少量ts脚本、mp3音效及fire场景文件整体约7.72MB目录结构完整可直接导入引擎运行调试。目前已有1121人学习下载适合希望借助小体量项目熟悉Cocos Creator组件化开发、TypeScript强类型写法与单机游戏架构的读者参考。1. 从一台抓娃娃机的物理逻辑说起为什么用 Cocos Creator 做这个小示例抓娃娃机这个玩法看起来简单真动手做才发现它是个“物理 状态机 概率”三合一的小系统。爪子什么时候下、什么时候合、抓到之后判定是“真抓”还是“假抓”、娃娃被抓起后怎么跟随爪子移动、到顶之后怎么掉落——每一步都不是纯动画能糊弄过去的。我见过不少同学拿 Cocos Creator 做抓娃娃最后做出来一个“爪子下去、娃娃消失、弹窗恭喜”的假交互答辩时被问一句“抓取判定怎么做的”就卡住了。这份 Cocos Creator 抓娃娃小示例定位就是一个能跑通完整抓取链路的最小可交付项目。技术栈是 Cocos Creator TypeScript适合正在做课程设计、毕设前期练手或者想拿一个完整小游戏案例摸清 Creator 物理与节点体系的人。它不追求美术多精致重点是把“移动—下爪—抓取判定—回收—结算”这条主循环用 TS 脚本串起来让你能在此基础上改参数、换皮、加关卡。2. 需求拆解与技术选型为什么是 Creator TS 而不是纯动画2.1 玩法需求拆解成四个可独立验证的模块先把“抓娃娃”这个笼统需求拆开不拆开就没法写代码。我一般会拆成四块横移控制模块爪子在天车轨道上左右移动有边界限制松手即停或自动往返取决于你想做“按住移动”还是“点按移动”。下爪与抓取模块爪子沿 Y 轴下降到达娃娃所在高度后闭合触发抓取判定。抓取判定模块这是整个项目的核心。判定不是“碰到就抓到”而是“碰到 概率 抓力衰减”三者共同决定。回收与结算模块爪子带娃娃上升、回到顶部、移动到出口、释放娃娃、更新分数或库存。这四个模块拆完之后你会发现每个模块都能单独写一个 TS 脚本挂到节点上互不干扰调试也方便。很多同学一上来把所有逻辑塞进一个GameManager.ts写到三百行就开始互相打架改一个下爪速度结果横移也跟着抖。2.2 技术选型Creator 的物理系统够不够用Cocos Creator 自带 2D 物理系统Box2D 封装做抓娃娃其实有两种路线方案实现方式优点缺点纯运动学手动改节点 position自己写碰撞检测可控性强不依赖物理引擎碰撞判定要自己算娃娃堆叠麻烦物理系统给爪子和娃娃加 RigidBody2D Collider碰撞自动处理堆叠自然抓取判定要额外写物理参数调起来玄学这个示例走的是混合路线娃娃用物理刚体让它们自然堆在池子里爪子用运动学节点手动控制位置抓取判定用碰撞回调 概率函数。这样既保留了娃娃堆叠的真实感又避免了爪子被物理引擎“带偏”导致下爪位置不准。提示如果你的 Creator 版本里 2D 物理默认没开需要在项目设置里手动启用物理系统否则 RigidBody2D 挂上去也不生效。2.3 TypeScript 在 Creator 里的组织方式Creator 支持 TS 脚本但要注意它编译后跑在引擎的模块体系里。我一般按职责分目录assets/ scripts/ core/ ClawController.ts // 爪子移动与下爪 GrabJudge.ts // 抓取判定 DollSpawner.ts // 娃娃生成 ui/ GameHUD.ts // 分数、按钮 config/ GameConfig.ts // 可调参数集中管理GameConfig.ts是关键把所有能调的数值抽出来答辩时老师问“难度怎么调”你直接指这个文件比现场翻代码强得多。3. 总体架构与核心模块实现从爪子控制到抓取判定3.1 爪子控制器状态机比 if-else 靠谱爪子有四个状态待机、横移、下爪、回收。用状态机写比一堆布尔标志清晰得多。// ClawController.ts export enum ClawState { Idle, Moving, Dropping, Grabbing, Returning } ccclass(ClawController) export class ClawController extends Component { private state: ClawState ClawState.Idle; private moveDir: number 0; private dropSpeed: number 300; // 下爪速度 px/s private moveSpeed: number 200; // 横移速度 px/s private minX: number -250; private maxX: number 250; update(dt: number) { switch (this.state) { case ClawState.Moving: this.node.x this.moveDir * this.moveSpeed * dt; // 边界钳制防止爪子跑出轨道 this.node.x Math.max(this.minX, Math.min(this.maxX, this.node.x)); break; case ClawState.Dropping: this.node.y - this.dropSpeed * dt; if (this.node.y this.getGrabLineY()) { this.state ClawState.Grabbing; this.onClawClosed(); } break; case ClawState.Returning: this.node.y this.dropSpeed * dt; if (this.node.y this.getTopY()) { this.state ClawState.Idle; this.onReturnComplete(); } break; } } }这段代码里几个参数值得说清楚dropSpeed和moveSpeed分开控制是因为下爪速度影响手感横移速度影响操作节奏两者混在一起调会互相干扰。minX和maxX是轨道边界通常根据背景图里轨道的实际像素宽度来定我一般会在编辑器里放两个空节点当左右边界标记运行时读取它们的 x 坐标而不是硬编码。getGrabLineY()返回的是爪子闭合的高度线这个值不是固定的因为娃娃堆的高度会变。常见做法是射线检测从爪子当前位置向下打一条射线碰到第一个娃娃的碰撞体就返回那个 y 值。3.2 抓取判定概率函数才是抓娃娃的灵魂抓取判定如果写成“碰到就抓到”那这个项目就没有灵魂了。真实抓娃娃机的核心是“抓力”概念——爪子合上时有一个初始抓力娃娃有一个重量抓力大于重量才抓得稳否则半路掉落。// GrabJudge.ts export class GrabJudge { // 基础抓取成功率0~1 static baseRate: number 0.6; // 娃娃重量对成功率的影响系数 static weightFactor: number 0.15; static judge(dollWeight: number, clawPower: number): boolean { // 实际成功率 基础率 爪子强度 - 娃娃重量影响 let rate this.baseRate clawPower - dollWeight * this.weightFactor; rate Math.max(0.05, Math.min(0.95, rate)); // 钳制避免必抓或必不抓 return Math.random() rate; } // 抓取成功后的“半路掉落”判定 static judgeDrop(dollWeight: number, clawPower: number): boolean { let dropRate dollWeight * 0.1 - clawPower * 0.05; dropRate Math.max(0, Math.min(0.5, dropRate)); return Math.random() dropRate; } }baseRate是基础成功率clawPower可以来自道具或关卡加成dollWeight是每个娃娃自己的属性。judgeDrop是第二层判定——即使抓到了回收途中还有概率掉落。这两层判定叠起来玩家才会觉得“有时候抓得起来有时候抓起来又掉了”而不是机械地每次结果一样。注意概率函数里的钳制很重要。如果不钳制clawPower堆高了会出现 100% 必抓游戏就没意思了反过来娃娃太重会出现永远抓不到玩家直接退游。3.3 娃娃生成与堆叠用物理刚体省一半力气娃娃池的堆叠如果手动算位置写起来很痛苦。用 RigidBody2D 让物理引擎自己堆// DollSpawner.ts ccclass(DollSpawner) export class DollSpawner extends Component { property(Prefab) dollPrefab: Prefab null; property spawnCount: number 12; property spawnAreaWidth: number 400; start() { for (let i 0; i this.spawnCount; i) { const doll instantiate(this.dollPrefab); // 在池子范围内随机 xy 从高处落下让物理自然堆叠 const x (Math.random() - 0.5) * this.spawnAreaWidth; const y 200 i * 30; doll.setPosition(x, y); this.node.addChild(doll); } } }娃娃预制体上挂 RigidBody2DDynamic 类型 CircleCollider2D摩擦力和弹性在物理材质里调。spawnCount控制娃娃数量spawnAreaWidth控制落点范围。y 从高处依次落下物理引擎会让它们自然堆成一堆比手动摆位置真实得多。这里有个血泪经验娃娃的刚体质量别设太大否则堆起来之后底层娃娃会被压得抖动看起来像在“抽搐”。我一般把质量设在 0.5~1 之间配合较高的线性阻尼。3.4 回收与结算别让娃娃穿模爪子抓到娃娃后要把娃娃设为爪子的子节点跟随爪子移动。但直接setParent会导致娃娃的物理刚体还在生效跟爪子打架。正确做法是先禁用娃娃的刚体再挂到爪子下面onGrabSuccess(doll: Node) { const rb doll.getComponent(RigidBody2D); if (rb) rb.enabled false; // 先关物理再挂载 doll.setParent(this.clawNode); doll.setPosition(0, -40); // 挂在爪子下方 }回收完成后在出口位置释放娃娃重新启用刚体或者直接销毁并加分。这一步如果顺序写反——先挂载再关物理——娃娃会因为物理惯性在爪子下面乱甩看起来像“抓了个陀螺”。4. 避坑与常见问题抓娃娃项目里最容易翻车的五个点4.1 爪子下爪位置和视觉不匹配现象爪子明明看着在娃娃正上方判定却说没碰到。原因爪子的碰撞体或者射线起点没有和视觉节点的锚点对齐常见于爪子图片的锚点不在中心。解决把爪子的碰撞体单独放在一个空子节点上锚点归零射线从这个子节点发出视觉图片怎么偏移都不影响判定。4.2 娃娃堆叠后穿透池底现象娃娃落下来直接穿过池子底部掉出屏幕。原因池底没有加静态碰撞体或者娃娃下落速度太快物理引擎的离散检测来不及响应。解决给池底加一个 Static 类型的 RigidBody2D BoxCollider2D同时把娃娃刚体的碰撞检测模式改成 Continuous代价是性能略降但抓娃娃这种量级完全扛得住。4.3 抓取概率调完之后“手感全无”现象改了一次baseRate结果要么把把都中要么十把不中。原因只调了基础率没考虑clawPower和dollWeight的叠加效果三个参数互相放大。解决固定两个调一个。我一般先把clawPower设为 0、dollWeight统一设为 1单独调baseRate找到基准手感再逐步引入重量差异。4.4 爪子回收时娃娃抖动或穿模现象娃娃挂在爪子下面一路抖或者直接穿过爪子掉下去。原因挂载时没禁用刚体或者挂载后没有重置娃娃的局部坐标。解决严格按“禁用刚体 → setParent → 重置 localPosition”的顺序执行三步缺一不可。4.5 横移边界在不同分辨率下错位现象在编辑器里调好的边界换到手机分辨率爪子能跑出轨道。原因边界值硬编码成了像素坐标没有跟随 Canvas 的适配缩放。解决用view.getVisibleSize()或者相对 Canvas 的百分比来算边界或者用两个边界节点做参照运行时读取它们的世界坐标转换到爪子父节点坐标系。5. 验收与答辩怎么证明这套抓娃娃示例是“完整”的验收这个项目我一般不看美术看三条链路能不能走通。第一条链路操作响应链路。从按下按钮到爪子开始移动延迟是否可感知。验收方法很简单在update里打时间戳记录输入事件到状态切换的间隔。通常要求在一帧内响应超过两帧就是事件绑定层级有问题。第二条链路抓取判定链路。准备一组测试用例固定随机种子验证不同dollWeight和clawPower组合下的成功率是否符合预期。下面这个表格可以直接拿去当验收记录用例娃娃重量爪子强度预期成功率实测 100 次成功数A1.0045%43B1.00.375%78C2.0030%29D2.00.565%61实测值在预期值上下浮动 10% 以内就算通过。答辩时把这表格一亮老师问“概率怎么验证的”你就有话说了。第三条链路异常边界链路。娃娃全部抓完之后程序会不会崩、连续快速点击按钮爪子会不会状态错乱、抓取过程中切后台再回来状态对不对。这几个边界我每次都会手动过一遍尤其是连续点击最容易暴露状态机没加锁的问题。答辩时还有一个技巧别只演示“抓到了”的流程主动演示一次“抓起来又掉了”的流程然后解释这是judgeDrop在起作用。老师看到你连失败路径都设计了印象分直接上去。提示如果答辩要求现场改参数提前把GameConfig.ts里的参数注释写清楚每个参数旁边标上“调大效果”和“调小效果”现场改起来不慌。从那以后我每次做带概率判定的项目都会强制走一遍“固定种子 批量统计”的验收流程不再靠手感说“差不多”。希望这套抓娃娃示例的结构和验收思路能帮你把课程设计或毕设的交互部分稳稳落地。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑