cocos2d-x版本: 3.8.1
需求
游戲邏輯中有需要添加touch屏蔽層的需求菩帝,比如說現(xiàn)在要點(diǎn)擊按鈕發(fā)送一條內(nèi)部消息創(chuàng)建A界面笛园,創(chuàng)建動(dòng)作實(shí)際是在下一幀或者下一個(gè)定時(shí)器調(diào)度時(shí)才開始執(zhí)行尝哆,如果快速點(diǎn)擊按鈕則會(huì)發(fā)送多條消息绊含。這種情況是需要規(guī)避的市殷。
Cocos2d-x引擎是建立在Layer概念上的纫事,多層layer有上下關(guān)系渗鬼;屏蔽層應(yīng)該設(shè)計(jì)在最上層担锤,而且屏蔽層應(yīng)該有swallow和unswallow的接口;但是調(diào)用時(shí)機(jī)需要把握準(zhǔn)確乍钻。
設(shè)計(jì)思路肛循、需要注意的問題
思路:點(diǎn)擊按鈕時(shí)發(fā)送消息顾稀,同時(shí)設(shè)置屏蔽層swallow镣陕,下一幀或者下一個(gè)定時(shí)調(diào)度時(shí)設(shè)置屏蔽層unswallow
這個(gè)思路一般情況下不會(huì)出問題,在這個(gè)swallow->unswallow的時(shí)間內(nèi)知纷,所有的touch事件都會(huì)被屏蔽層吸收浩考;但是在單點(diǎn)Listener和多點(diǎn)Listener混合使用時(shí)會(huì)有一點(diǎn)小問題夹孔,根源在于:
1、touch事件的執(zhí)行不依賴幀循環(huán)
2析孽、幀事件或者時(shí)間調(diào)度都依賴幀循環(huán)
3搭伤、單點(diǎn)Listener的onTouchMoved、onTouchEnded袜瞬、onTouchCancelled事件依賴onTouchBegan怜俐;只有onTouchBegan返回true,后續(xù)的事件才會(huì)觸發(fā)
4邓尤、多點(diǎn)Listener的onTouchesMoved拍鲤、onTouchesEnded、onTouchesCancelled事件不依賴onTouchesBegan汞扎,也就是說就算onTouchesBegan沒有執(zhí)行季稳,后續(xù)的moved,ended澈魄,cancelled事件一樣會(huì)被觸發(fā)
根據(jù)事件派發(fā)機(jī)制景鼠,考慮下面情況:
1、touch屏蔽層在最高層
2痹扇、中間有多個(gè)注冊(cè)了單點(diǎn)Listener的層, 其中有設(shè)置為swallow的層
3铛漓、再下面是一個(gè)或多個(gè)注冊(cè)了多點(diǎn)Listener的層,并且設(shè)置為swallow
這時(shí)會(huì)有這樣一種情況:began事件發(fā)生時(shí)帘营,屏蔽層swallow掉當(dāng)前touch票渠,接下來下一幀或者下一個(gè)定時(shí)器執(zhí)行逐哈,設(shè)置屏蔽層為unswallow芬迄;那么后續(xù)該touch的moved、ended操作都會(huì)傳遞到注冊(cè)了多點(diǎn)Listener的層中昂秃,這種情況并不是我們希望的
這時(shí)可能會(huì)覺得中間的層會(huì)swallow掉相關(guān)的事件禀梳,而不會(huì)傳遞到上面描述3中的層中杜窄;但因?yàn)橹虚g層只是注冊(cè)單點(diǎn)Listener,began事件被屏蔽層swallow掉了算途,中間層注冊(cè)的Listener Began事件并沒有觸發(fā)塞耕,所以后續(xù)的moved、ended等事件也不會(huì)觸發(fā)嘴瓤;根據(jù)上面提到的 根源4扫外,多點(diǎn)Listener的moved、ended等事件將觸發(fā)
改進(jìn)
原思路是在下一幀或者下一個(gè)定時(shí)調(diào)度時(shí)設(shè)置屏蔽層unswallow廓脆,改成:下一幀或者下一個(gè)定時(shí)調(diào)度時(shí)設(shè)置一個(gè)標(biāo)記筛谚,在屏蔽層的onTouchBegan方法中根據(jù)該標(biāo)記設(shè)置屏蔽層為unswallow,并且清除標(biāo)記