摘要:事件中事件分發機制進行了重寫,事件可以與任意對象綁定,而不是只有才能獲取。這就形成了一個完整的事件分發機制。如果返回,且為,則事件被吞沒,事件的順序傳遞則被阻止。
這兩天在使用cocos2d-js做一個拔蘿卜游戲,研究了一番cocos2d的事件分發機制,總結分享一下。
事件Cocos2d-JS v3.x中事件分發機制進行了重寫,事件可以與任意對象綁定,而不是只有Layer才能獲取。對象創建自己的事件監聽器,然后加入到全局的事件管理器統一管理。
事件監聽器有以下幾種:
觸摸事件
鍵盤響應事件
鼠標響應事件
自定義事件
加速計事件
事件分發在了解事件分發機制之前,我們首先要明確什么是事件分發。
對于事件分發,cocos2d官方定義為:當事件發生(例如,用戶觸摸屏幕,或者敲鍵盤),EventDispatcher 會發布(Event objects)事件對象到合適的EventListeners,并調用你的回調。各個Event object包含事件的信息(比如,觸摸點所在的坐標)。
我的理解是對于一個事件(比如觸摸事件、鍵盤相應事件等)可以與任意對象綁定,那么當這個事件被用戶觸發時,此時應該執行哪一個對象的回調函數(比如此時我們在好幾個sprite上同時綁定了touch事件,用戶此時點擊屏幕,用戶此時想點擊的到底是哪一個sprite),我們就需要作出判斷。EventDispatcher做的就是這個事情。
以touch事件(觸摸事件)為例,判斷用戶點擊的是哪一個sprite的方法很簡單,其實就是在onTouchBegan方法中獲取點擊點的坐標pos,然后通過cc.rectContainsPoint(target.getBoundingBox(),pos)判斷點擊的點是否在SushiSprite上。不過此時又會出現另外一個問題,就是如果兩個sprite有相互重疊的部分,而此時用戶點擊的恰恰是重疊部分,那么怎么判斷到底點擊的是哪一個sprite呢?這里是通過priority(分為兩種:SceneGraphPriority和FixedPriority)來解決的,優先級高的sprite優先執行它所對應的事件監聽器的回調函數。這樣就形成了一個按照優先級高低排列的sprite隊列等待依次執行用戶觸發的事件,而這中間則通過swallowTouches(吞沒事件)屬性來控制是否繼續向優先級低的sprite傳遞事件。這就形成了一個完整的事件分發機制。
tip:
SceneGraphPriority(顯示優先級):根據屏幕顯示的“遮蓋”實際情況,進行有序的函數回調。zOrder越大,優先級越大。
FixedPriority(固定優先級):依據手動設定的 Priority 值來決定事件相應的優先級,值越小優先級越高
總結一下:
通過點擊位置進行點擊范圍判斷,來確定執行哪一個sprite的事件監聽器
如果該位置存在重疊的sprite綁定了相同的事件,則依據優先級(SceneGraphPriority顯示優先級或FixedPriority固定優先級)來順序執行函數回調
通過設置swallowTouches屬性為true,并在onTouchBegan中返回true或者false來決定是否阻止事件的順序傳遞。如果onTouchBegan返回true,且swallowTouches為true,則事件被吞沒,事件的順序傳遞則被阻止。
實例新建一個sprite,并為其添加一個touch事件:
var SushiSprite = cc.Sprite.extend({ onEnter:function () { cc.log("onEnter"); this._super(); }, onExit:function () { cc.log("onExit"); } }); addTouchEventListenser:function(){ this.touchListener = cc.EventListener.create({ event: cc.EventListener.TOUCH_ONE_BY_ONE, // When "swallow touches" is true, then returning "true" from the onTouchBegan method will "swallow" the touch event, preventing other listeners from using it. swallowTouches: true, //onTouchBegan event callback function onTouchBegan: function (touch, event) { var pos = touch.getLocation(); var target = event.getCurrentTarget(); if ( cc.rectContainsPoint(target.getBoundingBox(),pos)) { cc.log("touched") return true; } return false; } cc.eventManager.addListener(this.touchListener,this); });
上面的代碼:
首先通過使用cc.EventListener.create創建了一個Touch事件監聽器touchListener
然后,通過cc.eventManager.addListener注冊監聽器到事件管理器。cc.EventListener.create擴展出一個用戶監聽器。
event屬性,定義這個監聽器監聽的類型。
swallowTouches屬性設置是否吃掉事件,事件被吃掉后不會遞給下一層監聽器。
onTouchBegan方法處理觸摸點擊按下事件,我們在這里可以獲取到觸摸點的坐標pos。event.getCurrentTarget()獲取當前事件的接受者,并判斷當前的是否點擊到了SushiSprite。
在touch事件中,我們還可以添加onTouchMoved/onTouchEnded方法監聽touch移動和結束的回調。如果onTouchBegan返回false后onTouchMoved/onTouchEnded不會執行。
tip: 在onTouchBegan方法中獲取點擊點的坐標pos,然后通過cc.rectContainsPoint(target.getBoundingBox(),pos)判斷點擊的點是否在SushiSprite上。
博客文章地址:http://joebon.cc/cocos2d-event-dispatcher
參考文獻[1] http://cn.cocos2d-x.org/article/index?type=cocos2d-x&url=/doc/cocos-docs-master/manual/framework/cocos2d-js/3-jumping-into-cocos2d-js/3-6-creating-user-interaction-with-event-manager/zh.md
[2] http://cn.cocos2d-x.org/article/index?type=wiki&url=/doc/cocos-docs-master/manual/framework/native/wiki/eventdispatcher-mechanism/zh.md
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79436.html
閱讀 2308·2021-11-24 09:39
閱讀 3038·2021-10-15 09:39
閱讀 3088·2021-07-26 23:38
閱讀 2288·2019-08-30 11:14
閱讀 3409·2019-08-29 16:39
閱讀 1713·2019-08-29 15:23
閱讀 778·2019-08-29 13:01
閱讀 2663·2019-08-29 12:29