Cocos Creator 2.4x 筆記 - 從Unity到Cocos [2]

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類型

ease type.png

// 傳入 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)前緩動并且接受一個targettween.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)為 setTimeoutsetInterval 就足夠了翠语,開發(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í)行順序:

  1. 可以通過組件在 屬性檢查器 里的排列順序來控制噪裕。排列在上的組件會先于排列在下的組件執(zhí)行膳音。我們可以通過組件右上角的齒輪按鈕里的 Move Up 和 Move Down 菜單來調(diào)整組件的排列順序和執(zhí)行順序祭陷。
  2. 可以設(shè)置組件執(zhí)行優(yōu)先級 兵志,設(shè)置組件的 executionOrderexecutionOrder 會影響組件的生命周期回調(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;
    },
};

腳本進(jìn)階參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末智袭,一起剝皮案震驚了整個濱河市闷哆,隨后出現(xiàn)的幾起案子嘀倒,更是在濱河造成了極大的恐慌碳胳,老刑警劉巖惜傲,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件开镣,死亡現(xiàn)場離奇詭異糠馆,居然都是意外死亡毕匀,警方通過查閱死者的電腦和手機(jī)愤炸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門掉奄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來姓建,“玉大人谍婉,你說我怎么就攤上這事」髌” “怎么了获诈?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長舔涎。 經(jīng)常有香客問我笼踩,道長,這世上最難降的妖魔是什么亡嫌? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任嚎于,我火速辦了婚禮,結(jié)果婚禮上挟冠,老公的妹妹穿的比我還像新娘于购。我一直安慰自己,他們只是感情好知染,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布肋僧。 她就那樣靜靜地躺著,像睡著了一般控淡。 火紅的嫁衣襯著肌膚如雪嫌吠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天掺炭,我揣著相機(jī)與錄音辫诅,去河邊找鬼。 笑死竹伸,一個胖子當(dāng)著我的面吹牛泥栖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播勋篓,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼吧享,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了譬嚣?” 一聲冷哼從身側(cè)響起钢颂,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拜银,沒想到半個月后殊鞭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體遭垛,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年操灿,在試婚紗的時候發(fā)現(xiàn)自己被綠了锯仪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡趾盐,死狀恐怖庶喜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情救鲤,我是刑警寧澤久窟,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站本缠,受9級特大地震影響斥扛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜丹锹,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一稀颁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧卷仑,春花似錦峻村、人聲如沸麸折。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽垢啼。三九已至窜锯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間芭析,已是汗流浹背锚扎。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留馁启,地道東北人驾孔。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像惯疙,于是被迫代替她去往敵國和親翠勉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容