Cocos Creator v2.0实战:2D闯关安卓游戏开发与打包

发布时间:2026/10/7 10:34:36
Cocos Creator v2.0实战:2D闯关安卓游戏开发与打包
简介这是一份面向计算机、软件工程及人工智能相关专业师生的Cocos Creator v2.0二维闯关安卓游戏开发教学资源可作为课程实践、毕业设计或项目实训的参考案例帮助学习者理解移动端游戏开发流程掌握二维场景渲染、物理引擎集成与交互逻辑设计等关键技术。资源包共375个文件约8.93MB以png图片素材、meta配置、js脚本、anim动画、prefab预制体、fire场景及mp3音效为主另含docx系统开发说明、pptx课件与mp4演示视频覆盖从素材到逻辑的完整工程结构。已有39人学习。具备编程基础者可在现有框架上扩展自定义关卡或优化角色行为建议优先查阅指南文件了解环境配置要求仅限教育科研用途。1. 基于Cocos Creator v2.0的2D闯关安卓游戏从课程设计到真机跑通很多同学做课程设计时选题一写“基于 Cocos Creator 的 2D 闯关安卓游戏”脑子里想的是超级马里奥手上做出来的却是一个方块在空白背景上左右横跳。问题不在引擎在于没人告诉你从“能跑”到“像个游戏”之间到底缺了哪几块。Cocos Creator v2.0 这个版本虽然不算新但它的组件化工作流、场景编辑器和一键打包 APK 的能力放到课程设计场景里依然是最省事的组合。这篇文章面向的是需要在一到两周内交出一个可演示、可安装、有完整关卡流程的安卓游戏的学生或初级开发者。我会按实际做项目的顺序把场景搭建、角色控制、关卡切换、碰撞检测、安卓打包这条链路拆开讲每一步都给出能直接抄的代码和参数。你不需要先学完整套引擎文档跟着走就能把 APK 装到手机上。2. 场景搭建与节点组织为什么你的层级一乱就全乱2.1 先定层级再拖素材别反过来Cocos Creator v2.0 的场景编辑器是所见即所得的很多人一上来就把背景图、角色图、地面图全拖进 Canvas 下面结果节点列表长得像购物清单改一个东西要找半天。正确的做法是先想清楚这个 2D 闯关游戏有哪些逻辑层再按层建空节点最后把美术资源挂到对应层下面。一个典型的 2D 横版闯关游戏场景层级至少分四层背景层Background、地形层Terrain、角色层Character、UI 层UI。背景层放远景和视差图地形层放地面、平台、障碍物角色层放玩家和敌人UI 层放血条、分数、暂停按钮。这样做的好处是后面做摄像机跟随的时候你只需要移动背景层和地形层的父节点角色层和 UI 层不受影响。在 Cocos Creator v2.0 里Canvas 节点默认带一个 Widget 组件做屏幕适配。课程设计里最常见的适配方案是 Fit Height 模式设计分辨率设成 960×640 或者 1280×720。如果你做的是竖屏闯关就改成 Fit Width。这个参数在 Canvas 的 Widget 组件里改不要手动去调节点位置否则换一台手机就偏了。节点命名也要有规矩。不要出现“Node”“Node1”“Sprite2”这种名字。用英文加下划线比如 bg_far、bg_near、terrain_ground、player、enemy_slime、ui_hp_bar。后面写代码的时候this.node.getChildByName(player)这种调用才不会写错。2.2 用 Prefab 管敌人和道具别在场景里复制粘贴课程设计里经常需要放十几个同样的敌人或者金币。如果你直接在场景里复制粘贴改一个敌人的属性就要改十几遍。Cocos Creator v2.0 的 Prefab 系统就是解决这个问题的。做法是在场景里做一个标准的敌人节点挂好 Sprite、Collider、脚本调好参数然后把它从层级管理器拖到资源管理器的 assets/prefabs 文件夹里。这时候场景里的那个节点会变成蓝色说明它已经是一个 Prefab 实例。之后你要放新敌人直接从资源管理器把 Prefab 拖进场景就行。代码里动态生成敌人也用 Prefab// EnemySpawner.js cc.Class({ extends: cc.Component, properties: { enemyPrefab: { default: null, type: cc.Prefab }, spawnInterval: 2.0, // 生成间隔单位秒 maxEnemies: 5 // 场上最大敌人数 }, onLoad: function () { this.enemyCount 0; this.schedule(this.spawnEnemy, this.spawnInterval); }, spawnEnemy: function () { if (this.enemyCount this.maxEnemies) return; var enemy cc.instantiate(this.enemyPrefab); // 挂到当前节点下保持层级整洁 this.node.addChild(enemy); // 随机放在屏幕右侧外 enemy.setPosition(cc.winSize.width / 2 100, -200); this.enemyCount; } });这段代码的逻辑是每隔 spawnInterval 秒检查一次场上敌人数量没超过上限就在屏幕右侧外生成一个。cc.instantiate是 v2.0 里复制 Prefab 的标准方法返回一个节点对象。this.node.addChild把它挂到当前节点下这样敌人会跟着当前节点一起移动或销毁。参数方面spawnInterval 设 2 到 3 秒比较合适太快了手机卡太慢了玩家觉得无聊。maxEnemies 根据你的屏幕宽度和敌人大小调一般 5 到 8 个。注意Prefab 实例化出来的节点它的脚本 onLoad 会在 addChild 之后才执行。如果你在 spawnEnemy 里立刻去取 enemy 上的组件要确保组件已经挂载。3. 角色控制与物理碰撞让方块像人一样走路3.1 用 cc.PhysicsBoxCollider 还是自己写 AABBCocos Creator v2.0 内置了 Box2D 物理引擎但很多课程设计项目其实用不上完整的物理模拟。如果你只是做平台跳跃角色踩地面、撞墙、吃金币自己写 AABB轴对齐包围盒检测反而更轻量、更可控。我一般会这样选如果游戏里有斜坡、弹跳、重力加速度变化用物理引擎如果只是矩形平台和矩形角色自己写。课程设计里 90% 的情况是后者。自己写碰撞的核心是每帧检测两个矩形是否相交// PlayerController.js cc.Class({ extends: cc.Component, properties: { moveSpeed: 300, // 水平移动速度像素/秒 jumpSpeed: 600, // 跳跃初速度像素/秒 gravity: -1500, // 重力加速度像素/秒² groundY: -200 // 地面的 Y 坐标 }, onLoad: function () { this.vx 0; this.vy 0; this.isOnGround true; // 注册键盘事件 cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this); cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this); }, onKeyDown: function (event) { switch (event.keyCode) { case cc.KEY.left: this.vx -this.moveSpeed; break; case cc.KEY.right: this.vx this.moveSpeed; break; case cc.KEY.up: if (this.isOnGround) { this.vy this.jumpSpeed; this.isOnGround false; } break; } }, onKeyUp: function (event) { if (event.keyCode cc.KEY.left || event.keyCode cc.KEY.right) { this.vx 0; } }, update: function (dt) { // 应用重力 this.vy this.gravity * dt; // 更新位置 var pos this.node.getPosition(); pos.x this.vx * dt; pos.y this.vy * dt; // 地面碰撞检测 if (pos.y this.groundY) { pos.y this.groundY; this.vy 0; this.isOnGround true; } this.node.setPosition(pos); } });这段代码里dt是每帧的时间增量Cocos Creator 的 update 回调会自动传入。this.vy this.gravity * dt是模拟重力加速度gravity 设负值表示向下。pos.y this.groundY是简单的地面检测实际项目里你会用多个平台的 Y 坐标来判断。参数方面moveSpeed 300 在 960 宽的设计分辨率下大概 3 秒穿过屏幕手感适中。jumpSpeed 600 配合 gravity -1500跳跃高度大约是 120 像素能跳过两个角色身高的障碍。3.2 用碰撞分组管理“谁能撞谁”Cocos Creator v2.0 的碰撞系统有分组概念。你可以在项目设置里定义分组比如 player、enemy、coin、platform。然后在 Collider 组件上勾选 Group 和 Mask决定这个节点和哪些组发生碰撞。这个机制在闯关游戏里非常有用。比如玩家碰到金币要加分碰到敌人要扣血碰到平台要停住。如果你不用分组就要在碰撞回调里写一堆 if-else 判断节点名字代码又丑又容易漏。设置方法项目设置 → 分组管理 → 添加分组。然后在每个 Collider 组件的 Group 下拉框选自己的组Mask 勾选要检测的组。代码里用onCollisionEnter回调// PlayerCollision.js cc.Class({ extends: cc.Component, properties: { hp: 3, score: 0 }, onCollisionEnter: function (other, self) { var group other.node.group; if (group coin) { this.score 10; other.node.destroy(); // 吃掉金币 } else if (group enemy) { this.hp - 1; if (this.hp 0) { this.gameOver(); } } }, gameOver: function () { // 切换场景或弹出结束界面 cc.director.loadScene(GameOver); } });other是碰撞到的另一个节点self是自己。other.node.group返回分组名字符串。other.node.destroy()会销毁金币节点注意销毁后不要再去访问它的属性。hp 和 score 这种参数课程设计里设 3 条命、金币 10 分比较常见你可以根据关卡长度调。提示碰撞回调只在两个节点的 Collider 都启用且分组匹配时触发。如果你发现碰撞没反应先检查分组设置再检查 Collider 的 Size 是不是太小。4. 关卡切换与数据持久化别让玩家每次重开都从第一关开始4.1 用 cc.director.loadScene 做关卡切换Cocos Creator v2.0 的场景切换很简单cc.director.loadScene(Level2)就能加载下一个场景。但课程设计里经常遇到一个问题玩家过了第一关第二关加载了但分数和生命值没了。这是因为场景切换会销毁当前场景的所有节点包括你存在节点上的数据。解决办法是用一个全局常驻节点来存数据。在游戏启动场景里创建一个节点挂上cc.game.addPersistRootNode(this.node)这个节点就不会被场景切换销毁。// GameData.js cc.Class({ extends: cc.Component, onLoad: function () { // 防止重复创建 if (cc.game.__gameData) { this.node.destroy(); return; } cc.game.__gameData this; cc.game.addPersistRootNode(this.node); // 初始化数据 this.score 0; this.hp 3; this.currentLevel 1; }, addScore: function (value) { this.score value; }, resetData: function () { this.score 0; this.hp 3; this.currentLevel 1; } });cc.game.addPersistRootNode是 v2.0 里让节点跨场景保留的 API。cc.game.__gameData是一个挂在全局对象上的引用方便其他脚本通过cc.game.__gameData.addScore(10)来调用。注意在 onLoad 里先判断是否已经存在避免从第二关返回第一关时重复创建。关卡切换的代码// LevelManager.js cc.Class({ extends: cc.Component, properties: { nextLevelName: // 在编辑器里填下一关的场景名 }, goToNextLevel: function () { var gameData cc.game.__gameData; gameData.currentLevel; cc.director.loadScene(this.nextLevelName); } });nextLevelName在编辑器属性面板里填比如 Level2 场景就填 Level2。这样每个关卡场景挂一个 LevelManager到终点触发 goToNextLevel 就行。4.2 用 localStorage 存最高分和关卡进度课程设计答辩的时候老师经常会问“你的数据能不能存下来”。Cocos Creator v2.0 支持cc.sys.localStorage在安卓和浏览器上都能用。// SaveManager.js var SaveManager { save: function (key, value) { cc.sys.localStorage.setItem(key, JSON.stringify(value)); }, load: function (key, defaultValue) { var str cc.sys.localStorage.getItem(key); if (str) { return JSON.parse(str); } return defaultValue; } }; module.exports SaveManager;用法是在 GameData 的 onLoad 里读在 addScore 和关卡切换时写// 在 GameData.js 里 onLoad: function () { // ... 前面的常驻节点逻辑 this.highScore SaveManager.load(highScore, 0); }, addScore: function (value) { this.score value; if (this.score this.highScore) { this.highScore this.score; SaveManager.save(highScore, this.highScore); } }cc.sys.localStorage在安卓上对应的是 SharedPreferences在浏览器上对应 localStorage。存的数据类型是字符串所以用 JSON.stringify 和 JSON.parse 做序列化。key 用英文比如 highScore、levelProgress不要用中文。注意localStorage 在安卓真机上需要应用有存储权限Cocos Creator 打包时会自动处理。如果你在浏览器预览时存了数据换到手机上是读不到的因为存储位置不同。5. 安卓打包与真机调试从构建到安装的完整链路5.1 构建 APK 前必须检查的四个配置Cocos Creator v2.0 打包安卓的入口在菜单栏的“项目 → 构建发布”。选 Android 平台填包名选 API Level然后点构建。但直接点构建大概率会报错因为有几个配置必须先改。第一个是包名。格式是 com.你的名字.游戏名比如 com.zhangsan.platformer。不要用 com.example有些应用商店会拒。第二个是 Target API Level。课程设计里选 Android 5.0 以上就行对应 API 21。太低了有些新手机装不上太高了老手机跑不了。第三个是屏幕方向。2D 横版闯关选 Landscape竖屏选 Portrait。这个在构建面板的“方向”里勾。第四个是渲染模式。v2.0 默认用 WebGL但有些老安卓机 WebGL 支持不好。如果你发现真机上黑屏在构建面板里把渲染模式改成 Canvas兼容性更好但性能差一点。构建完成后Cocos Creator 会在 build 文件夹下生成一个 android 工程。用 Android Studio 打开这个工程连上手机点运行就能装到手机上。如果你没有 Android Studio也可以用命令行cd build/android ./gradlew assembleDebug生成的 APK 在 build/android/app/build/outputs/apk/debug/ 下面。用数据线传到手机在文件管理器里点安装。第一次安装需要在手机设置里允许“安装未知来源应用”。5.2 真机调试用 cc.log 和 Chrome 远程调试游戏在电脑上跑得好好的装到手机上就闪退或者卡住这是课程设计里最常见的翻车现场。调试方法有两个。第一个是在代码里打日志用cc.log(player pos: this.node.x , this.node.y)。然后在 Android Studio 的 Logcat 里过滤 cocos 关键字就能看到输出。注意 cc.log 在发布版本里会被去掉调试版本才有。第二个是用 Chrome 远程调试。手机用 USB 连电脑打开游戏的调试版本然后在 Chrome 地址栏输入 chrome://inspect找到你的设备点 inspect 就能像调网页一样调游戏。这个功能在 Cocos Creator v2.0 的 WebGL 渲染模式下可用Canvas 模式不支持。真机上最常见的三个问题一是资源加载失败通常是路径大小写问题Windows 不区分大小写但安卓区分二是触摸事件偏移通常是 Canvas 的适配模式没设对三是帧率低通常是同屏节点太多或者用了太多透明图片。资源路径统一用小写适配模式用 Fit Height 或 Fit Width同屏节点控制在 50 个以内基本能解决。提示每次改完代码重新构建 APK 很慢可以先用浏览器预览调好逻辑最后再打包。浏览器预览用 Chrome 的开发者工具和真机调试体验接近。6. 用对象池优化金币和子弹一个让帧率翻倍的技巧课程设计做到后期你可能会发现同屏金币一多手机就开始发烫、掉帧。这不是手机不行是你在频繁地创建和销毁节点。Cocos Creator v2.0 提供了cc.NodePool对象池组件专门解决这个问题。对象池的思路是金币被吃掉的时候不销毁而是放回池子里需要新金币的时候从池子里取而不是重新 instantiate。这样避免了频繁的内存分配和垃圾回收。// CoinPool.js cc.Class({ extends: cc.Component, properties: { coinPrefab: { default: null, type: cc.Prefab }, poolSize: 20 // 池子初始大小 }, onLoad: function () { this.coinPool new cc.NodePool(CoinPool); for (var i 0; i this.poolSize; i) { var coin cc.instantiate(this.coinPrefab); this.coinPool.put(coin); } }, getCoin: function () { var coin null; if (this.coinPool.size() 0) { coin this.coinPool.get(); } else { coin cc.instantiate(this.coinPrefab); } return coin; }, recycleCoin: function (coin) { this.coinPool.put(coin); } });new cc.NodePool(CoinPool)创建一个对象池参数是池子的名字用于调试时区分。pool.put(coin)把节点放回池子节点会被自动从父节点移除并设为不可见。pool.get()从池子里取一个节点如果池子空了会返回 null所以代码里做了判断空了就重新 instantiate。在金币的碰撞回调里不要用destroy()改成调用对象池的 recycleCoin// Coin.js cc.Class({ extends: cc.Component, properties: { coinPool: { default: null, type: cc.Node } }, onCollisionEnter: function (other, self) { if (other.node.group player) { // 加分逻辑... var pool this.coinPool.getComponent(CoinPool); pool.recycleCoin(this.node); } } });参数方面poolSize 设成同屏最大金币数的 1.5 倍比较合适。比如一关最多同时出现 10 个金币池子设 15 到 20。太小了会频繁 instantiate太大了浪费内存。我自己的习惯是任何会反复出现的节点——金币、子弹、敌人、特效——都走对象池。这个习惯让我的课程设计在红米 Note 这种千元机上也能稳定 60 帧。对象池的坑在于放回池子的节点如果还挂着定时器或者动画要先停掉否则取出来的时候状态是乱的。我一般会在 recycle 之前调coin.stopAllActions()和coin.unscheduleAllCallbacks()。希望帮到你。本文还有配套的精品资源点击获取