ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Cocos Creator v2.0 2D闯关安卓游戏课程设计:从搭建到打包全流程

Cocos Creator v2.0 2D闯关安卓游戏课程设计:从搭建到打包全流程 简介一款基于Cocos Creator v2.0的2D闯关安卓游戏课程设计资料包已发布面向计算机科学与技术、软件工程、人工智能等专业的在校师生。内含可运行程序源码、系统设计方案、功能演示视频和配套讲解课件覆盖二维场景渲染、物理引擎集成、交互逻辑设计等移动端游戏开发核心环节适用于课程实践、毕业设计或项目实训。包内共375个文件以png美术素材、js逻辑脚本、anim角色动画、meta配置信息、md文档、docx系统开发说明、mp4操作演示和pptx课件为主压缩包整体约8.93MB目录结构清晰。目前已有39人学习下载适合希望系统梳理Cocos Creator安卓游戏项目的学习者。资源中的角色动作与关卡运行均经过多轮测试核心玩法稳定。附带的系统开发说明文档可帮助快速理解环境配置和项目架构具备编程基础的读者还可在现有框架上扩展自定义关卡或优化角色行为具有较好的参考与二次开发价值。1. Cocos Creator v2.0课程设计先跳出“做游戏”的执念回到“交作业”的及格线拿到《基于Cocos Creator v2.0的2D闯关安卓游戏开发课程设计》这个题目大多数人第一反应是去下个现成源码、换个皮就交。我见过太多这样翻车的同学答辩时老师一句“这个跳跃力度为什么给 600依据是什么”人就愣住了。课程设计和商业项目是两种玩法——商业项目看留存和付费课程设计看“需求能不能讲清、代码能不能改、演示能不能跑”。所以这篇笔记想聊的不是怎么把游戏做得多好玩而是怎么用 Cocos Creator v2.0 把一个2D闯关安卓游戏从零搭起来一路走到打包 APK 装进手机里并且每一步都有东西可讲。适合三类人要交课程设计的学生、第一次接触 Android 打包的新手、想快速验证 2D 闯关玩法的独立开发者。2. 用Cocos Creator v2.0搭2D闯关地基节点树、物理引擎和动画组件的正确姿势Cocos Creator v2.0 不是新版本但这恰恰是选它的理由。你搜“Cocos Creator 2D闯关教程”十篇里有八篇是 v2.x 时代的报错也能搜到对应答案v3.x 改了大量 API照着 v2 教程写会一路踩坑。课程设计求稳v2.0 够用。2.1 场景节点树先排清楚后面写代码不迷路闯关游戏场景里至少要有这几层背景层、地图层、角色层、敌人层、UI 层、全局控制节点。我一般会这样建节点树Canvas ├── GameRoot // 空节点挂全局控制脚本 │ ├── Background // 背景普通节点加 Sprite │ ├── MapLayer // Tilemap 地图挂这里 │ ├── EnemyLayer // 所有敌人预制体挂这里方便统一管理 │ └── Player // 角色节点挂 RigidBody 控制脚本 └── UIRoot // Canvas 下单独一层血条、金币、关卡提示有个容易被忽略的点v2.0 的 Canvas 默认会带一个 Camera 子节点。角色节点如果直接放在 Canvas 下摄像机跟随逻辑简单但物理碰撞对节点层级有要求——刚体节点的父节点不要做频繁位移否则物理位置会偏移。我一般把 Player 单独放一层不跟 UI 混在一起。设计分辨率建议设 1280x720 或 960x540横版闯关多数是这个比例。在“项目设置—项目数据—设计分辨率”里改适配策略选 SHOW_ALL边界留黑边也比裁掉内容强。2.2 启用物理引擎和重力先用一个全局脚本把环境稳住2D 闯关离不开碰撞和重力。v2.0 内置了两套物理Builtin 只做碰撞检测不做物理模拟轻量但弹跳、摩擦都没有Box2D 是完整刚体模拟闯关游戏大多选它。物理引擎的启用不是拖个组件就行要在一个最先加载的场景里做全局初始化。我习惯新建一个GameRoot节点挂GameManager.js在onLoad里一次性把物理环境配好原因后面避坑章会细说。// GameManager.js cc.Class({ extends: cc.Component, onLoad() { // 启用 Box2D 物理系统必须在任何物理组件使用前完成 let physicsManager cc.director.getPhysicsManager(); physicsManager.enabled true; physicsManager.gravity cc.v2(0, -600); // y 轴负方向为重力方向 // 调试开关打包前关掉编辑态打开能看碰撞体边界 physicsManager.debugDrawFlags cc.PhysicsManager.DrawBits.e_jointBit; } });逻辑说明enabled true是开启物理模拟的总开关不开则所有刚体都当静态物体处理gravity用向量表示方向(0, -600)表示垂直向下。600 这个数不是标准答案它和场景的像素尺度、角色尺寸强相关——角色要是 30 像素高600 会把它砸得贴地要是 200 像素高600 又显得飘。我的习惯是先给 -600跑起来再调这一步最好做成个可配置参数别写死在代码里。调试标志debugDrawFlags编辑态开着能看到角色周围一圈碰撞轮廓线方便你对着地图检查碰撞体是否贴合。打包前务必关掉否则手机性能会掉一截而且玩家能看到不美观的线框。这里有个经验物理初始化写成独立脚本并放在第一个加载场景比在每个角色脚本里各自设置要稳。后面第五章的“真机和编辑器表现不一致”就是在这里埋的坑。2.3 动画状态机和动画帧事件让角色动起来而不是“瞬移”角色动画是闯关游戏的门面。v2.0 里动画依靠 Animation 组件加 AnimationClip 资源实现。最少需要四个 Clipidle站立、run跑、jump跳、dead死亡。制作流程是美术序列帧拖入编辑器生成 Clip再把 Clip 挂到 Animation 组件上。代码里播放用anim.play(run)。// PlayerController.js 里的动画切换方法 playState(stateName) { let anim this.getComponent(cc.Animation); if (!anim) return; // 同一个状态不重复播放避免每帧调用导致动画反复从第一帧开始 if (anim.getAnimationState(stateName).isPlaying) return; anim.play(stateName); }参数说明getAnimationState返回的是这个 Clip 的播放状态对象isPlaying为 true 就说明已经在播此时不必再play一次。很多人写跳跃时每帧都调用play(jump)结果动画永远卡在跳跃第一帧——这就是没加这个判断。动画和逻辑的衔接有两个方式状态判断和帧事件。状态判断是给每个动画一个状态名角色在哪个状态就放哪段动画帧事件适合做跳跃踩地音效、刀光特效这类需要在某一帧触发的事。在动画编辑器里选中某一帧右键添加帧事件代码里用onAnimationEvent接收。注意帧事件回调的本质是同步调函数不要在回调里做耗时操作比如读文件、加载资源会造成明显卡顿。3. 闯关逻辑的三件套角色控制、Tilemap 关卡和存档模块怎么写才不出错地基搭好接下来是闯关游戏的核心玩法部分。三件套不是“三个功能”这么简单而是三条线角色怎么动、关卡怎么摆、进度怎么记。每一条拆开都是 50 行代码以内的事合起来要是没有清晰结构就是后半夜调 BUG 的起点。3.1 角色控制器一个脚本管住移动、跳跃和落地判定v2.0 里的角色节点我一般挂三样东西RigidBody刚体、Collider碰撞体、PlayerController控制脚本。刚体负责受重力、被碰撞体推开碰撞体负责触发伤害判定控制脚本只负责听键盘输入并给刚体施加影响。三种职责分开以后改任何一个都动不到另外两个。// PlayerController.js cc.Class({ extends: cc.Component, properties: { speed: 300, // 水平移动速度单位 px/s jumpForce: 620, // 跳跃瞬间的纵向速度单位 px/s maxJumpCount: 1 // 跳跃次数改 2 就是二段跳 }, onLoad() { // 拿到刚体组件后续所有操作都走刚体而不是直接改节点坐标 this.rigidBody this.getComponent(cc.RigidBody); this.jumpCount 0; this.keys {}; cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this); cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this); }, onKeyDown(e) { this.keys[e.keyCode] true; }, onKeyUp(e) { this.keys[e.keyCode] false; }, update(dt) { // 水平方向A/D 或左/右方向键给刚体一个恒定的水平速度 let vx 0; if (this.keys[cc.macro.KEY.a]) vx -this.speed; if (this.keys[cc.macro.KEY.d]) vx this.speed; this.rigidBody.linearVelocity cc.v2(vx, this.rigidBody.linearVelocity.y); // 跳跃单独监听空格键不放在 update 里轮询 if (this.keys[cc.macro.KEY.space]) { this.tryJump(); } }, tryJump() { if (this.jumpCount this.maxJumpCount) return; // 跳跃是瞬间改纵向速度而不是给一个持续向上的力 this.rigidBody.linearVelocity cc.v2(this.rigidBody.linearVelocity.x, this.jumpForce); this.jumpCount; }, // 刚体碰撞回调碰到地面层就重置跳跃次数 onBeginContact(contact, self, other) { if (other.node.group ground) { this.jumpCount 0; } } });逻辑说明移动不是直接改node.x而是设置刚体的linearVelocity线速度。如果你直接改坐标刚体的物理模拟会和你的手动设置打架角色会在碰撞体里抖来抖去。linearVelocity的x取输入方向乘以 speedy保留刚体当前纵向速度这样下落和重力不受影响。跳跃同理本质是瞬间把纵向速度设为jumpForce这个正数让角色获得向上的初速度然后重力再把速度拉下来。参数推荐speed 在 200~400 之间分辨率为 1280x720 时 300 是个舒服的值jumpForce 大一点小一点手感完全不同620 大致能跳两到三个角色身高具体还要看你角色碰撞体高度。maxJumpCount 1是单段跳想要二段跳就改成 2很多动作闯关喜欢用这个参数调节难度——把怪物的血量调高不如把玩家的跳跃次数调低来得明显。onBeginContact是刚体的接触回调只有碰撞双方至少有一方是刚体时才会触发。重置跳跃次数的时机要选在“脚底碰到地面”而不是“身体任何部位碰到地面”否则角色侧着蹭墙也能二段跳。常见做法是给地面和墙体分不同的碰撞分组只对地面分组重置跳跃数或者用一个放在角色脚下的子节点做专门的触地检测。3.2 用 Tilemap 搭关卡地图文件、碰撞层和摄像机边界一次说清闯关关卡不用一个个摆方块精灵用 Tilemap 效率高得多。v2.0 里是配合 Tiled 地图编辑器使用在 Tiled 里画好地图导出成.tmx文件包含地图数据加图片图集然后把.tmx拖进 Cocos Creator 资源管理器场景里挂一个 TiledMap 组件引用该文件。Tiled 里画地图时把格子大小定成 32x32 或 64x64格子越小地图越精细但碰撞体数量也越多。我一般用 32图集纹理一张尽量控制在 2048x2048 以内避免安卓低端机纹理内存吃紧。Tiled 里图层不建议只画视觉层一定要单独画一个碰撞层把有阻挡的格子填上。导出后在 Cocos 里给 TiledMap 节点加碰撞或者把 Tiled 的对象层导出成多个矩形碰撞体。习惯做法是在 Tiled 里用对象层画好障碍物的矩形范围导出后在 Cocos 里脚本批量读取对象层数据生成静态碰撞体这样地图有多少块都不用手动拖碰撞节点。// MapLoader.js – 读取 Tiled 对象层并生成碰撞体 cc.Class({ extends: cc.Component, properties: { tiledMap: cc.TiledMap }, onLoad() { // 拿到对象层层名要和 Tiled 里一致 let objGroup this.tiledMap.getObjectGroup(collision); if (!objGroup) return; let objects objGroup.getObjects(); objects.forEach(obj { // 每个对象生成一个矩形碰撞体挂到地图节点下 let collider this.node.addComponent(cc.PhysicsBoxCollider); collider.size cc.size(obj.width, obj.height); collider.offset cc.v2(obj.x obj.width / 2, obj.y obj.height / 2); collider.sensor false; // 实体碰撞角色会被挡住 }); } });逻辑说明getObjectGroup(collision)按名字取对象层getObjects()返回该层所有矩形对象每个对象有x、y、width、height属性。生成的碰撞体全部挂在地图节点下属于静态刚体没有 RigidBody 就不参与物理模拟但能挡人。sensor false表示这是实体玩家碰上会受阻如果做成机关区域、传送门这类不需要阻挡的效果才会设为sensor true。碰撞体生成后地图就“能站人”了但摄像机还不会跟着角色跑。给摄像机挂一个跟随脚本注意边界限制不然镜头会一路跑到地图外面的空白区域。// CameraFollow.js – 挂在主摄像机上 cc.Class({ extends: cc.Component, properties: { target: cc.Node, // 拖入角色节点 minX: 0, maxX: 640, // 地图的水平范围按你的地图尺寸填 minY: 0, maxY: 360 }, lateUpdate() { if (!this.target) return; // 世界坐标转节点坐标保证跟随平滑 let pos this.node.position; pos.x cc.misc.clamp(this.target.x, this.minX, this.maxX); pos.y cc.misc.clamp(this.target.y, this.minY, this.maxY); this.node.position pos; } });参数说明数值范围为地图边界比如 1280x720 分辨率下横向 100 格、每格 32 像素的地图maxX 就是 3200视具体地图而定。cc.misc.clamp把角色坐标限制在地图区间内角色跑出边界时镜头停在边界处不会露出黑屏外的空场景。摄像机跟随用lateUpdate而不是update因为update里先跑完角色物理和坐标更新lateUpdate再接住最新坐标避免“镜头比角色慢一帧”的拖拽感。3.3 敌人巡逻、玩家受击和死亡重生三个最常见的编码误区敌人最简单的形态是“左右巡逻 碰到玩家造成伤害”。巡逻逻辑完全不依赖物理就是一个脚本控制节点在起点两侧往返。常见误区是把敌人也做成刚体并设置速度结果两个刚体对撞把敌人弹飞——敌人的移动千万别用 RigidBody直接改坐标就行。// EnemyPatrol.js cc.Class({ extends: cc.Component, properties: { patrolDistance: 150, // 向左/向右各巡逻多少像素 speed: 80 // 巡逻速度 px/s }, onLoad() { this.startX this.node.x; this.dir 1; }, update(dt) { let x this.node.x this.dir * this.speed * dt; // 超出巡逻边界就掉头 if (x this.startX this.patrolDistance) { this.dir -1; } else if (x this.startX - this.patrolDistance) { this.dir 1; } this.node.x x; } });玩家受击判定走碰撞分组把玩家设为player组敌人设为enemy组玩家刚体的onBeginContact里判断撞到的是不是enemy分组。这里有个大坑onBeginContact在碰撞的一瞬间只触发一次如果你在回调里把玩家传送到存档点可能传送后仍然贴着敌人的碰撞体下一帧立即再次触发导致血量“跳楼式”归零。解决方法是受击后加一个短暂无敌状态用计时器挡住重复回调。onBeginContact(contact, self, other) { if (other.node.group enemy !this.invincible) { this.hp--; this.invincible true; // 1 秒无敌时间期间敌人碰撞不会扣血 this.scheduleOnce(() { this.invincible false; }, 1); if (this.hp 0) { this.respawn(); } } }存档模块比你想的简单v2.0 提供cc.sys.localStorage本质是 key-value 本地存储不需要引第三方库。// 保存进度当前关卡编号和金币数量 saveProgress(levelId, coinCount) { cc.sys.localStorage.setItem(levelId, levelId); cc.sys.localStorage.setItem(coinCount, coinCount); } // 读取进度取不到就返回默认值 loadProgress() { let levelId cc.sys.localStorage.getItem(levelId); return { levelId: levelId ? parseInt(levelId) : 1, coinCount: parseInt(cc.sys.localStorage.getItem(coinCount) || 0) }; }注意getItem拿到的永远是字符串存进去的数字拿出来要手动parseInt。另一个坑是课程设计演示时如果老师要求“清空进度重新玩”你要在设置界面或游戏开场加一个“重置存档”按钮否则老师会当场掏手机让你找怎么删数据。4. Cocos Creator v2.0 打包安卓 APK环境配置、签名和真机安装全流程2D 闯关游戏在编辑器里跑得欢不算完课程设计验收时老师大概率要求你把 APK 装到安卓手机上现场演示。打包安卓是 Cocos Creator v2.0 的老大难多数问题出在环境配置而不是代码上。4.1 构建前的环境三件套JDK、Android SDK、NDKv2.0 打包安卓走的是“Cocos 生成原生工程 Gradle 编译 APK”所以电脑上必须装好三样东西JDKJava 开发环境、Android SDK安卓开发库、NDK原生开发工具包v2.0 的安卓构建强制依赖。装好后在 Cocos Creator 菜单“偏好设置—原生开发环境”里分别填三个路径填错会在构建开始后立刻报错所以构建前先确认路径真实存在且版本匹配。SDK 路径要指到有platform-tools和build-tools的目录NDK 要指到根目录而不是toolchains子目录。这一步是血泪经验很多人路径指到 NDK 内部子目录构建器找不到版本号报错信息还看不懂。v2.0 对 NDK 版本比较挑剔太新的 NDK 反而编不过。如果你电脑上只有一个新版 NDK先测 C 那层编译动不动得了——跑一次构建就知道。课程设计时间紧建议直接装稳定版本一次通过比用新版折腾三天划算得多。4.2 构建发布面板的参数配置和签名生成打开“菜单—项目—构建发布”平台选 Android。发布路径默认在项目文件夹下build目录里生成的原生工程也在里面。面板上几个关键参数说清楚参数取值建议说明包名com.你名字拼音.游戏名Android 应用的唯一标识装到手机后不可改API Level21 以上太低了部分功能不可用太高了老手机装不上构建模式Release 优先Debug 包体积大、运行慢不适合演示构建 APK勾选不勾选只生成原生工程还要用 Android Studio 二次签名MD5 Cache勾选资源名带哈希值加快构建且避免资源替换残留签名文件是 APK 安装到手机的“身份证”。安卓要求每个 APK 必须有签名Cocos 默认有个调试签名但调试签名的 APK 有些手机装不上。课程设计建议自己生成一个正式签名。生成命令在命令行里执行keytool -genkey -alias game.keystore -keyalg RSA -keysize 2048 -validity 10000 -keystore game.keystore参数说明-alias是这个钥匙在钥匙库里的名字后面构建面板里要填对-validity 10000表示有效天数约 27 年不用担心过期-keystore是输出的文件名。执行后会交互式问你密码、姓名、组织等信息密码一定要记牢后面每次打新包都要用而且这个 keystore 文件别删丢了就再也签不了同一个包的升级版。生成后把game.keystore放到项目外单独目录别放项目里不然最后打包时会把签名文件也塞进 APK 资源里这是低级但又常见的翻车。构建面板里把签名文件路径、密码、别名填进去点击构建。第一次构建会下载 Gradle 依赖包耗时可能 20 分钟以上不是死机耐心等。构建完成后 APK 会输出到build/android目录下文件名一般是游戏名-release.apk。4.3 真机安装和运行日志排查APK 拷到手机有两种方式数据线 adb或者直接微信/QQ 传给手机。演示用后者省事但调试阶段推荐 adb因为能看到运行日志定位白屏和崩溃全靠这个。adb install -r build/android/你的游戏-release.apk-r表示覆盖安装保留手机上的存档数据。安装成功后先别急着点图标先在电脑上开一眼日志adb logcat -s cocos AndroidRuntime | grep -iE error|crash|exception这段命令把日志里带安卓崩溃信息、Cocos 报错的行过滤出来直接滚屏打印。游戏运行时崩了日志里能找到具体报错文件和方法名。注意一点APK 安装出现“解析包错误”时八成不是代码问题而是打包时资源路径异常导致 APK 被 Android 系统判定为损坏回构建面板勾选“清理”后重打。真机调试和模拟器最大的差别在于渲染和内存。模拟器上纹理占用和 GPU 驱动跟真机差太远游戏在模拟器能跑、真机一进关卡就闪退的情况我在课程设计里见过太多次。结论只有一个尽早用真机测别等到答辩前一天。5. 课程设计验收前的避坑5 个让演示当场翻车的经典问题下面是按“现象 → 原因 → 解决”写的高频问题。每一条都是真实发生过的前两条尤其值得注意因为它们都会在答辩现场直接让游戏“黑屏/闪退”而你几乎无法当场救场。5.1 打包后的 APK 首屏白屏或黑屏现象浏览器里跑得好好的打出来的 APK 装上后启动就黑屏过几秒自动闪退。原因多数是脚本运行时报错。编辑器和浏览器环境报错会弹控制台安卓上 JS 报错不会弹窗直接黑屏。最常见的报错源是用了浏览器专属 API比如window.alert或者资源路径大小写不对。排查先连 adb 跑一次adb logcat -s cocos AndroidRuntime看日志如果是脚本报错把window.onerror的报错信息打印到日志里。解决临场最快的办法是找出报错脚本改掉长期做法是打包前在编辑器里用“浏览器预览”把所有关卡跑一遍重点看控制台有没有红色报错。5.2 真机上角色物理行为和编辑器完全不一样现象编辑器里角色跳跃高度刚好装到手机上下落极慢或者直接穿墙。原因物理引擎的初始化时机和重力设置没有在游戏最早期场景执行。你在编辑器里看到的重力可能来自预览时某个脚本的初始化打 APK 后启动场景加载顺序不同重力参数没生效Box2D 默认重力就变成它的规范值导致体感全变。解决把物理引擎启用和重力设置放到一个常驻场景的onLoad里也就是第二章的GameRoot并确认该场景在“项目设置—参与构建的场景”里排在第一位。顺带检查角色刚体的gravityScale属性别不小心改成了 0那会让角色像在太空里走路。5.3 改完代码重新打包装到手机上还是旧版现象代码明明改了重新构建的 APK 装上还是老功能。原因Cocos 构建有增量缓存某些旧的脚本和资源文件残留手机端系统也可能复用了安装缓存。解决构建发布面板勾选“清理”后重新构建它会清掉build目录重来手机卸载旧版本后再安装新 APK不要使用覆盖安装。这个“做完了没生效”的问题最容易在答辩前一晚制造恐慌熟练以后固定流程清构建 → 卸载手机旧包 → 装新包三分钟搞定。5.4 安卓返回键一按就退出游戏现象演示时老师随手按了手机返回键游戏瞬间退出回桌面进度没存场面尴尬。原因v2.0 默认没有处理安卓返回键系统把它当“结束 Activity”处理。解决监听系统返回键事件弹出一个确认框确认后才退出。cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this); onKeyDown(e) { if (e.keyCode cc.macro.KEY.back) { // 弹自定义确认框不然就直接退出 this.showExitDialog(); } }参数说明cc.macro.KEY.back是安卓返回键的键码浏览器里对应退格键不会误触。注意在 v2.0 里该事件要在onLoad注册、onDestroy注销否则场景销毁后回调还在会报“调用已销毁对象的方法”错误。5.5 图片或字体在安卓上显示异常现象编辑器里正常的游戏标题字体打包后变成方块或默认宋体高清图在手机上发虚。原因v2.0 的资源加载在 web 平台不区分大小写但安卓原生环境区分。如果你资源文件名是GameTitle.png代码里写成gametitle.png浏览器预览没事APK 里就加载失败表现出来就是字体丢失或图片空白。解决项目里所有资源路径统一小写字母加下划线比如game_title.png代码引用时严格一致。字体建议用系统字体或把需要的字做成图片不要指望打包时自动嵌入一套中文字体那样 APK 体积会大几 MB 且仍有缺字风险。6. 答辩前最后的打磨跑通一遍验收清单再留一条升级后路别急着交先把下面的验收清单逐条跑一遍。这条清单能让你答辩时心里有底也能防止演示到一半手滑翻车。检查项验证方法预期结果角色移动进第一关左右移动方向正确、无抖动、速度适中跳跃手感跳上平台再跳下跳跃高度合理落地不滑步碰撞阻挡角色撞墙被挡住不穿墙不卡墙缝受击处理故意碰到敌人扣血并进入无敌状态不连续扣血死亡重生血量归零回到当前关存档点进度不丢通关跳转到达终点进入下一关关卡编号正确存档恢复退出游戏重进解锁关卡和金币保留安卓返回键按返回键弹确认框不直接退出APK 安装真机全新安装不报解析包错误、无白屏走完清单后如果时间富余性价比最高的一条升级是给角色加受伤闪白和顿帧效果用 v2.0 的cc.tween几十行就能实现但视觉上会明显比隔壁同学的“原版角色”更完整。// 受击时闪白把精灵颜色切到白色0.2秒内慢慢恢复 let sprite this.getComponent(cc.Sprite); sprite.node.color cc.Color.WHITE; cc.tween(sprite.node) .to(0.2, { color: cc.Color.WHITE }, { easing: quadOut }) .to(0.1, { color: cc.Color.WHITE }) .call(() { sprite.node.color cc.Color.WHITE; }) .start();代码说明cc.tween是 v2.0 提供的补间动画接口.to(0.2, { color: ... })表示在 0.2 秒内把属性渐变到目标值。闪白的实现是先把颜色提亮变白再渐变回正常颜色比直接切黑屏或淡出淡入更有打击感。做完这些你的课程设计从“能跑”变成“能讲”。讲的时候别忘了把每一步设计决策说成“我为什么这么做”——比如重力为什么用 -600、无敌时间为什么是 1 秒、存档为什么用 localStorage 而不是数据库。这些思考过程才是课程设计的评分重点。我自己早期做过一个项目功能全跑通了答辩被问“你这里为什么没有做失败处理”当场答不上来。后来养成的习惯就是写代码前先问自己三个问题异常输入怎么办、极端操作怎么办、数据丢了怎么办。这个习惯一直带到今天。希望帮到你。本文还有配套的精品资源点击获取
返回列表