Cocos Creator 既是一款高效、轻量、免费开源的跨平台 2D&3D 图形引擎,也是一个实时 2D&3D 数字内容创作平台。拥有高性能、低功耗、流式加载、跨平台等诸多优点,您可以用它来创作游戏、车机、XR、元宇宙等领域的项目。本文将详细介绍cocos creator 入门常用知识。
1. 编辑环境配置
安装API 适配插件
- 开发者 -> VS Code 工作流 -> 安装 VS Code 扩展插件
- 该操作会将 Cocos Creator API 适配插件安装到 VS Code 全局的插件文件夹中
- 这个操作只需要执行一次,如果 API 适配插件更新了,则需要再次运行来更新插件
- 安装成功后在 控制台 会显示绿色的提示:VS Code extension installed to ...。
- 这个插件的主要功能是为 VS Code 编辑状态下注入符合 Cocos Creator 组件脚本使用习惯的语法提示。 ** 生成智能提示数据 **
- 开发者 -> VS Code 工作流 -> 更新 VS Code 智能提示数据
- 该操作会将根据引擎 API 生成的 creator.d.ts 数据文件复制到项目根目录下
- 操作成功时会在 控制台 显示绿色提示:API data generated and copied to ...
- 对于每个不同的项目都需要运行一次这个命令
2. 场景
- 预加载场景: cc.director.preloadScene('GameScene')
- 切换场景: cc.director.loadScene('GameScene')
3. 节点
获取
-
当前节点 this
-
组件所依附的节点 this.node
-
节点的父节点this.node.parent
-
节点的子节点数组 this.node.children
-
通过节点名获取子节点 this.node.getChildByName('Node3')
获取其他节点
- 1 .声明
properties: {
node5: cc.Node
}
-
- 拖拽节点到声明的节点中
删除
removeFromParent() 解除父子关系
destroy()删除该节点
添加
new --> addChild
onLoad () {
let node8 = new cc.Node()
node8.name = 'node-8'
// 将当前node8添加到当前节点
this.node.addChild(node8)
console.log(node8.name) // node-8
}
4. 组件
添加 addComponent
移出 removeComponent
获取 getComponent
onLoad () {
let sprite = this.node.addComponent(cc.Sprite)
this.node.removeComponent(cc.Sprite)
this.node.getComponent(cc.Sprite)
}
5. 动作Action
-
1: Action类是动作命令,我们创建Action,然后节点运行action就能够执行Action的动作;
-
2: Action分为两类: (1) 瞬时就完成的ActionInstant, (2) 要一段时间后才能完成ActionIntervial;
-
3: cc.Node runAction: 节点运行action;
-
4: cc.moveTo, cc.moveBy To: 目标 By: 变化
-
5: cc.roateBy, cc.rotateTo,
-
6: cc.scaleBy, cc.scaleTo,
-
7: cc.fadeOut(淡出), cc.fadeIn(淡入): cc.fadeTo();
-
8: cc.callFunc, cc.delayTime
-
9: cc.sequnce, cc.repeat, cc.repeatForever
-
10: Action easing(缓动的方式): 加上缓动特效, cc.easeXXXXX查看文档设置自己想要的缓动对象
-
11: stopAction: 停止运行action
-
12: stopAllActions: 停止所有的action;
-
时间间隔动作 移动 moveTo 旋转 rotateTo 缩放 scaleTo 渐隐 fadeOut
this.node.runAction(
cc.moveTo(1, cc.v2(500, 500)) // 一秒钟移动到(500, 500)坐标处
cc.rotateTo(1, 180) // 一秒钟旋转180度(+-180 顺+ 逆-)
cc.scaleTo(1, 2, 2) // 一秒钟x轴y轴放大两倍
cc.fadeOut(1) // 1s 渐隐
)
- 容器动作 顺序执行动作 sequence 同步执行动作 spawn 重复执行动作 repeat 永远重复动作 repeatForever 修改动作速率 speed
- 即时动作 执行回调函数 callFunc
缓动动作
action.easing(cc.easeBackIn())
- easeBackIn 是在相反的方向缓慢移动,然后加速到正确的方向
- easeBackOut 快速移动超出目标,然后慢慢回到目标点。
onLoad () {
this.node.runAction(
cc.sequence(
cc.moveTo(1, cc.v2(500, 500)).easing(cc.easeBackIn()),
cc.fadeOut(2),
cc.callFunc(this.callback, this, {hello: 'world'})
)
)
},
callback: function(tagetNode, arg) {
console.log(tagetNode) // 节点
console.log(arg) //{hello: "world"}
},
6. 事件
发射和监听
- 监听 on
除了使用 on 监听,我们还可以使用 once 方法
once 监听在监听函数响应后就会关闭监听事件
- 监听对应的触摸事件: 向引擎底层注册一个回调函数,当有触摸事件发生的时候调用
回调函数
/*
回掉函数的格式 function(t) --> cc.Touch对象触摸事件对象 {触摸信息,事件信息}
call --> this, this指向谁就是这个target;你要绑那个对象作为你回掉函数的this, 可以为空
function () {}.bind(this);
*/
关闭 off
off 方法的 参数必须和 on 方法的参数一一对应,才能完成关闭 移除target上所有的注册事件: this.node.targetOff(this); 发射 emit
在 emit 函数的第二个参数开始传递事件参数(最多只支持传递 5 个事件参数) 派送 dispatchEvent
cc.Class({
extends: cc.Component,
properties: {
node4: cc.Node,
node5: cc.Node
},
onLoad () {
this.node.on('枪声', this.rush, this.node4)
this.node.on('枪声', this.escape, this.node5)
this.node.emit('枪声', {hello: 'world'})
},
rush: function (obj) {
console.log(this.name, 'rush') // node4 rush
console.log(obj, 'rush') // {hello: "world"} "rush"
this.runAction(
cc.moveTo(1, 500, 0)
)
},
escape: function (obj) {
console.log(this.name, 'escape') // node5 rush
console.log(obj, 'escape') // {hello: "world"} "escape"
this.runAction(
cc.moveTo(1, 0, 500)
)
},
start () {}
});
-
触摸事件
touchstarttouchmovetouchendtouchcancel -
停止事件传递:
t.stopPropagationImmediate()
cc.Class({
extends: cc.Component,
properties: {
},
// t: --> cc.Touch触摸的位置: 屏幕坐标,左下角(0, 0); getLocation();
onTouchMove: function(t) {
// 停止事件传递
t.stopPropagationImmediate();
// 位置
var w_pos = t.getLocation(); // cc.Vec2 {x, y}
// 距离上一次触摸变化了多少;
var delta = t.getDelta(); // x, y各变化了多少cc.Vec2(x, y)
this.node.x += delta.x;
this.node.y += delta.y;
},
// use this for initialization
onLoad: function () {
this.node.on('touchmove', this.onTouchMove, this)
// 移除
// this.node.off('touchmove', this.onTouchMove, this);
}
});
- 鼠标事件
mousedownmouseentermousemovemouseleavemouseupmousewheel - 键盘事件
keydownkeyup - cc.KEY : 获取所有keyword以及对应的keycod 向引擎注册一个事件类型的回调函数
- cc.systemEvent 小写开头,不是大写, 大写SystemEvent类, systemEvent 全局一个实例
onLoad () {
cc.systemEvent.on('keydown', this.onKeyDown, this) // 键盘
},
onKeyDown (e) {
console.log(cc.KEY)
}
7. 坐标转换
- 全局坐标系位置 location = e.getLocation()
- 全局 --转换成–> 相对于this.node this.node.convertToNodeSpaceAR(location)
- 全局 --转换成–> 相对于this.node的父节点
this.node.parent.convertToNodeSpaceAR(location)
onLoad () {
// this.node.on('touchstart', this.onTouchStart, this)
cc.find('node1').on('touchstart', this.onTouchStart, this)
},
onTouchStart: function (e) {
// console.log(e.getLocation()) // Vec2 {x: , y: } 全局坐标系位置
let location = e.getLocation()
// 全局 --转换成--> 相对于this.node
let locationOfThisNode = this.node.convertToNodeSpaceAR(location)
// 全局 --转换成--> 相对于this.node的父节点
let locationOfThisNodeParent = this.node.parent.convertToNodeSpaceAR(location)
// 赋值
this.node.position = locationOfThisNodeParent
}
8. 预制体Prefab
步骤
- 将要复制的节点拖到资源管理器
- 声明预制体node5Prefab
- 实例化该预制体instantiate
- 将预制体添加到节点
// 浅拷贝
properties: {
node5Prefab: cc.Prefab // 声明
},
onLoad () {
let node5Copy = cc.instantiate(this.node5Prefab) // 实例化(复制)
this.node.addChild(node5Copy) // 添加
}
9. 全局变量
- window.xxx
onLoad () {
window.globalVar = {
hello: 'word'
}
},
start () {
console.log(globalVar) //{hello: "word"}
}
- require // global_module
let obj = {
name: 'cc',
age: 16
}
let str = 'string'
module.exports = {
obj,
str
}
// components
cc.Class({
extends: cc.Component,
properties: {
},
onLoad () {
let global = require('global_module')
console.log(global.str) // string
},
start () {
}
})
- statics
let Component3 = cc.Class({
extends: cc.Component,
properties: {
},
statics: {
statics3Num: 0
},
onLoad () {
Component3.statics3Num ++
},
start () {
console.log(Component3.statics3Num)
}
});
- addPersistRootNode
cc.Class({
extends: cc.Component,
properties: {
},
onLoad () {
// 将this.node独立 (当前this.node的name为node3)
cc.game.addPersistRootNode(this.node)
// 获取该独立于场景的节点
let node3 = cc.director.getScene().getChildByName('node3')
// 移除
// cc.game.removePersistRootNode(this.node)
// 切换场景
cc.director.loadScene('scene3')
},
start () {
}
});
- localStorage
cc.sys.localStorage.setItem('key', 'value')
cc.sys.localStorage.getItem('key')
10. 计时器
schedule
unschedule
scheduleOnce
onLoad () {
this.schedule(this.timerCount, 1) // 每一秒执行一次timerCount
this.unschedule(this.timerCount) // 停止
this.scheduleOnce(this.timerCount) // 回调延迟一帧
},
timerCount () {
console.log(1)
},
11. 动画
步骤
- 添加Animation组件
- 添加Animation Clips 编辑动画
- 选中Clip --> Add Property --> 拖拽图片 —> 选择WrapMode
- 添加js组件
- 创建 --> 声明动画 --> 拖拽节点( 赋值 )
- 保存
- 动画数据 获取
var anim = this.getComponent(cc.Animation);
// play 会返回关联的 AnimationState
var animState = anim.play('run');
// 或是直接获取
var animState = anim.getAnimationState('run');
动画信息
clip name speed duration time repeatCount wrapMode isPlaying isPaused frameRate
var anim = this.getComponent(cc.Animation);
var animState = anim.play('run')
// 获取动画的循环模式
var wrapMode = animState.wrapMode
循环
var animState = anim.play('run');
// 设置循环模式为 Normal
animState.wrapMode = cc.WrapMode.Normal;
// 设置循环模式为 Loop
animState.wrapMode = cc.WrapMode.Loop;
// 设置动画循环次数为2次
animState.repeatCount = 2;
// 设置动画循环次数为无限次
animState.repeatCount = Infinity;
动画事件
play stop pause resume(恢复播放) lastframe finished
实例
// 注册
animation.on('play', this.onPlay, this);
// 取消注册
animation.off('play', this.onPlay, this);
// 对单个 cc.AnimationState 注册回调
var anim1 = animation.getAnimationState('anim1');
anim1.on('lastframe', this.onLastFrame, this);
12. 碰撞
步骤
-
添加碰撞组件
-
编辑Group
-
编辑js组件
-
获取碰撞管理器 cc.director.getCollisionManager
-
注册回调, 如果有碰撞则回调 manager.enabled = true
-
碰撞函数 onCollisionEnter onCollisionStay onCollisionExit
cc.Class({
extends: cc.Component,
properties: {
},
onLoad () {
// 获取碰撞管理器
let manager = cc.director.getCollisionManager()
// 注册回调, 如果有碰撞则回调
manager.enabled = true
// debug
manager.enabledDebugDraw = true
this.node.on('touchmove', this.onTouchMove, this)
},
onTouchMove (e) {
console.log('move')
this.node.position =
this.node.parent.convertToNodeSpaceAR(e.getLocation())
},
// 三个碰撞函数
onCollisionEnter (other, self) {
console.log('enter')
},
onCollisionStay (other, self) {
console.log('stay')
},
onCollisionExit (other, self) {
console.log('exit')
}
})
13. 音乐音效
背景音乐
添加AudioSource组件 音效
声明
audio: {
type: cc.AudioClip,
default: null
}
播放
cc.audioEngine.play(audio)
// cc.audioEngine.play(audio, false, 0.2) // (audio, loop, volume)
14. 打包到微信小游戏
代码包问题
代码包超过4MB不能发布问题
-
将打包生成的res文件放线上
-
修改根目录下main.js里的资源导入路径
libraryPath: 'res/import' --> libraryPath: 'http://192.168.../res/import'
cc.AssetLibrary.init({
libraryPath: 'http://192.168.../res/import',
rawAssetsBase: 'http://192.168.../res/raw-',
rawAssets: settings.rawAssets,
packedAssets: settings.packedAssets,
md5AssetsMap: settings.md5AssetsMap,
subpackages: settings.subpackages
});