cocos2d-x版本: 3.8.1
需求
游戏逻辑中有需要添加touch屏蔽层的需求,比如说现在要点击按钮发送一条内部消息创建A界面,创建动作实际是在下一帧或者下一个定时器调度时才开始执行,如果快速点击按钮则会发送多条消息。这种情况是需要规避的。
Cocos2d-x引擎是建立在Layer概念上的,多层layer有上下关系;屏蔽层应该设计在最上层,而且屏蔽层应该有swallow和unswallow的接口;但是调用时机需要把握准确。
设计思路、需要注意的问题
思路:点击按钮时发送消息,同时设置屏蔽层swallow,下一帧或者下一个定时调度时设置屏蔽层unswallow
这个思路一般情况下不会出问题,在这个swallow->unswallow的时间内,所有的touch事件都会被屏蔽层吸收;但是在单点Listener和多点Listener混合使用时会有一点小问题,根源在于:
1、touch事件的执行不依赖帧循环
2、帧事件或者时间调度都依赖帧循环
3、单点Listener的onTouchMoved、onTouchEnded、onTouchCancelled事件依赖onTouchBegan;只有onTouchBegan返回true,后续的事件才会触发
4、多点Listener的onTouchesMoved、onTouchesEnded、onTouchesCancelled事件不依赖onTouchesBegan,也就是说就算onTouchesBegan没有执行,后续的moved,ended,cancelled事件一样会被触发
根据事件派发机制,考虑下面情况:
1、touch屏蔽层在最高层
2、中间有多个注册了单点Listener的层, 其中有设置为swallow的层
3、再下面是一个或多个注册了多点Listener的层,并且设置为swallow
这时会有这样一种情况:began事件发生时,屏蔽层swallow掉当前touch,接下来下一帧或者下一个定时器执行,设置屏蔽层为unswallow;那么后续该touch的moved、ended操作都会传递到注册了多点Listener的层中,这种情况并不是我们希望的
这时可能会觉得中间的层会swallow掉相关的事件,而不会传递到上面描述3中的层中;但因为中间层只是注册单点Listener,began事件被屏蔽层swallow掉了,中间层注册的Listener Began事件并没有触发,所以后续的moved、ended等事件也不会触发;根据上面提到的 根源4,多点Listener的moved、ended等事件将触发
改进
原思路是在下一帧或者下一个定时调度时设置屏蔽层unswallow,改成:下一帧或者下一个定时调度时设置一个标记,在屏蔽层的onTouchBegan方法中根据该标记设置屏蔽层为unswallow,并且清除标记