Cocos2D Cocos Creator 入门详解

Cocos Creator界面

1620693358(1).png
层级管理器:层级管理器中包含了 画布场景中所有的节点

Cocos Creator常用设置

默认脚本编辑器

Cocos HelloWorld项目目录结构

项目新建后会自动生成scene、model等文夹,以及这个文件夹对应的meta文件,cocos引擎通过meta文件来管理项目的资源。它储存了资源配置信息和资源索引,.meta文件需要一并提交到文件版本控制系统中。
asstes:项目所有资源文件
library:资源库,asstes导入之后自动生成的资源,当library被破坏时,只需将整个库删除重新生成即可。
local:本地设置文件,它存储了该项目在本地配置的信息,编辑面板位置 大小,窗口大小,位置等信息
packages:拓展插件文件夹,如需手动安装插件 可手动创建文件夹,如需卸载插件 删除对应的文件夹即可
settings:项目设置,保存项目相关设置,构建发包 菜单里的包名,场景 平台选择等

项目设置

主菜单栏–项目–项目设置,打开项目设置面板

1620787130(1).jpg
项目设置面板常用主要是 高级设置-项目数据、高级设置-Layers两个板块
高级设置-项目数据:配置项目渲染后的效果,例如视图的尺寸、适配的方式
高级设置-Layers:图层面板;在这个添加图层,相机可以渲染指定图层内的节点,灯光可以照亮部分场景

场景

Cocos Creator是由一个个游戏场景组成的,场景是一种属性结构,他由有层级关系的节点组成的。
场景编辑器时 开发创作的核心区域,在这个地方对元素节点进行编辑

节点和组件

Cocos Creator是以组件开发为核心的,节点是承载组件的实体,我们通过将各种各样组件挂载到节点上,来让节点具有各种各样的功能。例如,在视图中不能会直接将button按钮组件放置在 场景中,必须现将其放置在节点中。

  • 新建一个空项目

1620704854(1).jpg

  • 在asstes中新建一个scene文件夹用来储存场景文件并新建main场景

1620705226(1).jpg

  • 双击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上

1620714293(1).jpg

1620714397(1).jpg

1620714589(1).jpg

1620714617(1).jpg

  • 打开组件脚本,在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 结构如下:

1620788363(1).jpg
3、双击main,进入main场景。删除自带相机和灯光,将视口改为2D模式。
4、将图片的类型设为 sprite-frame并保存,将图片拖拽到场景中。

1620818000(1).jpg

1620818056(1).png

1620818105(1).jpg

1620818515(1).jpg
将图片挂载到精灵节点上
1、先在场景新建sprite节点,并将图片(必须是 sprite-frame 类型)放到sprite节点的spriteFrame属性上

1620818708(1).jpg

1620818821(1).jpg

图集资源

图集(Atlas)也称为Sprite Sheet,它是一种常见的美术资源。他通过专门的工具将多个图片合成一张大图,并通过 plist等格式文件索引资源。可供CocosCreator使用的图集资源有plist和png组成。plist储存了这个图集中 每个子图片的位置、尺寸等信息,使用图集资源需要将图集的png文件和plist文件一共放进资源管理器中。

声音资源管理

游戏不仅仅是简单的界面和动画,还需要音乐音效的结合。场景中好的音效可以极大的提升用户体验。

WebAudio

在CC(coocs creator)中,加载音频的方式和图片一样,都是在资源管理器路径下添加即可。节点的属性检查器可以选择加载音频的方式,CC提供了WebAudio(默认)和DomAudio两种方式。
通过 WebAudio 方式加载音频资源,在引擎是以一个buffer的形式缓存的,该等方式特点是:兼容性好,问题少,但是占用的内存资源比较多。 示例
1、在层级管理器右击场景节点 新建空节点,并在空节点下挂载audio组件

1620821977(1).jpg

1620822195(1).jpg

