Cocos Creator界面
层级管理器:层级管理器中包含了 画布场景中所有的节点
Cocos Creator常用设置
默认脚本编辑器
Cocos HelloWorld项目目录结构
项目新建后会自动生成scene、model等文夹,以及这个文件夹对应的meta文件,cocos引擎通过meta文件来管理项目的资源。它储存了资源配置信息和资源索引,.meta文件需要一并提交到文件版本控制系统中。
asstes:项目所有资源文件
library:资源库,asstes导入之后自动生成的资源,当library被破坏时,只需将整个库删除重新生成即可。
local:本地设置文件,它存储了该项目在本地配置的信息,编辑面板位置 大小,窗口大小,位置等信息
packages:拓展插件文件夹,如需手动安装插件 可手动创建文件夹,如需卸载插件 删除对应的文件夹即可
settings:项目设置,保存项目相关设置,构建发包 菜单里的包名,场景 平台选择等
项目设置
主菜单栏–项目–项目设置,打开项目设置面板
项目设置面板常用主要是 高级设置-项目数据、高级设置-Layers两个板块
高级设置-项目数据:配置项目渲染后的效果,例如视图的尺寸、适配的方式
高级设置-Layers:图层面板;在这个添加图层,相机可以渲染指定图层内的节点,灯光可以照亮部分场景
场景
Cocos Creator是由一个个游戏场景组成的,场景是一种属性结构,他由有层级关系的节点组成的。
场景编辑器时 开发创作的核心区域,在这个地方对元素节点进行编辑
节点和组件
Cocos Creator是以组件开发为核心的,节点是承载组件的实体,我们通过将各种各样组件挂载到节点上,来让节点具有各种各样的功能。例如,在视图中不能会直接将button按钮组件放置在 场景中,必须现将其放置在节点中。
- 新建一个空项目
- 在asstes中新建一个scene文件夹用来储存场景文件并新建main场景
- 双击main场景 进入main场景
- 在主场景根节点下新建精灵单色组件
事件响应
触摸事件
TOUCH_START:手指触摸屏幕
TOUCH_MOVE:手指在屏幕上移动
TOUCH_END:手指在目标节点区域离开屏幕时
TOUCH_CANCEL:手指在目标节点区域之外离开屏幕时
注册事件
语法:node.on(事件类型,处理函数,作用域(通常是this))
this.node.on(cc.Node.EventType.TOUCH_START,callback,this)
示例
- 新建asstes/newScript.ts脚本,并添加到label上
- 打开组件脚本,在start初始化钩子中为节点注册TOUCH_START事件。
export class NewScript extends Component {
......
start() {
// 为脚本节点注册事件
this.node.on(Node.EventType.TOUCH_START, this.handleTouch, this)
}
handleTouch() {
alert("事件触发")
}
......
}
复制代码
键盘事件
键盘事件不是节点事件 他是系统级事件
KEY_DOWN:键盘按键按下
KEY_UP:键盘按键抬起
注册事件
语法:systemEvent.on(事件类型,处理函数,作用域(通常是this))
import { systemEvent, SystemEvent } from ‘cc’;
systemEvent.on(SystemEvent.EventType.KEY_DOWN, callback, this);
systemEvent.off(SystemEvent.EventType.KEY_DOWN,callback, this);
按键类型
macro.KEY
自定义事件
自定义事件是注册在节点上的
注册事件
this.node.on(事件名, 事件回调)
触发回调
方法1:这种方式只在当前节点触发不会冒泡
this.node.emit(事件名, 参数?)
方法2:这种方式会触发事件冒泡
const customEvent = new Event(事件名,参数?) //生成自定义事件
this.node.dispatch(customEvent) // 将自定义事件派发到时间流中
游戏资源
一个游戏往往由,种类繁多数量庞大的资源构成,所以管理包括图片、音频、字体、粒子、地图等多媒体资源也是一个游戏引擎的核心功能。资源的管理大概包括 资源的组织、运行、载入和清理以及资源的操作和优化等
图片资源管理
游戏的图片资源也称其为贴图、cocos不仅支持png/jpg,图集资源的导入和自动图集资源的生成
单张图片
直接将图片添加到场景中
1、在资源管理器 asstes中新建 source 文件夹储存图片资源。直接将图片拖拽进 asstes/source 中
2、在资源管理中 Ctrl+s 保存场景,生成 asstes/scene/main.scene 结构如下:
3、双击main,进入main场景。删除自带相机和灯光,将视口改为2D模式。
4、将图片的类型设为 sprite-frame并保存,将图片拖拽到场景中。
将图片挂载到精灵节点上
1、先在场景新建sprite
节点,并将图片(必须是 sprite-frame 类型)放到sprite
节点的spriteFrame
属性上
图集资源
图集(Atlas)也称为Sprite Sheet,它是一种常见的美术资源。他通过专门的工具将多个图片合成一张大图,并通过 plist等格式文件索引资源。可供CocosCreator使用的图集资源有plist和png组成。plist储存了这个图集中 每个子图片的位置、尺寸等信息,使用图集资源需要将图集的png文件和plist文件一共放进资源管理器中。
声音资源管理
游戏不仅仅是简单的界面和动画,还需要音乐音效的结合。场景中好的音效可以极大的提升用户体验。
WebAudio
在CC(coocs creator)中,加载音频的方式和图片一样,都是在资源管理器路径下添加即可。节点的属性检查器可以选择加载音频的方式,CC提供了WebAudio(默认)和DomAudio两种方式。
通过 WebAudio 方式加载音频资源,在引擎是以一个buffer的形式缓存的,该等方式特点是:兼容性好,问题少,但是占用的内存资源比较多。 示例
1、在层级管理器右击场景节点 新建空节点,并在空节点下挂载audio组件
2、将资源管理器中音频资源拖拽到audio组件的Clip属性中。渲染项目后音频成功加载到项目中(项目渲染完成需要点击一下,才会播放音频)
DomAudio
通过生成一个标准的 audio 元素来播放声音资源,缓存的就是这个 audio 元素。使用标准的 audio 元素播放声音资源的时候,在某些浏览器上可能会遇到一些兼容性问题。比如:iOS 上的浏览器不支持调整音量大小,所有 volume 相关属性将不会有效。
cocos加载音频模式默认为WebAudio,当web不支持使用WebAudio模式,引擎会自动回滚到DomAudio模式。DomAudio有很多限制,每次播放必须通过一些操作事件触发(WebAudio只需要触发一次)
强制使用DomAudio:
assetManager.loadRemote('http://example.com/background.mp3', {
audioLoadMode: AudioClip.AudioType.DOM_AUDIO,
}, callback);
复制代码
预制体
这个概念最初来源于unity,他是一种可以重复使用的游戏对象。例如:子弹、士兵、敌人、墙上的砖块
创建使用预制体
在场景新建单色精灵节点,为节点增加新的功能(碰撞系统、脚本之类)。然后将层级选择器中配置好的节点 拖拽到资源管理器成一个预制体(.prefab文件),这样我们可以将资源管理器中的预制体放入任意节点下使用
文字
CC有系统自带文字,也可以字渲染文字。CC支持的文字有:系统文字、动态字体、位图文字
系统文字
使用CC系统文字,先创建label(文本)节点,然后修改属性面板的属性
string:label节点 文字内容
useSystemFont:是否使用系统文字,默认勾选
动态文字
CC目前支持TFF格式的的动态文字,只需要将.TFF文件拖拽到资源管理器中,即可完成动态文字的导入
位图文字
动态文字不适用中文,位图文字可以解决在CC中使用中文字体的问题。
位图文字的制作
位图文字由fnt文字文件和一张png图片组成。fnt文件提供了对每一个字符小图的索引,这种格式的文件由专门的位图字体制作工具生成。常见的有:hiero、bmfont
位图字体的导入和使用
1、将位图字体的.fnt和.png一同拖进资源管理器中。
2、将.fnt文件拖拽到label节点的 font属性中。
粒子系统
用普通动画做绚丽的效果可能需要很大的代价(占用大量内存),粒子系统是一个不错的解决方案。它能发射大量细小无规则运动的粒子并高效的渲染这些粒子,比渲染单个精灵要高效的多。他可以模拟随机的烟雾、闪电、风雨、雪花掉落效果。
CC的粒子资源
CC的粒子系统可以通过Particle Designer软件进行制作,也可以通过网页在线制作 www.effecthub.com/particle2dx .
使用粒子
粒子文件也是.plist文件,里面记录了粒子发射的坐标、规则等信息。
将粒子文件拖拽进资源管理器中,新建一个粒子节点,将粒子文件拖拽到粒子节点的file属性上。
如果勾选custom选项还可以 对粒子系统进行编辑
地图集资源管理
游戏的地图一般都是重复的,重复的部分我们称之为图素。
tiled地图编辑器
tiled特点
1、可以使用多种编码形式的地图数据文件,可以在不同游戏引擎中通用
2、支持普通和45度两种视角
3、可以吧对象放到精确像素位置
4、支持复制。粘贴、撤销等操作
5、拥有图素、层级、对象等概念
6、自动载入图素集等
7、tiled资源最少有两种:
- .tmx 地图数据
- .png 图集纹理
- .tsx tileset 数据配置文件(部分.tmx文件需要)
下载并安装
下载地址:www.mapeditor.org/
tiled的使用
打开准备好的素材,打开后进入到tiled操作界面
注意:
Cocos Creator 3.0 支持 TiledMap v1.2.0 但是我手里瓦片图资源是低于1.2的。所以 此处使用的Cocos Creator是2.4.5版本。
在CC中使用地图资源
使用Cocos Creator 2.4.5创建一个新项目
为了方便CC解析tiled资源(瓦片图),要在资源管理器中新建map文件夹。然后将瓦片图资源拖拽到map中。
第一种:
直接拖拽tiled资源的.tmx文件到场景中
第二种:
在场景中,新建空节点。空节点添加TiledMap组件,将tiled资源的.tmx文件拖拽到 TiledMap组件的tmxAsstes属性中。
骨骼动画
传统动画是通过 关键帧来实现 物体对象的动画。而骨骼动画可以实现控制物体对象的顶点,来实现动画。 它是通过spine导出的资源来实习的
骨骼动画资源
.json/.skel
:骨骼数据,保存人物骨骼的数据,不同部分的尺寸 位置 活动范围
.png
:图集纹理,保存了人物不同身体部位
.txt/.atlas
:图集数据,图集纹理和图集数据组成了一个完整人物的皮肤
导入骨骼动画资源
因为我骨骼动画资源版本低,依然先新建2.4.5版本的CC项目
在资源管理器中新建spine文件夹保存所有骨骼动画文件
第一种:
直接拖拽骨骼动画json文件到场景中
第二种:
在场景中新建空节点,并为其添加spine skeleton组件,将骨骼动画json文件拖拽到spine skeletion组件的skeleton Data属性中。
点击属性面板的 animation选择要渲染的动画
骨骼动画组件属性检查器重要属性
Skeleton Data:控制骨骼动画的.json文件
Default Skin:默认皮肤
Animation:要渲染的动画
Loop:是否循环播放
Premuliplied Alpha:是否使用预乘贴图
TimeScale:动画周期缩放系数,数值越大周期越短 默认为:1
Debug Slots:是否显示Slot调试信息
Debug Bone:是否显示Bone调试信息 勾选后可在场景编辑器中显示 骨骼资源的节点数据
骨骼动画组件重要方法
sp.Skeleton实例.clearTrack()
:清理所有播放队列的动画
sp.Skeleton实例.clearTrack(0)
:清理索引0的播放队列的动画
sp.Skeleton实例.setAnimation(index,animationName,isLoop)
:
设置设置某个播放队列的动画,会覆盖之前的播放队列的所有动画
sp.Skeleton实例.addAnimation(index,animationName,isLoop)
:
像播放队列中添加动画,前面的动画不会覆盖。整个动画队列依次执行
- index:播放队列的索引,Number类型
- animationName:骨骼动画的名称,String类型
- isLoop:是否循环播放,Boolean类型
sp.Skeleton实例.setAnimation(0,"start",false)
复制代码
骨骼动画的事件
sp.Skeleton实例.setStartListener(callBack,this)
:动画开始播放时触发
sp.Skeleton实例.setEndtListener(callBack,this)
:动画播放结束时触发
sp.Skeleton实例.setCompleteListener(callBack,this)
:动画一次播放结束时触发,动画为循环播放时 会被触发多次
示例
该示例 我们需要在场景中展示骨骼动画,并且可以通过按钮添加新骨骼动画。
1、新建 spine_scene场景,并在场景中新建 空节点spine 和三个控制展示动画的 Button节点
2、spine节点 添加 Skeleton组件 并绑定 骨骼动画.json文件, Skeleton组件 默认不勾选任何动画
3、新建 spine_canvas.js脚本 并挂载到 根节点Canvas 上。
// spine_canvas.js
// 声明spineSke属性 用来界面绑定 sp.Skeleton
properties: {
spineSke: {
default: null,
type: sp.Skeleton
}
},
onLoad() {
// 获取spine节点
const spine = this.node.getChildByName("spine")
// 获取spine_skeleton组件
const ske_com = spine.getComponent(sp.Skeleton)
this.ske_com = ske_com
this.ske_com.setAnimation(0, "walk", true)
},
// 点击按钮设置动画队列
setAnimate(type, customData) {
// 先清理播放队列
this.ske_com.clearTrack(0)
// 设置播放队列
this.ske_com.setAnimation(0, customData, false)
// 向播放队列添加动画
this.ske_com.addAnimation(0, "walk", true)
}
复制代码
4、打开 根节点Canvas 的脚本属性检查中,将 spine节点 的 spineSke属性上
5、为三个按钮 注册点击事件 分别传出参数 death、hit、jump 设置要展示动画的名称
脚本编程
CC的脚本主要是通过拓展组件进行开发的
创建使用脚本
在asstes下新建script文件夹用来保存所有脚本文件,在script下新建index脚本,为场景节点添加脚本组件并将index脚本注册上去。
在脚本start钩子中,增加打印语句
start() { cc.log("hello world") }
渲染程序 控制台出现打印信息
声明类
CC中的类 通过cc.Class
实现
示例
// 声明一个名为 sprite的类
let Sprite = cc.Class({
// 类名
name: "sprite",
// 实例方法
print() {
cc.log("实例的print方法被调用了")
}
})
start() {
// 实例化
const sprite = new Sprite()
cc.log(sprite instanceof Sprite)
sprite.print()
}
复制代码
声明自定义属性
自定义属性指的是 properties,他主要是为游戏设置参数,脚本添加自定义属性后,就会在属性面板中增加对应的选项
简单声明
属性的简单声明都是 键值对的形式,属性的值分为 基本类型 和 数组类型
- 基本类型
properties:{
height:20, //number
type:"actor", //string
loaded:false, //boolean
target:null //object
}
复制代码
当声明的属性具备类型时,可以在声明处传入他们的构造函数
properties:{
target:cc.Node,
pos:cc.Vec2,
age:cc.Number
}
复制代码
- 数组类型
当声明属性时数组时,可以在声明处填写他们的类型或构造函数
properties:{
any:[],
bools:[cc.Boolean], // 不定义具体类型的数组
Strings:[cc.String],
floats:[cc.Float],
frame:[cc.SpriteFrame]
}
复制代码
复杂声明
复杂声明指 属性的值为有键值对的对象
常用的复杂声明属性
default:该组件的默认值,仅在脚本第一次挂载到组件上时生效
type:该属性的类型,例如cc.Number、cc.Node
displayName:属性显示的名称
tooltip:鼠标悬停在属性名位置显示的提示
visible:是否在属性面板显示该属性,在脚本内部使用该属性不希望有人通过面板更改这个属性时,就是可以把visible设为false 隐藏该属性
serializable:设置false时,不序列化(保存)该属性
properties: {
score: {
default: 20,
type: cc.Number,
displayName: "得分",
tooltip: "这是提示工具"
}
}
复制代码
- 数组类型
数组类型的默认值必须为[],如果要在属性面板编辑属性 还要声明其类型
properties: {
name:{
default:[],
type:[cc.String]
},
enemies:{
default:[],
type:[cc.Node]
}
}
复制代码
脚本生命周期函数
onLoad:会在组件首次初始化时被触发,可以获取其他节点。
onEnable:当组件enable由false变为true,或者active由false变为true时触发。执行顺序:onLoad–onEnable–start
onUpdata:游戏更新时触发,通常在其内部完成完成一些关键帧(物体的状态 尺寸)的操作
onUpdata(dt) {
// donUpdata会有一个参数dt,它是当前帧距离上一帧的时间。假如设备为60帧 则dt等于1/60
}
复制代码
lateUpadate:会在所有动画执行前触发,如果我们需要在一些动效(粒子等)更新之后完成一些操作,或者所有组件upDate都执行完在进行其他操作就可以用这个钩子
onDisable:当组件的enable属性由true变为false,或者active由true变为false时触发
onDestry:当组件或所在节点调用destry(),触发该回调
访问节点/组件
我们可以通过CC面板修改节点,但是有些场景下我们需要根据用户输入、当前逻辑动态修改节点/组件
获取组件所在节点
在组件的方法中访问 this.node 变量
start() {
// 获取节点 修改节点轴位置
const node = this.node
node.x = 100
}
复制代码
获取当前节点下其他组件
start() {
const label = this.getComponent(cc.Label)
let text = this.name + 'started'
label.string = text
}
复制代码
获取其他节点
在当前节点脚本中声明一个自定义属性,将其他脚本绑定到这个自定义属性中,在脚本中可以通过这个自定义属性获取被绑定的节点
properties: {
depNode: {
default: null,
type: cc.Node
}
},
start() {
cc.log("获取到依赖的节点",this.depNode)
}
复制代码
在CCIDE中,在场景中分别创建两个单色节点,将其中一个绑定到另外一个节点身上。
获取其他节点下的组件
在场景中,有两个节点分别是nodeA和nodeB。如何在nodeA中获取nodeB的script组件?
准备工作
1、新建场景main,在场景中分别创建两个单色sprite节点分别重命名为 nodeA 和 nodeB
2、新建scriptA脚本并将其挂载到NodeA节点的script组件上,新建scriptB脚本挂在到nodeB节点上。
// scriptB
// 在scriptB中,声明一个方法。
hello() {
cc.log("scriptB脚本 hello方法被调用")
}
复制代码
3、在scriptA 脚本中声明自定义属性 scriptB 用来绑定 scriptB 脚本组件
// scriptA
//引入 组件类型
const scriptB = require("scriptB")
properties: {
scriptB:{
default:null,
// 声明被绑定属性的类型
type:scriptB
}
}
start() {
// 获取scriptB
const scriptB = this.scriptB
// 调用scriptB的方法
scriptB.hello()
}
复制代码
获取子节点
获取所有子节点:node.children.children
获取单个子节点:node.getChildByName(“子节点名”)
获取深层子节点:cc.find(“子节点名/孙子节点名”,this.node)
获取全局任意节点:cc.find(“Canvas/节点名/节点名..”)
通过节点.children
获取,该节点所有子节点组成的集合
示例
1、新建main场景,在main中新建parent节点,并未其绑定parent脚本
2、在parent节点下新建众多子节点,在parent脚本中获取所有子节点
start () {
// 获取子节点集合
const childList = this.node.children
childList.forEach(element => {
// 获取节点名称
console.log("节点Name",element.name);
});
const nodeA = this.node.getChildByName("nodeA")
const grandChildA = cc.find("nodeA/grandChildA",this.node)
},
复制代码
节点激活状态
设置节点的激活状态:node.active = fasle/true
获取节点激活状态:node.activeInHierarchy
注意:
当节点处于激活状态时,节点的update钩子每帧都会被触发一次
当节点处于未激活状态,激活节点时,节点的onEnable钩子会被触发
当节点处于激活状态,关闭节点时,节点的onDisable钩子会被触发
更改节点父节点
第一种
//直接节点设置父节点
node.parent = 父节点
第二种
// 清除节点的父节点
// node.removeFromParent的参数flag为布尔值,是否清空节点绑定的事件和action,flag默认为true.
node.removeFromParent(flag)
// 将当前节点插入到父节点中
父节点.addChild = (node)
start() {
// 获取父节点
const canvasNode = cc.find("Canvas")
// 通过第一种方式更改父节点
this.node.parent = canvasNode
// 通过第二种方式更改父节点
this.node.parent.removeFromParent(false)
canvasNode.addChild(this.node)
}
复制代码
索引节点的子节点
获取节点的所有子节点数组:node.children
获取子节点的数量:node.childrenCount
注意:这个两个API只能获取直接子节点,不能获取子节点的子节点
更改节点变换(位置、旋转、缩放、尺寸)
修改坐标
1、直接修改
node.x = 50
node.y = 100
复制代码
2、通过node.setPosition(X轴坐标,Y轴坐标)
node.setPosition(50,100)
node.setPosition(cc.v2(50,100))
复制代码
3、通过node.position实现
node.postion = cc.v2(50,100)
复制代码
cc.v2用来创建2d空间向量坐标对象的API
注意:
修改的位置就是相对于父节点的位置
节点旋转
node.setRotation(90) 或
node.rotation = 90
复制代码
节点缩放
node.scaleX = 2
node.scaleY = 2 或
node.setScale(2) // 同时缩放宽高
node.setScale(2,2)
复制代码
修改节点尺寸
node.setContentSize(100)
node.setContentSize(100,100)
node.setContentSize(cc.size(100,100)) 或
node.width = 100
node.height = 100
复制代码
节点锚点
节点锚点默认在节点的中心位置,默认为50,50
node.anchorX = 1
node.anchorY = 0 或
node.setAnchorPoint(1,0)
复制代码
节点颜色和不透明度
要修改Sprite、Label等基本渲染组件的颜色和透明度时,只能在节点示例上操作,因为cc本身并未给这些基本渲染组件设置相关API
// 设置节点颜色
node.color=cc.Color.RED
// 设置节点不透明度
node.opacity = 128 //区间 0-255
复制代码
组件常用接口
this.node
:获取组件所属示例节点
this.enabled
:是否每帧执行该组件update方法,可以控制组件的显示
update(dt)
:组件成员方法,组件的enable属性为true时,每帧都会被触发
onLoad
:组件成员方法,组件所属节点进行初始化时(节点)触发
start
:组件第一次update之前执行,通常用在所有组件执行完onLoad之后的逻辑
创建节点
动态加载资源:cc.loader.loadRes(资源名,资源类型,加载完成后的回调)
新建节点: new cc.Node(节点名称)
为节点添加组件:node.addComponent(cc.Sprite)
注意:
动态加载资源,必须在assets下新建sources文件夹,并将所有资源放入到sources文件下
示例
1、在assets下新建resources文件夹,并放入avatar.png图片,新建index.js
2、新建main场景,在场景中新建空节点并添加脚本组件绑定index.js
start () {
// 保存当前脚本实例
const self = this
// 动态加载assets/resources资源,加载avatar资源并声明资源类型,加载完成的回调,参数1为错误信息,参数二为加载完后的节点信息 cc.loader.loadRes("avatar",cc.SpriteFrame,function(err,spriteFrame){
// 生成sprite节点
let node = new cc.Node("sprite")
// 为sprite节点添加 sprite组件
let sp = node.addComponent(cc.Sprite)
// 设置sprite节点的spriteFrame属性
sp.spriteFrame = spriteFrame
// 将sprite节点插入到 当前脚本组件节点中
node.parent = self.node
// 设为sprite节点尺寸
node.setContentSize(100,100)
})
}
复制代码
克隆节点
克隆场景中已有节点:cc.instantiate(this.target)
示例
cc.Class({
extends:cc.Component,
properties:{
target:{
default:null,
type:cc.Node
}
},
start() {
const node = cc.instantiate(this.target)
node.parent = this.node
node.setContentSize(50,50)
node.setPosition(0,0)
}
})
复制代码
创建预制节点
创建预制节点类似,只需设置预制节点类型 prefab
示例
cc.Class({
extends:cc.Component,
properties:{
target:{
default:null,
type:cc.Prefab
}
},
start() {
const node = cc.instantiate(this.target)
node.parent = this.node
node.setContentSize(50,50)
node.setPosition(0,0)
}
})
复制代码
销毁节点
销毁节点:node.destroy()
注意:
当节点被销毁时,不会立即移除节点。而是在当前帧逻辑更新后统一执行。当节点销毁后他会处于无效状态,可以通过cc.isValid判断状态
示例
start () {
setTimeout(()=>{
this.node.destroy()
},2000)
},
update (dt) {
if(cc.isValid(this)) {
cc.log("组件有效")
}
},
复制代码
destroy
和removeFromParent
的区别
removeFromParent
:当节点调用了removeFromParent,并不一定完全从内存释放出来,可能会造成内存泄漏
destroy
:会完全清除这个对象,同时会触发onDestroy
加载切换场景
在CC脚本中,可以通过导演类的loadScene方法加载场景。
cc.director.loadScene(场景名称,场景加载完成的回调(可选))
预加载
有些场景加载时间过长会造成卡顿,可以使用预加载的方式。使场景提前缓存在内存中。
cc.director.preloadScene("main",function() {cc.log('场景加载完成')})
通过常驻节点进行场景资源管理和参数传递
引擎同时只能运行一个场景,切换场景时,默认会将场景内所有节点和其他实例销毁。如果我们需要用一个组件控制所有场景的加载,或场景直接传递参数。就需要将该组件所在节点编辑为 常驻节点 ,使他在切换场景时不会被自动清除
cc.game.addPersistRootNode(node)
被标记的 常驻节点 ,挂载载该节点上的组件会在场景之间持续作用。
移除常驻节点
cc.game.removePersistRootNode(node)
资源管理
在CC中,所有继承cc.Asstes的类型都统称为资源。例如cc.Text2D
、cc.SpriteFrame
、cc.AnimationClip
、cc.Prefab
等,他们的加载懂事统一自动完成的。
如何在资源选择器设置资源
1、新建单色sprite节点作背景,同时绑定index脚本
2、在index中声明自定义属性sprite_frame用来绑定资源渲染源
sprite_frame:{
default:null,
type:cc.SpriteFrame
}
复制代码
3、在cc中,将资源绑定到背景节点的scipte的sprite_frame属性上
4、在index中,获取Sprite组件,并将其渲染源 设置为背景节点的背景图
onLoad () {
// 获取节点的Sprite组件
const sprite = this.node.getComponent(cc.Sprite)
// 更改sprite组件的渲染源
sprite.spriteFrame = this.sprite_frame
}
复制代码
动态加载资源
动态加载resource文件夹下资源: cc.loader.loadRes(资源路径,资源类型,加载完成的回调)
const self = this
cc.loader.loadRes("Pler",(err,prefab)=>{
// 克隆一个预制体节点
const newNode = cc.instantiate(prefab)
// 将预制体节点插入到当前节点中
self.node.addChild(newNode)
})
复制代码
资源的释放
不使用资源时,如何释放它
cc.loader.releaseRes(资源路径,资源类型(可选))
释放特定Assets实例
cc.loader.releaseAsset(spriteFrame)
动作系统
CC提供动作系统,可以实现在一定时间内对节点完成位移、缩放、旋转等动作
CC的Action类并不是在屏幕中显示的对象,动作依托的必须是节点类及它的子类实例。
基本使用
// 创建一个动作
// cc.moveTo(周期,X轴坐标,y轴坐标)
const action = cc.moveTo(2,100,100)
// 执行动作
this.node.runAction(action)
// 停止一个动作
this.node.stopAction(action)
// 停止所有动作
this.node.stopAllActions()
复制代码
动作类型
基本动作
基本动作主要指是节点的各种形变、位移的动作
cc.moveTo
:移动节点到某个位置
cc.moveBy
:基于节点当前位置进行移动
cc.rotateBy
:让节点旋转一定角度
cc.scaleTo
:缩放节点
基础动作分为 时间间隔动作 和 即时动作
时间间隔动作:在一定时间间隔内完成渐变动作,这些动作全部继承自cc.ActionInterval
即时动作:是立即发生,例如用来调用函数的cc.callFunc
、用来隐藏节点的cc.hide
、他们全部继承自cc.ActionInstant
容器动作
容器动作可以将不同动作组合在一起。
顺序动作:将一系列动作按顺序一个一个执行
// 让节点左右来回移动
let seq = cc.sequence(cc.moveBy(0.5,200,0),cc.moveBy(0.5,-200,0))
node.runAction(seq)
复制代码
同步动作:让所有动作 同步执行
// 让节点在移动的同时缩放
let action = cc.spawn(cc.moveBy(0.5,200,0),cc.scaleTo(0.5,0.8,1.4))
node.runAction(action)
复制代码
重复动作: 让一个动作不停重复进行几次
// 让节点左右来回移动 重复进行5次
let action = cc.repeat(
cc.sequence(cc.moveBy(0.5,200,0),cc.moveBy(0.5,-200,0)),5
)
node.runAction(action)
复制代码
永久重复动作: 让一个动作永久不停重复进行 直到手动停止
// 让节点左右来回移动 重复进行5次
let action = cc.repeatForever(
cc.sequence(cc.moveBy(0.5,200,0),cc.moveBy(0.5,-200,0)))
node.runAction(action)
复制代码
速度动作: 改变目标动作的执行速率,让动作更快或更慢完成
// 让目标动作加快一倍,相当于4秒完成的动作在2秒内完成
let action = cc.speed(
cc.sequence(cc.moveBy(0.5,200,0),cc.moveBy(0.5,-200,0))),2
node.runAction(action)
复制代码
动作回调
动作回调可以实现在某个动作完成后触发回调
cc.callFunc(处理函数,context(一般为this),处理函数的参数)
// 声明一个动作回调
let finished = cc.callFunc(
function(target,score){
cc.log("动作回调")
},
this,
100
)
// 为动作注册动作回调
// 只为其中一个动作注册动作回调
let action = cc.sequence(cc.moveBy(1,cc.v2(0,100)),cc.fadeOut(1),finished)
// 为每个动作都注册动作回调
let action = cc.sequence(cc.moveBy(1,cc.v2(0,100)),finished,cc.fadeOut(1),finished)
复制代码
UI系统
一个游戏除了游戏玩法之外,最大的工作量就在于UI界面的开发。CC经过多个版本迭代后,在易用性上得到了极大的提升。
基础渲染组件–精灵组件
sprite组件是2D渲染图像最常见的图片。
使用精灵组件渲染图片
1、场景新建空白节点,空白节点添加sprite组件。让图片拖拽到sprite组件的spriteFrame属性中。
2、在场景中新建sprite节点,让图片拖拽到sprite组件的spriteFrame属性中。
sprite属性
Atlas: 用来保存图集资源
SpriteFrame:用来保存单张图片资源
Type:渲染模式,Simple、Sliced、Tiled、Filled
SizeMode:资源尺寸裁剪模式,Trimmed(使用资源原始尺寸,超过节点尺寸自动裁剪)、Raw(使用资源原始尺寸,超出不裁剪)、Custom(自定义资源尺寸)
Trim:勾选后将在渲染时去除原始图像周围的透明像素区域,该项仅在Type设置为Simple时生效
SrcBlendFactor:当前图像混合模式(一般使用默认设置即可)
DstBlendFactor:背景图像混合模式(一般使用默认设置即可)
渲染模式
- 普通模式(Simple): 按照原始资源的样子渲染sprite
- 九宫格模式(Sliced):
将图像分割成九宫格,并按照一定规则进行缩放 - 平铺模式(Tiled):
当sprite尺寸增大时,图像不会拉伸。而是按照原始图片大小不断重复,一直铺满整个sprite为止 - 填充模式(Filled):
根据原点和填充模式的设置,按照一定方向和比例绘制原始图片的一部分。经常用于进度条的动态展示。
选择填充模式后,会新增一组属性可供配置- FillType:填充类型,HORIZONTAL(横向填充)、VERTICAL(纵向填充)、RADIAL(扇形填充)
- FillStart:填充起始点(0-1),横向时从最左侧开始
- FillRange:填充范围(0-1),设为1,就会填充最多整个原始图像的范围
- FillCenter:填充中心点,只有填充类型选为扇形时出现该属性。它决定扇形填充时围绕sprite的哪个点。类似坐标系的锚点功能
- 网格模式(Mesh):
必须使用TexturePacker 4.X以上并且设置ploygon算法打包出来的plist文件才能使用该模式
基础渲染组件–Lable组件
Lable组件用来显示一段文字,文字可以为系统文字。也可以图片子或者艺术字。
Lable常用属性
String:文本内容字符串
HorizontalAlign:文本水平对齐方式,LEFT、CENTER、RIGHT
VerticalAlign:文本垂直对齐方式,TOP、CENTER、BOTTOM
FontSize:文字大小
LineHeight:文本行高
Overflow:文本排班方式,目前支持CLAMP、SHRINK、RESIZE_HEIGHT
EnableWrapText:是否开启文本换行 (在排版方式设为CLAMP、SHRINK有效)
SpacingX:文本之间的间距。(使用BMFont位图字体时生效)
Font:指定文本渲染需要的字体文件,如果为系统文字 则该属性可以为空
FontFamily:文字字体名字,使用系统字体生效
CacheMode:文字缓存类型用来对应用进行优化,仅对系统文字或TTF字体有效
- NONE:默认值,Label中整段文本将生成一张位图
- BITMAP:选择后也是将文段生成一张位图,但是会尽量参与动态合成。由于动态合图会占用更多内存,该模式主要用于不常更新的Label.注意:如果场景中,有大量相同文本的Label,建议使用CHAR模式复用内存空间
- CHAR:这个原理有点负责自行百度
UseSystemFont:布尔值,是否使用系统文字
Button按钮组件
Button组件可以响应用户的点击操作,用户点击Button时,Button自身会有状态变化。Button可以让用户完成点击操作后响应一个自定义行为。
Button属性
Target:
Node类型,当Button发生Transition时。会相应的修改target节点的SpriteFrame颜色或者Scale
Interactable:布尔类型,设为false时,Button组件进入禁用状态
Transition:枚举类型,包括NONE、COLOR、SPRITE和SCALE。每种类型对应不同的Transition设置 详情见 Button Transition部分
ClickEvent:列表类型,默认为空。用户添加的每个事件由节点引用、组件名称、一个相应函数组成。详情见 Button 事件部分
ButtonTransition
Button的Transition 用来指定当用户点击Button时状态表现。目前主要有NONE、COLOR、SPRITE、SCALE四种类型
- COLOR:可以配置正常、点击、悬停、禁用状态的button颜色
- SPRITE:可以配置正常、点击、悬停、禁用状态的button图片资源
- SCALE:可以配置点击时,组件缩放的时间和缩放倍数
Button点击事件
通过属性检查器添加回调
Target:带有脚本的节点
Component:脚本组件名称
Handler:用户点击时触发的回调函数
CustomEventData:用户指定任意字符串作为事件回调的最后一个参数传入
// btn.js 声明onClick方法
onClick() {
cc.log("btn组件被点击了")
}
复制代码
通过脚本添加回调
注意:该方法很便捷,但是有局限性,就是无法获取用户点击button时的屏幕坐标
新建btnHandle脚本并绑定到任意节点或组件上
properties: {
// 声明自定义属性button 用来绑定Button组件
button: cc.Button
},
onLoad() {
// 为button组件注册点击事件
this.button.node.on("click", this.onClick, this)
},
onClick() {
cc.log("点击了Button组件")
}
复制代码
动画系统
CC不仅支持标准的位移、旋转、缩放动画和序列帧动画以外,这套动画系统还支持任意组件属性和用户自定义属性的驱动,再加上可编辑的时间曲线和移动轨迹编辑功能。可以让使用这不写一行代码做出各种细腻动画
CC自带的动画编辑器适用不太复杂的需要与逻辑联动的东阿虎,例如UI动画。如果需要复杂的特效、角色动画、嵌套动画,这需要考虑Spine或DragonBones制作。
Animation
Animation组件
CC可以通过Animation组件,配置不同帧节点的状态来实现动画
Clip 动画剪辑
Clip是一种资源文件类型,提前保存了动画声明的数据(节点运动的轨迹、节点变化的周期、关键帧等),将它挂载到Animation组件上,才能将动画数据应用在节点上
示例
1、新建main场景、新建单色sprite节点(bg)作为白色背景,新建一个单色sprite节点(box)红色盒子作为运动的物体
2、box节点添加 Animation组件 , 点击新建Clip文件Assets/res/move(Clip文件),点击左上角进行编辑
3、在动画编辑器中,左侧上部是节点信息下部是节点的属性列表,右侧是动画时间轴。时间轴的红线代表关键帧。
4、新建属性Postion,为属性设置关键帧
5、拖动关键帧将,设置节点下一状态的关键帧位置。然后在场景编辑器中 拖动节点设置节点位置
6、保存动画剪辑,将动画剪辑挂载到box节点 Animation 的 default clip 属性上,渲染项目
动画编辑器界面
动画编辑器的基本操作
更改时间轴缩放比例
在图2/4/6区域滚动鼠标滚轮可以放缩时间轴显示比例
移动显示区域
如果想查看右侧查出编辑的关键帧部分 可以通过鼠标右键拖拽查看
快捷键:
left:向前移动一帧
right:向后移动一帧
delete:删除当前所选中的关键帧
ctrl/cmd + left:跳转到第0帧
ctrl/cmd + right:跳转到有效的最后一帧
剪辑内的数据
节点数据
动画剪辑通过节点定义数据的位置,其余的子节点通过与根节点的相对路径索引找到对应的数据,有时候完成动画后,将节点重命名 会造成动画数据丢失的问题
解决数据路径丢失问题
点击丢失的数据—点击移动数据–重新修改数据路径