遊戲中常用到的事件分發機制
遊戲中常常需要處理不同層之間的事件傳遞以及自定義使用者資料,在不使用函式傳遞的時候,常常用到時間的監聽與分發。
第一種:簡單事件監聽(“一次監聽” 可多處觸發)
local EventListener = {}
local events = {}
-- 相同的事件名只能註冊一次
function EventListener.registerEvent(eventName, handler)
events[eventName] = handler
end
function EventListener.dispatchEvent(eventName, ...)
local handler = events[eventName]
if handler then
return handler(...)
else
-- print(eventName .. " handler not found")
end
end
return EventListener
這個方法是將註冊的事件監聽新增至 table Events(事件名作key,所以同一事件只能註冊一次),然後在觸發條件處通過遍歷 table找到對應的key,再執行傳入的handler持有的方法( 可以多處觸發 )。比較容易理解,適合模組內呼叫。
第二種:全域性事件監聽(多處監聽,多處觸發)
local EventManager = class("EventManager")
local node = display.newNode()
node:retain()
local eventDispatcher = node:getEventDispatcher()
eventDispatcher:retain()
--建立一個監聽事件,第一個引數是事件的鍵值名(事件名) 第二個引數是回撥函式。
--同一事件可以多處監聽,即回撥函式可以不同,因為這裡的觸發事件不是放在table表中的
function EventManager.addEventListener(evtName,callback)
local listener = cc.EventListenerCustom:create(evtName,callback)
eventDispatcher:addEventListenerWithFixedPriority(listener, 1)
return listener
end
--可以多處監聽,自然可以多處觸發,可以傳遞不同引數,通過eventDispatcher:dispatchEvent(event)觸發
function EventManager.dispatchEvent(evtName,data)
local event = cc.EventCustom:new(evtName)
local evtData = nil
if data == nil then
evtData = {}
elseif type(data) ~= "table" then
evtData = data
else
evtData = data
end
evtData.name = evtName
event.data = evtData
eventDispatcher:dispatchEvent(event)
end
--在不需要監聽事件時,將監聽移除(與事件的監聽成對使用)
function EventManager.removeEventListener(evtName)
eventDispatcher:removeCustomEventListeners(evtName)
end
function EventManager.removeEventListenerByHandler(evtHandler)
eventDispatcher:removeEventListener(evtHandler)
end
return EventManager
有人說這是觀察者模式,MVC模式的一種,一個model可以對應很多個觀察者view(註冊事件行為),當model收到事件通知時(事件觸發條件,傳遞資料),對應的view馬上處理事件(執行回撥函式)。