1620822253(1).jpg
2、将资源管理器中音频资源拖拽到audio组件的Clip属性中。渲染项目后音频成功加载到项目中(项目渲染完成需要点击一下,才会播放音频)

1620822514(1).jpg

1620822603(1).jpg

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:是否使用系统文字,默认勾选
1620871785(1).jpg

动态文字

CC目前支持TFF格式的的动态文字,只需要将.TFF文件拖拽到资源管理器中,即可完成动态文字的导入

1620872752(1).png

位图文字

动态文字不适用中文,位图文字可以解决在CC中使用中文字体的问题。

位图文字的制作

位图文字由fnt文字文件和一张png图片组成。fnt文件提供了对每一个字符小图的索引,这种格式的文件由专门的位图字体制作工具生成。常见的有:hiero、bmfont

位图字体的导入和使用

1、将位图字体的.fnt和.png一同拖进资源管理器中。
2、将.fnt文件拖拽到label节点的 font属性中。

1620873704(1).jpg

粒子系统

用普通动画做绚丽的效果可能需要很大的代价(占用大量内存),粒子系统是一个不错的解决方案。它能发射大量细小无规则运动的粒子并高效的渲染这些粒子,比渲染单个精灵要高效的多。他可以模拟随机的烟雾、闪电、风雨、雪花掉落效果。

CC的粒子资源

CC的粒子系统可以通过Particle Designer软件进行制作,也可以通过网页在线制作 www.effecthub.com/particle2dx .
1620874649(1).jpg

使用粒子

粒子文件也是.plist文件,里面记录了粒子发射的坐标、规则等信息。
将粒子文件拖拽进资源管理器中,新建一个粒子节点,将粒子文件拖拽到粒子节点的file属性上。

1620875167(1).jpg

1620875034(1).jpg
如果勾选custom选项还可以 对粒子系统进行编辑

1620875377(1).jpg

地图集资源管理

游戏的地图一般都是重复的,重复的部分我们称之为图素。

tiled地图编辑器

tiled特点

1、可以使用多种编码形式的地图数据文件,可以在不同游戏引擎中通用
2、支持普通和45度两种视角
3、可以吧对象放到精确像素位置
4、支持复制。粘贴、撤销等操作
5、拥有图素、层级、对象等概念
6、自动载入图素集等
7、tiled资源最少有两种:

  • .tmx 地图数据
  • .png 图集纹理
  • .tsx tileset 数据配置文件(部分.tmx文件需要)

下载并安装

下载地址:www.mapeditor.org/

tiled的使用

打开准备好的素材,打开后进入到tiled操作界面

1620876351(1).jpg
注意:
Cocos Creator 3.0 支持 TiledMap v1.2.0 但是我手里瓦片图资源是低于1.2的。所以 此处使用的Cocos Creator是2.4.5版本。

在CC中使用地图资源

使用Cocos Creator 2.4.5创建一个新项目

1620889157(1).jpg

1620889206.jpg

1620889266(1).jpg

1620889318(1).jpg
为了方便CC解析tiled资源(瓦片图),要在资源管理器中新建map文件夹。然后将瓦片图资源拖拽到map中。

1620890185(1).jpg
第一种:
直接拖拽tiled资源的.tmx文件到场景中

1620890310(1).jpg
第二种:
在场景中,新建空节点。空节点添加TiledMap组件,将tiled资源的.tmx文件拖拽到 TiledMap组件的tmxAsstes属性中。
1620890440(1).jpg

1620891151(1).jpg

1620891206(1).jpg

1620891242(1).jpg

骨骼动画

传统动画是通过 关键帧来实现 物体对象的动画。而骨骼动画可以实现控制物体对象的顶点,来实现动画。 它是通过spine导出的资源来实习的

骨骼动画资源

.json/.skel:骨骼数据,保存人物骨骼的数据,不同部分的尺寸 位置 活动范围
.png:图集纹理,保存了人物不同身体部位
.txt/.atlas:图集数据,图集纹理和图集数据组成了一个完整人物的皮肤

导入骨骼动画资源

