0.背景
在游戲的UI中,往往會(huì)出現(xiàn)這樣的情況:
在某個(gè)戰(zhàn)斗副本中獲得了某個(gè)道具A,那么當(dāng)進(jìn)入主界面的時(shí)候,你會(huì)看到你的背包UI上有個(gè)小紅點(diǎn)(意思是有新道具),點(diǎn)擊進(jìn)入背包后,發(fā)現(xiàn)新增了道具A,顯示個(gè)數(shù)為1,并且在下個(gè)界面中有個(gè)使用的按鈕由灰色不可使用變成橙色的可使用狀態(tài)

圖1. 事件觸發(fā)說明圖
其中這里是由道具獲得這個(gè)事件,觸發(fā)了上述的三個(gè)行為。如果使用顯示調(diào)用行為,會(huì)使得代碼難擴(kuò)展,易出錯(cuò),邏輯混亂等問題,如果使用Event回調(diào)機(jī)制,就會(huì)變得十分方便。
其實(shí)Event回調(diào)機(jī)制就是觀察者模式,如下圖:

圖2. 觀察者模式
在C#中存在(delegate & event)的語義來實(shí)現(xiàn)Event回調(diào)機(jī)制:具體使用如下:
public delegate void NewToolGotEvent();public class ToolBag{ event NewToolGotEvent newToolGotHandler; void Start() { newToolGotHandler += renderRedPoint; newToolGotHandler += renderNewTool; newToolGotHandler += renderAvaliableUseBtn; } void renderRedPoint() { //TODO } void renderNewTool() { //TODO } void renderAvaliableUseBtn() { //TODO } void EventHappened() { newToolGotHandler(); // usage, fill args if necessary }}如果在Python,可以在注冊(cè)事件的回調(diào)時(shí),帶入一個(gè)參數(shù)callback,在注冊(cè)函數(shù)實(shí)體內(nèi),存在一個(gè)list將callback添加進(jìn)去,形如:
def register_callback(self, cb): self.callbacks.append(cb)
但是這樣是一個(gè)最為普遍的做法,既然是Python,這里我們有更Pythonic的做法,而且相比于上述的觀察者模式,它的做法更加簡(jiǎn)潔,使用更加方便,接下來我們來解析一下Python實(shí)現(xiàn)Event callback的步驟。
1. UML類圖
上述案例中,是針對(duì)游戲客戶端UI的案例。所以我們呈現(xiàn)出的UML圖也是與UI相關(guān)。如圖3所示,它顯示了Python中實(shí)現(xiàn)Event回調(diào)的機(jī)制。

圖3. UML關(guān)系圖
如上圖所示,此機(jī)制主要由三個(gè)類及他們的實(shí)例(instance)組成:UIBase, UIScene, UIDataEvent。
1 . UIBase: 所有UIScene的基類,其實(shí)例有scene_id變量,包含兩個(gè)必要的方法, __init__ 是初始化方法,init_data_listeners方法是將實(shí)例中的某些方法, 例如ui_updata_func中包含的UIDataEvent實(shí)例(所有的UIDataEvent實(shí)例都是單例)遍歷,并把ui_update_func注冊(cè)在每一個(gè)UIDataEvent實(shí)例中。
2 . UIScene: 場(chǎng)景類,管理某個(gè)場(chǎng)景的UI渲染。在其實(shí)例中,存在某些方法,例如ui_update_func需要在某些UIDataEvent實(shí)例觸發(fā)時(shí)候,也被同時(shí)觸發(fā)調(diào)用。ui_update_func在Python中一個(gè)bound method object, 它會(huì)擁有一個(gè)特殊的屬性events,即所有需要觸發(fā)此方法的UIDataEvent實(shí)例集合。這個(gè)通過裝飾器(decorator)來實(shí)現(xiàn),即圖中的:
新聞熱點(diǎn)
疑難解答
圖片精選