cc.Tween 緩動系統(tǒng)
cc.tween
能夠?qū)ο蟮娜我鈱傩赃M(jìn)行緩動螃征,功能類似于 cc.Action(動作系統(tǒng))靖榕。但是 cc.tween
會比 cc.Action
更加簡潔易用找都,因為 cc.tween
提供了鏈?zhǔn)絼?chuàng)建的方法,可以對任何對象進(jìn)行操作赏枚,并且可以對對象的任意屬性進(jìn)行緩動饿幅。
動作系統(tǒng) 是從 Cocos2d-x 遷移到 Cocos Creator 的栗恩,提供的 API 比較繁瑣洪燥,只支持在節(jié)點屬性上使用,并且如果要支持新的屬性就需要再添加一個新的動作市咆。為了提供更好的 API蒙兰,cc.tween
在 動作系統(tǒng) 的基礎(chǔ)上做了一層 API 封裝搜变。
動作系統(tǒng)目前已不推薦使用挠他,未來將逐步移除绩社,建議使用 緩動系統(tǒng) 做為替代。
使用對比
cc.Action:
this.node.runAction(
cc.sequence(
cc.spawn(
cc.moveTo(1, 100, 100),
cc.rotateTo(1, 360),
),
cc.scale(1, 2)
)
)
cc.tween:
cc.tween(this.node)
.to(1, { position: cc.v2(100, 100), rotation: 360 })
.to(1, { scale: 2 })
.start()
鏈?zhǔn)?API
cc.tween
的每一個 API 都會在內(nèi)部生成一個 action贮尉,并將這個 action 添加到內(nèi)部隊列中猜谚,在 API 調(diào)用完后會再返回自身實例魏铅,這樣就可以通過鏈?zhǔn)秸{(diào)用的方式來組織代碼坚芜。
cc.tween
在調(diào)用 start 時會將之前生成的 action 隊列重新組合生成一個 cc.sequence
隊列,所以 cc.tween
的鏈?zhǔn)浇Y(jié)構(gòu)是依次執(zhí)行每一個 API 的沧竟,也就是會執(zhí)行完一個 API 再執(zhí)行下一個 API悟泵。
cc.tween(this.node)
// 0s 時糕非,node 的 scale 還是 1
.to(1, { scale: 2 })
// 1s 時朽肥,執(zhí)行完第一個 action衡招,scale 為 2
.to(1, { scale: 3 })
// 2s 時右钾,執(zhí)行完第二個 action舀射,scale 為 3
.start()
// 調(diào)用 start 開始執(zhí)行 cc.tween
cc.tween 提供了兩個設(shè)置屬性的 API:
to
:對屬性進(jìn)行絕對值計算脆烟,最終的運行結(jié)果即是設(shè)置的屬性值邢羔,即改變到某個值。
by
:對屬性進(jìn)行相對值計算框冀,最終的運行結(jié)果是設(shè)置的屬性值加上開始運行時節(jié)點的屬性值敏簿,即變化值惯裕。
cc.tween(node)
.to(1, {scale: 2}) // node.scale === 2
.by(1, {scale: 2}) // node.scale === 4 (2 + 2)
.by(1, {scale: 1}) // node.scale === 5
.to(1, {scale: 2}) // node.scale === 2
.start()
tween 可以支持任意對象的任意屬性
let obj = { a: 0 }
cc.tween(obj).to(1, { a: 100 }).start()
修改緩動函數(shù) Ease EaseType(動畫曲線)
查看cocos的Easing類型
// 傳入 easing 名字撑刺,直接使用內(nèi)置 easing 函數(shù)
cc.tween().to(1, { scale: 2 }, { easing: 'sineOutIn'})
// 使用自定義 easing 函數(shù)
cc.tween().to(1, { scale: 2 }, { easing: t => t*t; })
// 只對單個屬性使用 easing 函數(shù)
// value 必須與 easing 或者 progress 配合使用
cc.tween().to(1, { scale: 2, position: { value: cc.v3(100, 100, 100), easing: 'sineOutIn' } })
可以用自定義 progress
函數(shù)來控制緩動
可以復(fù)制當(dāng)前緩動并且接受一個target
:tween.clone(cc.find('Canvas/cocos')).start()
可以不用.start()
够傍,而是創(chuàng)建一些固定緩動然后再組合
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)})
// 先縮放再旋轉(zhuǎn)
cc.tween(this.node).then(scale).then(rotate)
緩動可以借助 parallel
實現(xiàn)并行王带,而不是按照原本的sequence
的方式
let t = cc.tween;
t(this.node)
// 同時執(zhí)行兩個 cc.tween
.parallel(
t().to(1, { scale: 2 }),
t().to(2, { position: cc.v2(100, 100) })
)
.call(() => {
console.log('All tweens finished.')
})
.start()
可以在動作執(zhí)行中進(jìn)行函數(shù)回調(diào)
cc.tween(this.node)
.to(2, { rotation: 90})
.to(1, { scale: 2})
// 當(dāng)前面的動作都執(zhí)行完畢后才會調(diào)用這個回調(diào)函數(shù)
.call(() => { cc.log('This is a callback') })
.start()
重復(fù)執(zhí)行 repeat
repeatForever
cc.tween(this.node)
.by(1, { scale: 1 })
// 對前一個 by 重復(fù)執(zhí)行 10次
.repeat(10)
// 最后 node.scale === 11
.start()
// 也可以這樣用
cc.tween(this.node)
.repeat(10,
cc.tween().by(1, { scale: 1 })
)
.start()
// 一直重復(fù)執(zhí)行下去
cc.tween(this.node)
.by(1, { scale: 1 })
.repeatForever()
.start()
延遲執(zhí)行
cc.tween(this.node)
// 延遲 1s
.delay(1)
.to(1, { scale: 2 })
// 再延遲 1s
.delay(1)
.to(1, { scale: 3 })
.start()
計時器
在 Cocos Creator 中,我們?yōu)榻M件提供了方便的計時器搞挣,這個計時器源自于 Cocos2d-x 中的 cc.Scheduler
囱桨,我們將它保留在了 Cocos Creator 中并適配了基于組件的使用方式舍肠。
也許有人會認(rèn)為 setTimeout
和 setInterval
就足夠了翠语,開發(fā)者當(dāng)然可以使用這兩個函數(shù)肌括,不過我們更推薦使用計時器谍夭,因為它更加強(qiáng)大靈活,和組件也結(jié)合得更好袁辈!
下面這個計時器將每隔 5s 執(zhí)行一次吵瞻。
component.schedule(function() {
this.doSomething();
}, 5);
下面的計時器將在 10 秒后開始計時橡羞,每 5 秒執(zhí)行一次回調(diào)卿泽,執(zhí)行 3 + 1 次滋觉。
// 以秒為單位的時間間隔
var interval = 5;
// 重復(fù)次數(shù)
var repeat = 3;
// 開始延時
var delay = 10;
component.schedule(function() {
// 這里的 this 指向 component
this.doSomething();
}, interval, repeat, delay);
只執(zhí)行一次的計時器
component.scheduleOnce(function() {
this.doSomething();
}, 2);
用回調(diào)函數(shù)取消計時器
this.count = 0;
this.callback = function () {
if (this.count === 5) {
// 在第六次執(zhí)行回調(diào)時取消這個計時器
this.unschedule(this.callback);
}
this.doSomething();
this.count++;
}
component.schedule(this.callback, 1);
schedule
:開始一個計時器
scheduleOnce
:開始一個只執(zhí)行一次的計時器
unschedule
:取消一個計時器
unscheduleAllCallbacks
:取消這個組件的所有計時器
控制腳本的執(zhí)行順序
使用統(tǒng)一的控制腳本來初始化其他腳本
其中在 Player.js第租、Enemy.js 和 Menu.js 中需要實現(xiàn) init 方法慎宾,并將初始化邏輯放進(jìn)去。這樣我們就可以保證 Player术健、Enemy 和 Menu 的初始化順序荞估。
// Game.js
const Player = require('Player');
const Enemy = require('Enemy');
const Menu = require('Menu');
cc.Class({
extends: cc.Component,
properties: {
player: Player,
enemy: Enemy,
menu: Menu
},
onLoad: function () {
this.player.init();
this.enemy.init();
this.menu.init();
}
});
在 Update 中用自定義方法控制更新順序
同理如果要保證以上三個腳本的每幀更新順序跪腹,我們也可以將分散在每個腳本里的 update 替換成自己定義的方法:updatePlayer: function (dt) { // do player update}
尺迂,然后在Game.js
中腳本的update
里調(diào)用這些
// Game.js
update: function (dt) {
this.player.updatePlayer(dt);
this.enemy.updateEnemy(dt);
this.menu.updateMenu(dt);
}
控制同一個節(jié)點上的組件執(zhí)行順序
在同一個節(jié)點上的組件腳本執(zhí)行順序:
- 可以通過組件在 屬性檢查器 里的排列順序來控制噪裕。排列在上的組件會先于排列在下的組件執(zhí)行膳音。我們可以通過組件右上角的齒輪按鈕里的 Move Up 和 Move Down 菜單來調(diào)整組件的排列順序和執(zhí)行順序祭陷。
- 可以設(shè)置組件執(zhí)行優(yōu)先級 兵志,設(shè)置組件的
executionOrder
。executionOrder
會影響組件的生命周期回調(diào)的執(zhí)行優(yōu)先級按价。executionOrder
越小楼镐,相對于其他組件就會越優(yōu)先執(zhí)行框产。
cc.Class({
extends: cc.Component,
editor: {
executionOrder: -1
},
onLoad: function () {
cc.log('Player onLoad!');
}
});
標(biāo)準(zhǔn)網(wǎng)絡(luò)接口
在 Cocos Creator 中,我們支持 Web 平臺上最廣泛使用的標(biāo)準(zhǔn)網(wǎng)絡(luò)接口:
XMLHttpRequest:用于短連接
WebSocket:用于長連接
這部分暫時不了解 错洁,參考文檔 標(biāo)準(zhǔn)網(wǎng)絡(luò)接口
對象池
cocos自帶有cc.NodePool
的對象池茅信,使用可參考文檔 使用對象池
模塊化腳本
Cocos Creator 允許你將代碼拆分成多個腳本文件,并且讓它們相互調(diào)用墓臭。要實現(xiàn)這點蘸鲸,你需要了解如何在 Cocos Creator 中定義和使用模塊,這個步驟簡稱為 模塊化窿锉。感覺這個東西類似于引用變量酌摇,然后提供了一個public的引用進(jìn)行代碼之間的耦合。
如果你還不確定模塊化究竟能做什么嗡载,模塊化相當(dāng)于:
- Java 和 Python 中的
import
- C# 中的
using
- C/C++ 中的
include
- HTML 中的
<link>
模塊化使你可以在 Cocos Creator 中引用其它腳本文件:
- 訪問其它文件導(dǎo)出的參數(shù)
- 調(diào)用其它文件導(dǎo)出的方法
- 使用其它文件導(dǎo)出的類型
- 使用或繼承其它 Component
Cocos Creator 中的 JavaScript 使用和 Node.js 幾乎相同的 CommonJS 標(biāo)準(zhǔn)來實現(xiàn)模塊化窑多,簡單來說:
- 每一個單獨的腳本文件就構(gòu)成一個模塊
- 每個模塊都是一個單獨的作用域
- 以 同步 的
require
方法來引用其它模塊 - 設(shè)置
module.exports
為導(dǎo)出的變量
在本文中,“模塊”和“腳本”這兩個術(shù)語是等價的埂息。所有“備注”都屬于進(jìn)階內(nèi)容,一開始不需要了解。
不論模塊如何定義,所有用戶代碼最終會由 Creator 編譯為原生的 JavaScript,可直接在瀏覽器中運行。
引用模塊
var Rotate = require("Rotate");
require 返回的就是被模塊導(dǎo)出的對象,通常我們都會將結(jié)果立即存到一個變量(var Rotate
)幕侠。傳入 require
的字符串就是模塊的文件名舞箍,這個名字不包含路徑也不包含后綴捎迫,而且大小寫敏感崔兴。
派生范例
var Rotate = require("Rotate");
var SinRotate = cc.Class({
extends: Rotate,
update: function (dt) {
this.rotation += this.speed * Math.sin(dt);
}
});
定義模塊
如果你的模塊是extends:cc.Component
的話,在腳本中聲明了一個組件损同,Creator 會默認(rèn)把它導(dǎo)出何什,其它腳本直接 require 這個模塊就能使用這個組件。
但是模塊導(dǎo)出的也可以是任意的JavaScript對象黍衙,只要通過 module.exports = xxx;
就可以導(dǎo)出
module.exports
默認(rèn)是一個空對象({})方椎,可以直接往里面增加新的字段摄欲。
module.exports = {
FOO: function () {
this.type = "foo";
},
bar: "bar"
};
在腳本內(nèi)定義的變量可以通過封裝來進(jìn)行訪問:
// foobar.js:
var dirty = false;
module.exports = {
setDirty: function () {
dirty = true;
},
isDirty: function () {
return dirty;
},
};