因为我骨骼动画资源版本低,依然先新建2.4.5版本的CC项目
在资源管理器中新建spine文件夹保存所有骨骼动画文件

1620892275(1).jpg
第一种:
直接拖拽骨骼动画json文件到场景中
第二种:
在场景中新建空节点,并为其添加spine skeleton组件,将骨骼动画json文件拖拽到spine skeletion组件的skeleton Data属性中。

image.png

1620892709(1).jpg
点击属性面板的 animation选择要渲染的动画

1620893723(1).jpg

QQ录屏20210513162100.gif

骨骼动画组件属性检查器重要属性

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):动画一次播放结束时触发,动画为循环播放时 会被触发多次

示例

该示例 我们需要在场景中展示骨骼动画,并且可以通过按钮添加新骨骼动画。

1621478866(1).jpg
1、新建 spine_scene场景,并在场景中新建 空节点spine 和三个控制展示动画的 Button节点

1621479209(1).jpg
2、spine节点 添加 Skeleton组件 并绑定 骨骼动画.json文件Skeleton组件 默认不勾选任何动画

1621479349(1).jpg
3、新建 spine_canvas.js脚本 并挂载到 根节点Canvas 上。

1621479857(1).jpg

  // 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属性上

1621480178(1).jpg
5、为三个按钮 注册点击事件 分别传出参数 death、hit、jump 设置要展示动画的名称
1621480332(1).jpg

脚本编程

CC的脚本主要是通过拓展组件进行开发的
创建使用脚本
在asstes下新建script文件夹用来保存所有脚本文件,在script下新建index脚本,为场景节点添加脚本组件并将index脚本注册上去。

1620896553(1).jpg
在脚本start钩子中,增加打印语句
start() { cc.log("hello world") }
渲染程序 控制台出现打印信息

1620898230(1).jpg

声明类

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
}

复制代码

1620900564(1).jpg
当声明的属性具备类型时,可以在声明处传入他们的构造函数

properties:{
  target:cc.Node,
  pos:cc.Vec2,
  age:cc.Number
}
复制代码

1620901037(1).jpg

  • 数组类型

当声明属性时数组时,可以在声明处填写他们的类型或构造函数

properties:{
  any:[],
  bools:[cc.Boolean],   // 不定义具体类型的数组
  Strings:[cc.String],
  floats:[cc.Float],
  frame:[cc.SpriteFrame]
}
复制代码

1620901434(1).jpg

复杂声明

复杂声明指 属性的值为有键值对的对象
常用的复杂声明属性
default:该组件的默认值,仅在脚本第一次挂载到组件上时生效
type:该属性的类型,例如cc.Number、cc.Node
displayName:属性显示的名称
tooltip:鼠标悬停在属性名位置显示的提示
visible:是否在属性面板显示该属性,在脚本内部使用该属性不希望有人通过面板更改这个属性时,就是可以把visible设为false 隐藏该属性
serializable:设置false时,不序列化(保存)该属性

  properties: {
    score: {
      default: 20,
      type: cc.Number,
      displayName: "得分",
      tooltip: "这是提示工具"
    }
  }
复制代码

1620902966(1).jpg

  • 数组类型

数组类型的默认值必须为[],如果要在属性面板编辑属性 还要声明其类型

  properties: {
    name:{
      default:[],
      type:[cc.String]
    },
    enemies:{
      default:[],
      type:[cc.Node]
    }
  }
复制代码

1620902966(1).jpg

脚本生命周期函数

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
}
复制代码

1620906684(1).jpg

1620906715(1).jpg

获取其他节点

在当前节点脚本中声明一个自定义属性,将其他脚本绑定到这个自定义属性中,在脚本中可以通过这个自定义属性获取被绑定的节点


  properties: {
    depNode: {
      default: null,
      type: cc.Node
    }
  },
 start() {
   cc.log("获取到依赖的节点",this.depNode)
 }
复制代码

