cocos creator基础篇:脚本开发指南

1,583 阅读5分钟

前言

最近因为工作的关系接触到了cocos creator,所以也将自己学习到的内容逐一在这里记录下来,方便自己日后复盘。

动作系统

动作系统简介

动作系统可以在一定时间内对节点完成位移,缩放,旋转等各种动作。

需要注意的是,动作系统并不能取代动画系统,动作系统提供的是面向程序员的 API 接口,而动画系统则是提供在编辑器中来设计的。

同时,它们服务于不同的使用场景,动作系统比较适合来制作简单的形变和位移动画,而动画系统则强大许多,美术可以用编辑器制作支持各种属性,包含运动轨迹和缓动的复杂动画。

缓动系统

缓动系统介绍

cc.tween 能够对对象的任意属性进行缓动,功能类似于 cc.Action(动作系统)。但是 cc.tween 会比 cc.Action 更加简洁易用,因为 cc.tween 提供了链式创建的方法,可以对任何对象进行操作,并且可以对对象的任意属性进行缓动。

链式 API

cc.tween 的每一个 API 都会在内部生成一个 action,并将这个 action 添加到内部队列中,在 API 调用完后会再返回自身实例,这样就可以通过链式调用的方式来组织代码。

cc.tween(this.node)
    // 0s 时,node 的 scale 还是 1
    .to(1, { scale: 2 })
    // 1s 时,执行完第一个 action,scale 为 2
    .to(1, { scale: 3 })
    // 2s 时,执行完第二个 action,scale 为 3
    .start()
    // 调用 start 开始执行 cc.tween

设置缓动属性

cc.tween 提供了两个设置属性的 API:

cc.tween(node)
  .to(1, {scale: 2})      // node.scale === 2
  .by(1, {scale: 2})      // node.scale === 4 (2 + 2)
  .start()

支持缓动任意对象的任意属性

let obj = { a: 0 }
cc.tween(obj)
  .to(1, { a: 100 })
  .start()

同时执行多个属性

cc.tween(this.node)
    // 同时对 scale, position, rotation 三个属性缓动
    .to(1, { scale: 2, position: cc.v2(100, 100), rotation: 90 })
    .start()

easing

使用 easing 可以使缓动更生动,cc.tween 针对不同的情况提供了多种使用方式。

// 传入 easing 名字,直接使用内置 easing 函数
cc.tween().to(1, { scale: 2 }, { easing: 'sineOutIn'})

// 使用自定义 easing 函数
cc.tween().to(1, { scale: 2 }, { easing: t => t*t; })

// 只对单个属性使用 easing 函数
// value 必须与 easing 或者 progress 配合使用
cc.tween().to(1, { scale: 2, position: { value: cc.v3(100, 100, 100), easing: 'sineOutIn' } })

Easing 类型说明可参考 API 文档。

自定义 progress

相对于 easing,自定义 progress 函数可以更自由的控制缓动的过程。

// 对所有属性自定义 progress
cc.tween().to(1, { scale: 2, rotation: 90 }, {
  progress: (start, end, current, ratio) => {
    return start + (end - start) * ratio;
  }
})

// 对单个属性自定义 progress
cc.tween().to(1, {
  scale: 2,
  position: {
    value: cc.v3(),
    progress: (start, end, current, t) => {
      // 注意,传入的属性为 cc.Vec3,所以需要使用 Vec3.lerp 进行插值计算
      return start.lerp(end, t, current);
    }
  }
})

复制缓动

clone 函数会克隆一个当前的缓动,并接受一个 target 作为参数。

// 先创建一个缓动作为模板
let tween = cc.tween().to(4, { scale: 2 })

// 复制 tween,并使用节点 Canvas/cocos 作为 target
tween.clone(cc.find('Canvas/cocos')).start()

插入其他的缓动到队列中

你可以事先创建一些固定的缓动,然后通过组合这些缓动形成新的缓动来减少代码的编写。

