简介这是一份 Cocos Creator 打包微信小游戏的完整源代码资源适合已掌握 Cocos Creator 基础、正准备将自己的 2D 游戏发布到微信小游戏平台的开发者。压缩包共 592 个文件约 1.67MB包含 289 个 json场景、配置与资源映射、180 个 png美术素材、81 个 meta资源导入信息、17 个 js 与 2 个 ts核心逻辑与脚本、2 个 fire场景文件以及 bin、plist、fnt、gltf 等资源基本覆盖小游戏从配置、构建到运行所需的典型文件结构。已有 3301 人学习下载。通过这份资源可以直观了解 Cocos Creator 构建微信小游戏时引擎自动生成的目录组织方式、资源引用关系和脚本入口减少首次打包时在平台配置与文件校验上花费的调试时间适合作为入门参考或同类项目打包时的对照样例。1. 先说结论这份小鸟源码真正值钱的是打包链路拿到一份“Cocos Creator 打包成微信小游戏源代码”不少人第一反应是先打开 Cocos Creator 跑一遍一只像素小鸟立在屏幕左侧点击屏幕上升穿过水管缝隙就加分碰到水管或地面直接结束。跑通了有人会想“这不就是个休闲小游戏 demo 吗”。然后他按自己的理解构建发布导入微信开发者工具黑屏、报错、场景加载不出来折腾一下午才发现——这份源码里最有价值的不是那只扇翅膀的鸟而是从 Creator 工程到微信小游戏产物之间一整套已经调通的配置。这份资源适合两种人一是想在微信小游戏里做经典“点击上升”玩法、却被构建配置卡住的新手二是已经会写 Cocos Creator 游戏逻辑、想搞清楚小游戏平台适配细节的开发者。把它跑起来等于拿到一个可以照着抄的模板场景怎么配、脚本怎么挂、资源怎么压缩、构建参数怎么选全都在工程里摆好了。2. 工程解剖Cocos Creator 项目里哪些文件在替小游戏打工拿到这份工程先别急着打开场景把目录过一遍你就能看出它跟普通 Creator 教学项目的差别普通项目只有 assets 和脚本这份工程多了一整套围绕微信小游戏平台做的构建适配。2.1 技术栈选型为什么是 2.4 系 Creator 加 TypeScript工程用的是 Cocos Creator 2.4 系构建流程脚本层是 TypeScript。选这套组合不是拍脑袋2.4 时代 Creator 对微信小游戏的支持已经稳定构建产物是纯 JS 加 JSON 配置首包体积容易控制而 3.x 虽然也在小游戏平台跑得不错但构建产物体积偏大对包体限制更敏感。物理相关代码没有引物理引擎全部用手动模拟。这个选择在小游戏场景里非常务实——物理引擎库打进包体要占几百 KB手机端性能开销也不小而这类“点击上升”玩法的碰撞判定用矩形相交就足够。我一般拿到这类休闲游戏源码也会先问一句物理引擎是不是必要的很多情况下答案都是否定的。2.2 assets 目录结构游戏资源和脚本怎么分区打开工程根目录核心结构是这样的assets/ scenes/ # 场景文件 loading.fire # 启动场景负责预加载和初始化 game.fire # 主游戏场景玩法全在这里 scripts/ # 逻辑脚本 Bird.ts # 小鸟控制重力、跳跃、旋转 PipeManager.ts # 水管生成、移动、回收 GameManager.ts # 状态控制、碰撞、计分 AudioManager.ts # 音频加载与播放 textures/ # 图片资源 bird/ # 小鸟序列帧扇翅动画用 pipe/ # 上下水管图片 background/ # 背景、地面 prefabs/ # 预制体 Bird.prefab # 小鸟预制体 Pipe.prefab # 水管对预制体 build/ wechatgame/ # 微信小游戏构建产物由 Creator 生成assets 是编辑器的资源根目录Creator 会按这个目录结构管理资源 UUID 和依赖。scenes 和 prefabs 分开放是工程里的常见做法便于预览场景时快速定位scripts 单独成目录也方便脚本编译时按依赖关系打包。textures 里的小鸟和背景都是小尺寸图这是故意控制的。微信小游戏主包有体积限制图片资源是首包体积的大头能用小图绝不用大图。水管和地面用纯色拼接配合简单纹理比整张背景图省得多。2.3 build/wechatgame构建产物里藏着平台适配的关键构建发布一次后build/wechatgame 目录下会出现这些文件build/wechatgame/ game.js # 编译后的游戏逻辑代码 game.json # 小游戏全局配置方向、子包等 project.config.json # 微信开发者工具的项目配置 src/ # 引擎源码和设置 assets/ # 序列化后的场景与资源project.config.json 是微信开发者工具识别项目用的里面配置了 appid、项目名、编译设置。game.json 是真正跑在微信小游戏环境里的运行时配置deviceOrientation 字段控制了屏幕方向networkTimeout 字段决定了网络请求超时时间。这里有个细节值得注意构建产物里 assets 目录里的资源全部是重新序列化过的已经不是编辑器的原始格式。所以在微信开发者工具里改了 game.js 之后如果重新在 Creator 里构建改动会被覆盖。二次开发时要么改 Creator 源码再构建要么只改产物里 Creator 不会动的文件——这个坑后面会细说。3. 打包实战从 Creator 构建到微信开发者工具的三步流程这一章直接把打包流程完整走一遍。这三步听起来简单实际每一步都有几个参数容易配错配错了预览就是黑屏。我按实际操作的顺序来写。3.1 构建面板关键配置平台、方向、分辨率打开 Creator 菜单栏的“项目” → “构建发布”在构建面板里选择微信小游戏平台。核心配置项有四个配置项推荐值说明发布平台微信小游戏对应构建产物目录 wechatgame设备方向竖屏 portrait这类玩法横屏没法玩竖屏最合适设计分辨率720 × 1280主流竖屏分辨率切到不同手机上不会被过度拉伸勾选 ES6 转 ES5开启兼容低版本微信基础库不勾选会在老机型上报语法错误设计分辨率这个参数要重点说。720 × 1280 是按竖屏主流机型取的构建后游戏画面会被缩放适配到实际屏幕。如果设计分辨率太高小屏手机上 UI 会显得特别小太低在 2K 屏上又会有明显颗粒感。这个工程在适配模式上用的是适配屏幕宽度加适当地图高度保证玩家在任何机型上看到的画面范围接近一致。3.2 构建与导入生成产物到微信开发者工具配置完成后点击“构建”Creator 会把 assets 里的资源序列化、脚本编译打包最后生成 build/wechatgame 目录。构建完成后打开微信开发者工具选择“小程序”项目目录直接指向 build/wechatgame 就好。导入后建议先做两件事第一在微信开发者工具的“详情” → “本地设置”里勾选“不校验合法域名、web-view业务域名、TLS 版本以及 HTTPS 证书”。开发阶段资源请求如果走了远程地址不勾这个会被拦截。第二在主界面确认 game.js 里的渲染逻辑没有报错。常见错误是 require 路径不对或者脚本里用了 ES6 的箭头函数但构建时没做语法转换错误信息会直接指向具体行号。3.3 调试预览真机效果和模拟器效果差距在哪微信开发者工具自带模拟器但模拟器和真机行为不一致主要体现在三方面一是屏幕适配。模拟器窗口默认是 iPhone 尺寸真机可能有刘海屏、挖孔屏、全面屏安全区不同画面底部可能会被系统手势条遮挡。这个工程在 GameManager 里读取了 safeArea后续适配章节再展开。二是性能表现。模拟器用的是电脑性能真机是手机性能。如果游戏在模拟器上流畅真机上掉帧优先检查是否有对象反复创建销毁——水管对如果每根都新建节点到后期水管数量多了就会卡。这个工程里用了对象池就是解决这个问题的。三是音频策略。微信小游戏平台规定音频不能自动播放必须由用户触摸事件触发。模拟器上自动播放可能正常真机上没声音大概率是触发了这个限制。3.4 除了编辑器还有命令行构建方式如果后续要反复构建调试我建议直接用命令行构建省去打开编辑器点按钮的时间。Cocos Creator 支持命令行构建# macOS 路径示例 /Applications/CocosCreator/CocosCreator.app/Contents/MacOS/CocosCreator \ --project /path/to/your/project \ --build platformwechatgame;debugtrue # Windows 路径示例 C:\CocosCreator\CocosCreator.exe \ --project D:\path\to\project \ --build platformwechatgame;debugtrue命令行构建走的构建逻辑和编辑器里一致区别是 debugtrue 时构建产物保留源码映射方便在微信开发者工具里调试脚本正式发布时把这个参数改成 false产物体积会小一些。4. 核心代码拆解小鸟飞行、水管生成与碰撞判定这一章直接拆玩法代码。整个玩法逻辑可以拆成三块小鸟自身的行为、水管的生成与移动、两者之间的碰撞与计分。每一块都能单独替换和扩展这正是这份源码适合二次开发的基础。4.1 小鸟控制手动重力模型怎么模拟出飞行手感小鸟的核心代码在 Bird.ts下落和上升完全手动计算没有依赖物理引擎// Bird.ts —— 手动模拟重力不依赖物理引擎 const { ccclass, property } cc._decorator; ccclass export default class Bird extends cc.Component { property jumpSpeed: number -320; // 点击时瞬间速度负值表示向上 property gravity: number 900; // 每秒钟加速度增量像素/秒² property maxRotation: number 30; // 最大旋转角度让俯冲姿态不过度夸张 private vy: number 0; // 当前垂直速度 private isDead: boolean false; update(dt: number) { if (this.isDead) return; // 重力累积到速度上速度再累积到位移 this.vy this.gravity * dt; this.node.y this.vy * dt; // 根据速度方向让小鸟低头或抬头增加姿态反馈 const ratio Math.max(-1, Math.min(1, this.vy / 500)); this.node.angle ratio * this.maxRotation; } jump() { if (this.isDead) return; this.vy this.jumpSpeed; this.node.angle this.maxRotation; } die() { this.isDead true; } }逻辑说明每帧经过的时间 dt 是一个增量值单位是秒。重力加速度乘以 dt得到“这一帧速度增加了多少”速度乘以 dt得到“这一帧位移了多少”。这是 2D 平台游戏里最经典的手动重力写法比接入物理引擎更可控。参数说明jumpSpeed 是负数因为 Cocos Creator 坐标系里 y 轴向上为正负值代表向上飞。这个值绝对值越大点一下就蹿得越高。gravity 越大下落越快手感就越“重”。两个参数配合决定了这游戏的难度曲线后面二次开发部分会讲怎么调整。旋转那段用了 ratio 做限幅把速度映射到 -30 到 30 度之间防止小鸟下落时翻个底朝天。4.2 水管生成对象池是怎么保证不掉帧的水管生成在 PipeManager.ts。这里最关键的设计不是每隔几秒生成一对水管而是生成的节点“循环利用”// PipeManager.ts —— 水管对对象池避免频繁创建和销毁节点 const { ccclass, property } cc._decorator; ccclass export default class PipeManager extends cc.Component { property(cc.Prefab) pipePrefab: cc.Prefab null; property spawnInterval: number 1.5; // 生成间隔秒 property gapHeight: number 220; // 上下水管之间的空隙高度 private pool: cc.Node[] []; // 对象池最多存 8 对 private timer: number 0; start() { // 预创建 4 对水管放进池子游戏启动时不卡顿 for (let i 0; i 4; i) { const pipe cc.instantiate(this.pipePrefab); pipe.parent this.node; pipe.active false; this.pool.push(pipe); } } update(dt: number) { // 生成计时器 this.timer dt; if (this.timer this.spawnInterval) { this.timer 0; this.spawnPipe(); } } spawnPipe() { // 从池子里取一对池子空了就新创建 let pipe this.pool.find(p !p.active); if (!pipe) { pipe cc.instantiate(this.pipePrefab); pipe.parent this.node; this.pool.push(pipe); } pipe.active true; // 随机设置水管对的 y 位置让空隙位置变化 const minY 120; const maxY 360; pipe.y minY Math.random() * (maxY - minY); pipe.x 400; // 屏幕右侧外进场 } }逻辑说明start 里先创建 4 对水管但不激活这些节点提前存在于场景中后面的游戏过程就是循环激活和复用。spawnPipe 从池里找一个未激活的节点设置新的位置后激活。这样游戏玩 10 分钟也就只有那十几对节点在反复移动不会有新节点产生导致的卡顿。参数说明spawnInterval 越小水管出得越快游戏整体节奏越快。gapHeight 是上下水管之间的空隙越小越难钻过去。这两个参数一个管时间压力一个管操作难度是游戏难度曲线的两个主要旋钮。random 范围那两行minY 和 maxY 控制水管对的位置变化范围。范围越大玩家每次钻缝都要重新找位置视觉上不容易产生重复感。4.3 碰撞判定与计分矩形相交和分数存储碰撞检测没有用物理碰撞体而是用坐标盒的直接相交判断放在 GameManager.ts// GameManager.ts —— 状态管理、碰撞检测、计分 const { ccclass, property } cc._decorator; ccclass export default class GameManager extends cc.Component { property(cc.Node) bird: cc.Node null; property(cc.Node) pipeManager: cc.Node null; private score: number 0; private isGameOver: boolean false; update() { if (this.isGameOver) return; // 遍历水管对逐个做矩形框碰撞检测 const pipes this.pipeManager.children; for (let i 0; i pipes.length; i) { const pipeNode pipes[i]; if (!pipeNode.active) continue; if (this.checkHit(this.bird, pipeNode)) { this.gameOver(); return; } // 计分逻辑水管完全越过小鸟后加分 if (pipeNode.x this.bird.x !pipeNode.getComponent(Pipe).scored) { pipeNode.getComponent(Pipe).scored true; this.score; } } } checkHit(a: cc.Node, b: cc.Node): boolean { const boxA a.getBoundingBoxToWorld(); const boxB b.getBoundingBoxToWorld(); return boxA.intersects(boxB); } gameOver() { this.isGameOver true; this.bird.getComponent(Bird).die(); // 写入微信小游戏本地存储保留下次启动的最高分 if (typeof wx ! undefined wx.getStorageSync) { const best wx.getStorageSync(bestScore) || 0; if (this.score best) { wx.setStorageSync(bestScore, this.score); } } } }逻辑说明getBoundingBoxToWorld 取的是节点在屏幕坐标里的轴对齐包围盒intersects 就是两个矩形是否相交的判断。这套组合适合所有 2D 休闲游戏不需要物理引擎参与性能开销极小。计分方式用的是“水管通过小鸟后置位”每对水管只记一次分。这里通过 Pipe 组件上的 scored 布尔值避免重复计分比用坐标区间判断更可靠。微信存储那部分做了环境判断typeof wx ! undefined这样代码在 Creator 编辑器预览里也不会报错只有真正跑到微信小游戏环境里才执行存储逻辑。4.4 平台桥接wx 全局对象在代码里怎么用才安全除了解析存储分数工程里 AudioManager 也做了类似的环境判断。因为音频必须先由用户触摸触发所以在场景初始化时会把音频播放挂到 Canvas 节点的触摸监听上而不是在场景加载时就自动播放。这是微信小游戏平台特有的约束。桥接层建议单独放一个 utils 文件不要去每个组件里到处写 wx.xxx。原因很简单编辑器预览、微信开发者工具、浏览器调试三种环境对 wx 的支持程度不一样集中的桥接层可以统一处理兼容出问题也只改一个文件。5. 小游戏打包避坑5 个真实踩过的坑和修复这一章写的是拿到这类源码后最容易踩的坑每条都是“现象 → 原因 → 解决”的结构照着排查就行。5.1 构建后开发者工具报语法错误现象构建成功导入微信开发者工具后控制台报错指向 game.js 里的箭头函数或 Promise 语法低版本安卓真机上直接白屏。原因构建面板里“ES6 转 ES5”没有勾选。微信基础库在较新版本支持 ES6但不少安卓手机上的微信版本还没跟上。Creator 默认产物保留 ES6 语法老环境解析不了。解决构建面板里勾选 ES6 转 ES5重新构建。如果重新构建后仍然报错检查代码里有没有用 async/await这种语法不转需要把相关函数改写成 Promise 链式调用。5.2 首包体积超过限制现象微信开发者工具提示主包大小超限或者审核被拒提示“小游戏主包超过 4M”。原因素材资源过大。尤其是背景图、音频文件和序列帧图集没有压缩就直接进了 assets构建产物把这些资源整包塞进主包。解决先看 build/wechatgame/assets 目录里最大的几个文件确定是哪类资源占空间。图片压缩到合适尺寸序列帧改成图集texture atlas音频转成 AAC 低码率格式。必要时用分包加载功能把奖励动画、额外关卡的资源放进分包首包只保留核心玩法资源。5.3 真机上游戏没有声音现象模拟器和 Creator 编辑器里都有声音真机预览就是安静的。原因微信小游戏限制了音频自动播放必须由用户触摸事件触发播放逻辑。编辑器没有这个限制所以问题只在真机暴露。解决在游戏开始场景加一个“点击开始”按钮音频播放全部从按钮触摸回调里触发。如果开局前就要有背景音乐可以在开始按钮的回调里同时启动背景音乐和游戏倒计时用一次触摸换取整局音频的播放权限。5.4 全面屏手机画面下方被手势条遮挡现象iPhone 或安卓全面屏真机上游戏底部的地面被系统手势条和 Home 条盖住UI 按钮点不到。原因开发者工具模拟器不模拟全面屏安全区真机才有这个问题。游戏的设计分辨率适配没有处理 safeArea 区域。解决在小游戏适配代码里读取微信的 safeArea 信息把地面和重要 UI 提升到安全区之内。常见做法是获取 screen.safeArea 的 top 和 bottom 值换算成设计分辨率坐标给地面节点和计分 UI 加上偏移。这个工程里因为做了这个适配真机表现是正常的如果换到别的工程要记得补上。5.5 请求远程资源或接口被拦截现象排行榜加载失败、远程图片不显示控制台报错提示“http://xxx 不在以下 request 合法域名列表中”。原因微信小游戏的所有网络请求必须走 HTTPS并且域名必须在微信公众平台配置过合法域名。开发阶段你直接访问公司内网 HTTP 接口一定被拦截。解决开发调试时在微信开发者工具勾选“不校验合法域名”保证功能能跑发布前把资源域名和接口域名配置到微信公众平台的后台。注意小游戏的后台配置路径和普通小程序不一样别搞混了。审核时域名没配置好功能必然挂了。6. 二次开发把“小鸟”骨架改成跑酷或跳跃玩法最后一章直接给改造思路。这个工程的核心结构是“状态机 对象池 矩形碰撞”这套骨架天然适合横向卷轴类玩法不只限于水管。6.1 调整手感参数先定游戏难度曲线改动手感最快的是调 Bird.ts 和 PipeManager.ts 顶部那几个 property参数当前值效果说明jumpSpeed-320绝对值调大跳跃幅度变大调小更“肉”gravity900调大下落更快调小腾空时间更长容错更高spawnInterval1.5s调小水管节奏变快游戏进程压力变大gapHeight220调大容易钻调小考验操作精度我一般先调 spawnInterval 和 gapHeight 这对组合因为它们一个管频率、一个管容错比单纯调重力对玩家体验的影响更直接。调完跑 10 局再微调 gravity 让下落的手感顺滑一点。6.2 把水管换成浮空平台的跳跃玩法水管对本质是一组移动的“障碍物检查点”。改成平台跳跃只需要把 PipeManager 生成的预制体从上下两根水管换成一个平台预制体碰撞逻辑不用改计分位置从“水管通过后加分”变成“平台通过后加分”。平台预制体需要加一个 Platform.ts 组件里面用一个 scored 布尔值记录是否已计分别的都不变。GameManager 里遍历的仍然是 pipeManager 节点下的子节点只是碰撞形状从矩形变成了平台自己的包围盒。代码骨架不用动替换预制体和场景里的节点引用就行。6.3 给游戏加变速系统原版始终匀速玩久了没有压迫感。我建议在 GameManager 里加一个 speedScale 属性每得 5 分把 pipeManager 的移动速度整体乘一个系数// GameManager.ts 里加一段分数驱动的变速逻辑 onScoreChanged() { const pipeMgr this.pipeManager.getComponent(PipeManager); pipeMgr.moveSpeed 160 Math.floor(this.score / 5) * 20; }水管移动速度从初始值开始每 5 分提高 20上限可以自己设。这样游戏不会永远停留在同一难度玩家也有持续挑战的感觉。如果要更平滑可以把分段改成线性插值用 score / maxScore 做权重。改造完记得重新构建一次在微信开发者工具里跑通完整流程模拟器预检、真机预览、查看构建体积有没有异常。说实话这类工程源码我拆过不少最大的教训是改动前一定要先备份构建产物或者干脆养成每次只改 Creator 源码、重新构建的习惯。直接改 build 目录里的 game.js重新构建一次之前的修改就全部丢掉血泪经验。从那以后我每次拿到新工程第一件事就是确认构建流程能完整跑通再动代码。希望帮到你。本文还有配套的精品资源点击获取