在CCIDE中,在场景中分别创建两个单色节点,将其中一个绑定到另外一个节点身上。

1620908322(1).jpg

1620908366(1).jpg

获取其他节点下的组件

在场景中,有两个节点分别是nodeA和nodeB。如何在nodeA中获取nodeB的script组件?
准备工作
1、新建场景main,在场景中分别创建两个单色sprite节点分别重命名为 nodeA 和 nodeB

1620998770(1).jpg
2、新建scriptA脚本并将其挂载到NodeA节点的script组件上,新建scriptB脚本挂在到nodeB节点上。

1620998863(1).jpg

// 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()
 }
复制代码

1621000369(1).jpg

获取子节点

获取所有子节点:node.children.children
获取单个子节点:node.getChildByName(“子节点名”)
获取深层子节点:cc.find(“子节点名/孙子节点名”,this.node)
获取全局任意节点:cc.find(“Canvas/节点名/节点名..”)
通过节点.children获取,该节点所有子节点组成的集合
示例
1、新建main场景,在main中新建parent节点,并未其绑定parent脚本

1621000897(1).jpg
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)
},
复制代码

1621001933(1).jpg

1621001973(1).jpg

节点激活状态

设置节点的激活状态: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

1621257268(1).jpg

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("组件有效")
  }
},
复制代码

destroyremoveFromParent的区别
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.Text2Dcc.SpriteFramecc.AnimationClipcc.Prefab等,他们的加载懂事统一自动完成的。

如何在资源选择器设置资源

1、新建单色sprite节点作背景,同时绑定index脚本

1621341649(1).jpg
2、在index中声明自定义属性sprite_frame用来绑定资源渲染源

sprite_frame:{
  default:null,
  type:cc.SpriteFrame
}
复制代码

3、在cc中,将资源绑定到背景节点的scipte的sprite_frame属性上

1621342037(1).jpg
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:用户指定任意字符串作为事件回调的最后一个参数传入

1621390889(1).jpg

// btn.js 声明onClick方法
onClick() {
  cc.log("btn组件被点击了")
}
复制代码

通过脚本添加回调
注意:该方法很便捷,但是有局限性,就是无法获取用户点击button时的屏幕坐标
新建btnHandle脚本并绑定到任意节点或组件上

1621391150(1).jpg

 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)红色盒子作为运动的物体

1621394751(1).jpg

1621394819(1).jpg
2、box节点添加 Animation组件 , 点击新建Clip文件Assets/res/move(Clip文件),点击左上角进行编辑

1621394928(1).jpg

1621395193(1).jpg
3、在动画编辑器中,左侧上部是节点信息下部是节点的属性列表,右侧是动画时间轴。时间轴的红线代表关键帧。

1621395981(1).jpg
4、新建属性Postion,为属性设置关键帧

1621396278(1).jpg

1621401782(1).jpg
5、拖动关键帧将,设置节点下一状态的关键帧位置。然后在场景编辑器中 拖动节点设置节点位置

1621402204(1).jpg
6、保存动画剪辑,将动画剪辑挂载到box节点 Animationdefault clip 属性上,渲染项目

1621402434(1).jpg

动画编辑器界面

1621402622(1).jpg

动画编辑器的基本操作

更改时间轴缩放比例
在图2/4/6区域滚动鼠标滚轮可以放缩时间轴显示比例
移动显示区域
如果想查看右侧查出编辑的关键帧部分 可以通过鼠标右键拖拽查看
快捷键:
left:向前移动一帧
right:向后移动一帧
delete:删除当前所选中的关键帧
ctrl/cmd + left:跳转到第0帧
ctrl/cmd + right:跳转到有效的最后一帧

剪辑内的数据

节点数据

动画剪辑通过节点定义数据的位置,其余的子节点通过与根节点的相对路径索引找到对应的数据,有时候完成动画后,将节点重命名 会造成动画数据丢失的问题
解决数据路径丢失问题
点击丢失的数据—点击移动数据–重新修改数据路径

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享