let scale = cc.tween().to(1, { scale: 2 })
let rotate = cc.tween().to(1, { rotation: 90})
let move = cc.tween().to(1, { position: cc.v3(100, 100, 100)})

// 先缩放再旋转
cc.tween(this.node).then(scale).then(rotate)
// 先缩放再移动
cc.tween(this.node).then(scale).then(move)

并行执行缓动

cc.tween 在链式执行时是按照 sequence 的方式来执行的,但是在编写复杂缓动的时候可能会需要同时并行执行多个队列,cc.tween 提供了 parallel 接口来满足这个需求。

let t = cc.tween;
t(this.node)
    // 同时执行两个 cc.tween
    .parallel(
        t().to(1, { scale: 2 }),
        t().to(2, { position: cc.v2(100, 100) })
    )
    .call(() => {
        console.log('All tweens finished.')
    })
    .start()

回调

cc.tween(this.node)
    .to(2, { rotation: 90})
    .to(1, { scale: 2})
    // 当前面的动作都执行完毕后才会调用这个回调函数
    .call(() => { cc.log('This is a callback') })
    .start()

重复执行

repeat/repeatForever 函数会将前一个 action 作为作用对象。但是如果有参数提供了其他的 action 或者 tween,则 repeat/repeatForever 函数会将传入的 action 或者 tween 作为作用对象。

cc.tween(this.node)
    .by(1, { scale: 1 })
    // 对前一个 by 重复执行 10次
    .repeat(10)
    // 最后 node.scale === 11
    .start()
    
// 也可以这样用
cc.tween(this.node)
    .repeat(10,
        cc.tween().by(1, { scale: 1 })
    )
    .start()
    
// 一直重复执行下去
cc.tween(this.node)
    .by(1, { scale: 1 })
    .repeatForever()
    .start()

延迟执行

cc.tween(this.node)
    // 延迟 1s
    .delay(1)
    .to(1, { scale: 2 })
    .start()

使用计时器

Cocos Creator 为组件提供了方便的计时器,这个计时器适配了基于组件的使用方式。下面来看看它的具体使用方式:

首先,先创建一个指向某个组件的变量,变量名为 component。

开始一个计时器

 component.schedule(function() {
     // 这里的 this 指向 component
     this.doSomething();
 }, 5);

上面这个计时器将每隔 5s 执行一次。

更灵活的计时器

 // 以秒为单位的时间间隔
 var interval = 5;
 // 重复次数
 var repeat = 3;
 // 开始延时
 var delay = 10;
 component.schedule(function() {
     // 这里的 this 指向 component
     this.doSomething();
 }, interval, repeat, delay);

上面的计时器将在 10 秒后开始计时,每 5 秒执行一次回调,执行 3 + 1 次。

只执行一次的计时器(快捷方式)

 component.scheduleOnce(function() {
     // 这里的 this 指向 component
     this.doSomething();
 }, 2);

上面的计时器将在两秒后执行一次回调函数,之后就停止计时。

取消计时器

开发者可以使用回调函数本身来取消计时器:

 this.count = 0;
 this.callback = function () {
     if (this.count === 5) {
         // 在第六次执行回调时取消这个计时器
         this.unschedule(this.callback);
     }
     this.doSomething();
     this.count++;
 }
 component.schedule(this.callback, 1);

注意:组件的计时器调用回调时,会将回调的 this 指定为组件本身,因此回调中可以直接使用 this。

下面是 Component 中所有关于计时器的函数:

schedule:开始一个计时器

scheduleOnce:开始一个只执行一次的计时器

unschedule:取消一个计时器

unscheduleAllCallbacks:取消这个组件的所有计时器

这些 API 的详细描述都可以在 Component API 文档中找到。

除此之外,如果需要每一帧都执行一个函数,请直接在 Component 中添加 update 函数,这个函数将默认被每帧调用,这在 生命周期文档 中有详细描述。

注意:cc.Node 不包含计时器相关 API