獨孤九劍與乾坤大挪移—uikiller外掛系統
上篇《雷神之錘》介紹了uikiller的基本用法,有人說長按功能可以取名為蓄力攻擊、重擊,我覺得還真是可以的,但就是感覺招數名字不夠大氣。在這裡還要給大家道個歉,上篇中我說了這一樣句話:
uikiller只有一行需要要被主動呼叫的函式:uikiller.bindComponent
不好意思,在這裡我可能隱瞞了大家,除了uikiller.bindComponent以外,還有一行可以被主動呼叫的函式
uikiller.bindNode(node, target)
這次希望我能把uikiller全部祕密給抖動出來,請各位不要太過驚訝!
一、獨孤九劍
之前的篇幅主要介紹了uikiller的一系的招數、連擊等,接下來講講uikiller的另一種絕技,它是爭對敵人不同的招數一一破解的功法:獨孤九劍
1. 總決式
總決式中體現外掛類的寫法,主要的屬性和事件函式名
let UIKillerPlugin = { name: '外掛名字', onRegister() { //當外掛註冊時響應 }, onCheckNode(node, target) { //當一個node將要被繫結時響應,返回false將不會繫結該節點下的子節點 }, onBeforeHandleEvent(node, event, hasEventFunc) { //當一個節點的事件處理函式執行前響應 }, onAfterHandleEvent(node, event, hasEventFunc, eventResult) { //當一個節點的事件處理函式執行後響應 } }; //註冊外掛 uikiller.registerPlugin(UIKillerPlugin);
uikiller的外掛是一組事件勾子函式,這些勾子函式不一定都要實現,但一般至少要實現一個才有意義,瞭解了總決式,我們來看看能做些什麼。
2. 破劍式—過濾節點
在一些戰鬥中,英雄與魔靈只需要站在那裡,擺擺pose就夠了,不需要被指揮(無需呼叫節點或元件上的方面)。可以將這些英雄們請到VIP席上就坐。
let UIKillerBindFilter = { name: 'UIKillerBindFilter', onCheckNode(node, target) { if (node === target.node) { return true; } //過濾掉首字母為“@”的節點下的子節點 if (node.name[0] === '@') { return false; } /*在bindNode\bindComponent的最後一個引數是一個options物件*/ /*呼叫options上的過濾函式,進行節點過濾*/ let options = target.$options; if (uikiller.isFunction(options.filter)) { if (options.filter(node)) { return false; } } } }; uikiller.registerPlugin(UIKillerBindFilter);
在編輯器中,當節點以名“@”開頭,他下面的子節點都不能會被綁定了。如果你還想複雜點你可以嘗試用正則表示式過濾節點名。
遇到複雜的情況可以使用bindNode或bindComponent上的最後一個引數,設定一個filter函式實現動態過濾。
//元件程式碼
onLoad() {
uikiller.bindComponent(this, { filter: (node) => {
//在此可以根據node名字、型別等屬性進行過濾
}})
}
3. 破刀式—Label的問題
Label是一個作戰頻次特別高的魔靈(component),但是問題也多,比如:字型、多語言特別的煩人,就像插在心口上的一把刀,這裡介紹一種破多語言的方法。
const UIKillerLabelLanguage = {
name: 'UIKillerLabelLanguage',
onCheckNode(node, target) {
//檢查節點是否有label元件
let label = node.getComponent(cc.Label);
if (!label) {
return;
}
//以節點名上的$為多語言key,如果不存在以name為多語言key
let key = node.$ || node.name;
//使用i18n獲取多語言文字
label.string = i18n.t(key);
}
};
這種方法不用為裝備有Label的英雄(node)部署一個魔靈(component),直接在英雄的名字上做文章是不是更直接一些呢?除了Label外,還可以應用到EditBox\RichText之上,更多招數自己去發明創造!
4. 破槍式—音效控制
英雄、魔靈們奮勇作戰,在戰場上各種機槍、手槍、來福槍此起彼伏,喊殺聲中還有帶上背景音樂,可是在奎特爾上英雄是不能直接發出聲音的,那是怎麼辦的呢?看下面最常見的一種做法
onButtonTouchEnd() {
//處理一堆業務
...
//播放音效
cc.audioEngine.play(url);
}
這種做法是到處埋地雷,稍微不注意把自己給炸了,還有可能地雷弄錯了或要換地雷時,就慘了。
看看uikiller的破槍式,先定義一個音效配置
//用英雄節點的名字作key或者$名字也行
const SOUND_CONFIG = {
_attack: '3002.mp3',
_expedition: '3006.mp3',
click: 'click.mp3',
}
破槍式心法
const UIKillerTouchSound = {
name:'UIKillerTouchSound',
/**
* 事件處理函式執行完畢後觸發此函式
* @param {*} node 觸控事件節點
* @param {*} event 觸控事件物件
* @param {*} hasEventFunc 是否有事件處理函式
* @param {*} eventResult 事件處理函式返回值
*/
onAfterHandleEvent(node, event, hasEventFunc, eventResult) {
//在TouchEnd事件時,而且事件處理函式返回值不能為false
if (event.type !== cc.Node.EventType.TOUCH_END || eventResult === false) {
return;
}
//獲取聲音檔名,沒有的話統一的click聲音
let soundName = SOUND_CONFIG[eventResult] || //優先取事件返回值
SOUND_CONFIG[node.$] || //其次取$名字
SOUND_CONFIG[node.name] || //再次為節點名
SOUND_CONFIG.click; //沒有統一的click聲音
//播放音效
let url = cc.url.raw(`resources/sound/${soundName}`);
cc.audioEngine.play(url);
}
};
戰鬥實操,領略一下如此整潔的戰場,地雷沒有了,只有動聽的音效!
onLoad() {
this.bindComponent(this);
},
//有個_button節點,且寫了這個函式,不做事也會有預設音效播放
_onButtonTouchEnd() {
},
//有個_button1節點,事件函式返回了false,不會有聲音出現
_onButton1TouchEnd() {
return false;
},
//有個_attack節點,音效配置中對應“3002.mp3”,將自動播放此音效,這裡不用再費心了
_onAttackTouchEnd() {
//如果返回一個音效配置字串,將會改變聲音的播放
//return "_expedition";
},
破刀式可以作用於任何節點,不僅僅是Button,再此招式啟示下,你可以可以推演出點選時的動畫播放,比如爆炸一個粒子等等。
5. 無招勝有招
獨孤九劍以無招勝有招,是敵強我愈強,使用“獨孤九劍”,除了精熟javascript和奎特爾的世界外,還需要依賴使劍者的靈悟,一到自由揮灑、更無規範的境界,便如是大詩人靈感到來,作出了一首好詩一般。
二、乾坤大挪移
在講解乾坤大挪移之前,需要做一點點鋪墊,那就是在創造奎特爾星球上除了創世之主(程式設計師)以還,還存在兩類物種分別是:
-
神機軍師(策劃)
-
幻靈法師(美術)
1. 謀士與法師的煩惱
謀士與法師也是構建奎特爾不可缺少的人物,他們通常都是高輸出、低防禦的特質,同時謀士與法師大多都不會使用咒語(編寫程式碼)與英雄(node)和魔靈(component)做心靈溝通。
但有時謀士需要嘗試下派兵佈陣(UI佈局),法師想預覽下剛研製出的幻術(美術效果),在沒有創世之主的幫助下,經常是做的得過且過,如何解決這個問題呢?不使用任何一句咒語(程式碼),就能讓謀士和法師任意放出或收回召喚獸(prefab)
經過我對javascript咒語和奎特爾的潛心研究,創造了新的招式:乾坤大挪移心法
2. 第一層
「乾坤大挪移」第一層心法,是對javascript運用,利用原型給魔靈們增加一個createNode、destroyNode法門。
//召喚一個英雄
cc.Component.prototype.createNode = function() {
...
}
//給英雄放個假
cc.Component.prototype.destroyNode = function() {
}
這裡就不帖那麼多咒語(程式碼)了,請上github領取你的武器。
3. 第二層
第二層心法是利用cc.Button的ClickEvents事件屬性佈置召喚陣法,請看下圖:
-
給Button英雄新增一個點選處理
-
給事件cc.Node屬性設定為將要召喚出的神獸(prefab)的落腳點(父節點)
-
隨便指定一個元件
-
元件方法上選擇createNode(這是召喚核心)
-
CustomEventData設定為召喚獸的名字(prefab的路徑字串)
需要注意,召喚獸(prefab)需要放到resources目錄中。點選這個Button,就可以將召喚獸(prefab)釋放出來了。
4. 第三層
有召喚必有降伏,將不需要的英雄(node)或召喚獸(prefab)叫回去睡覺覺。
-
給Button英雄新增一個點選處理
-
cc.Node設定為想要休假的節點
-
隨便指定一個元件即可
-
選擇destroyNode方法
點選這個Button,節點就自己乖乖回家了!
乾坤大挪移的一大特點就是「激發最大潛力」,有此功夫謀士(策劃)與法師(美術)的小宇宙也可以被激發起來,同時也激發了創世之主(程式設計師)做更有創意的事情。
5. 第四層
很輕鬆的就來到練乾坤大挪移的第四層,這一層不再是謀士(策劃)和法師(美術)能輕易習得的了!前面我提到了uikiller中還有一個主動呼叫的函式: bindNode,它是修習後面幾層的基礎,功能非同小可,先看看最簡單的演示:
onLoad() {
//定義一個target物件,交UI編輯器上的節點和元件挪移到它上面去
this.target = {
//處理節點的觸控事件
_onLabelTouchEnd() {
//_label補繫結到target物件上了,可以用this直接訪問
this._label.$Label.string = 'yyy';
}
};
uikiller.bindNode(this.node, this.target);
//_label屬性已經被挪移到this.target上了,在target變數上訪問
this.target._label.x = 100;
this.target._label.$Label.string = 'xxx';
}
其實上面的演示中bindNode並不能展示他的威力,不過它體現了乾坤大挪移的精髓之一:「牽引挪移敵勁」,將一個元件上的節點和事件牽引到別的物件上。
6. 第五層
第五層了,我們來看看乾坤大挪移的「轉換陰陽二氣」的能力,接下來越下越複雜了,要細心哦,小心走火入魔。
-
建立一個傀儡魔靈,並繫結到一個prefab的根節點上
------------------XXXComponent.js--------------------
let Ctrl = require('Ctrl');
cc.Class({
extends: cc.Component,
onLoad() {
//建立一個控制器
this.ctrl = new Ctrl(this.node);
//使用bindComponent注入乾坤大挪移的陽剛之氣
uikiller.bindComponent(this);
},
/**
* 在此控制介面邏輯
*/
_onButtonTouchEnd(sender) {
//360度旋轉起來
this._button.runAction(cc.rotateBy(3, 360).repeatForever());
}
});
-
再製造一個幕後黑手一起操縱英雄(node)
let uikiller = require('uikiller');
function Ctrl(node) {
//使用bindNode注入乾坤大挪移的陰柔之力
uikiller.bindNode(node, this);
//同樣方式訪問節點與元件
this._label.$Label.string = 'xxx';
};
//定義成員函式
Ctrl.prototype = {
/**
* 在此控制業務邏輯
*/
_onButtonTouchEnd(
//處理業務邏輯
...
//發起網路請求
net.request(url, param, (data) => {
//資料來了,停止旋轉
this._button.stopAllActions();
this._button.rotation = 0;
});
}
}
上面的演示,相當於兩個人同時一起駕駛了一部坦克,一起協作,他們之間遙相呼應,發動了一個大必殺技:激無雙亂舞
看到這裡,你可能對曾經的信仰有些懷疑了,因為有這樣一個古老的傳說
在奎特爾星球上一切皆魔靈(一切皆元件)
此刻,這個傳說被打uikiller給打破了。
7. 第六層
第六層已經是很高的境界了,既然一切皆魔靈(一切皆元件)的傳說被打破了,那利用bindNode的複製對手武功、牽引挪移敵勁的能力,就不一定要構造一個魔靈(component)控制戰鬥。同時結合PureMVC + uikiller.bindNode將prefab做為mvc中的view,將view中的節點和元件挪移到meidator中,那將是另一種全新的戰鬥模式!
7. 第七層
第七層MVVM,比第六層深了數倍,不好意思我也不得要領,還得繼續修練,為了不至於走火入魔,我就不再介紹了!
四、寫在最後
uikiller中關於上述大招的使用都放到github上了,歡迎把玩
https://github.com/ShawnZhang2015/uikiller
歡迎關注「奎特爾星球」微信公眾號,有程式碼、有教程、有視訊、有故事,一起來玩吧!