cocos2d-x 一道简单面试题,触摸事件的重新分发

转载请注明出处 http://blog.csdn.net/rct1985


前段时候换工作时,去触控科技面试,面试官问了这么一个问题。”当弹出一个新窗口时,如果屏蔽掉下面层的触摸事件?“
这个问题对于接触cocos2d引擎一段时间的同学来说,都不算难。当时我想到了两种解决方案,也是在之前项目中用到过的:


一、加一个屏蔽层,TouchMaskLayer, 它的写法差不多就是
a. CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, kCCMenuTouchPriority, true);
b. ccTouchBegan 中 return true;
二、先把本层的触摸开关手动关掉,再加弹出层,实现方式差不多是 :
a. 本层实现 onControl() 和 lostControl(), 把本层触摸相关的对象(CCLayer, CCMenu CCEditbox,...)setTouchEnable(true/false),
b.弹出新层之前,调用lostControl(), 新层关掉时回调onControl()


第一种写法简单粗暴,简单的逻辑可以直接这么用。它的问题是,如果弹出层上需要多点触摸的话,这是行不通的,因为多点触摸优先级没有TouchMaskLayer高,它将得不到事件。
第二种方法,是和三国塔防程序同事杨新宁,魏莱一起讨论而来的。这种方式我一直在用,除了麻烦一些外,没发现任何问题。其实这种方式也没想象中的麻烦,因为一个场景中可以有触摸事件的对象也就那几个。


我问他们有什么更好的方式时,捕鱼2主程汪东林(在些表示感谢)说了他们的做法,自己处理事件分发。我根据这个想法自己做了个弹出层的基类UpperLayer


【cocos2d-x 一道简单面试题,触摸事件的重新分发】
[cpp]view plain copy print ?

  1. //
  2. //UpperLayer.h
  3. //MythLeague
  4. //
  5. //Created by raochongtao on 13-6-26.
  6. //
  7. //
  8. /* 功能
  9. * 1. 弹出层的基类, 比下层拥有更高的优先级, 用于屏蔽下层,及本层外触摸事件
  10. * 2. 提供一个容量,及相应方法,用于装纳需要处理事件的对象 CCTouchDelegate*对象,
  11. */
  12. #ifndef __MythLeague__UpperLayer__
  13. #define __MythLeague__UpperLayer__
  14. #include "Global/Constants.h"
  15. #include "CommonLayer/TouchLogicLayer.h"
  16. class UpperLayer : publicTouchLogicLayer{
  17. public:
  18. UpperLayer();
  19. virtual ~UpperLayer();
  20. bool init();
  21. void onEnter();
  22. void onExit();
  23. void registerWithTouchDispatcher();
  24. void appendToTouchDispatch(cocos2d::CCTouchDelegate* p_touchableObject);
  25. #pragma mark 触摸相关
  26. //开始
  27. bool ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
  28. //移动
  29. void ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
  30. //结束
  31. void ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
  32. //点击home键或其它方式引起的取消
  33. void ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
  34. public:
  35. //cocos2d::CCArray* m_touchDispatchTable;
  36. std::vector m_touchDispatchTable;
  37. int m_iIndex; //m_iIndex-1为实际索引
  38. };
  39. #endif /* defined(__MythLeague__UpperLayer__) */

[cpp]view plain copy print ?
  1. //
  2. //UpperLayer.cpp
  3. //MythLeague
  4. //
  5. //Created by raochongtao on 13-6-26.
  6. //
  7. //
  8. #include "UpperLayer.h"
  9. using namespace cocos2d;
  10. UpperLayer::UpperLayer(){
  11. }
  12. UpperLayer::~UpperLayer(){
  13. }
  14. bool UpperLayer::init(){
  15. bool l_bResult = true;
  16. do {
  17. if(!TouchLogicLayer::init()){
  18. l_bResult = false;
  19. }
  20. } while (0);
  21. return l_bResult;
  22. }
  23. void UpperLayer::onEnter(){
  24. TouchLogicLayer::onEnter();
  25. }
  26. void UpperLayer::onExit(){
  27. TouchLogicLayer::onExit();
  28. }
  29. void UpperLayer::registerWithTouchDispatcher()
  30. {
  31. cocos2d::CCDirector* pDirector = cocos2d::CCDirector::sharedDirector();
  32. pDirector->getTouchDispatcher()->addTargetedDelegate(this, kCCMenuHandlerPriority-1, true);
  33. }
  34. void UpperLayer::appendToTouchDispatch(CCTouchDelegate* p_touchableObject){
  35. //断言,p_touchableLayer是CCLayer*类型, (可以是继承)
  36. CCAssert(dynamic_cast(p_touchableObject) != NULL, "p_touchableLayer must be a layer");
  37. m_touchDispatchTable.push_back(p_touchableObject);
  38. }
  39. #pragma mark 触摸相关
  40. //开始
  41. bool UpperLayer::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){
  42. //super
  43. TouchLogicLayer::ccTouchBegan(pTouch, pEvent);
  44. m_iIndex = Common_Empty;
  45. CCTouchDelegate* l_touchAble = NULL;
  46. int l_iIndex = 0;
  47. for (; l_iIndex
  48. l_touchAble = m_touchDispatchTable[l_iIndex];
  49. if (l_touchAble && l_touchAble->ccTouchBegan(pTouch, pEvent))
  50. {
  51. m_iIndex = l_iIndex;
  52. break;
  53. }
  54. }
  55. return true;
  56. }
  57. //移动
  58. void UpperLayer::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){
  59. //super
  60. TouchLogicLayer::ccTouchMoved(pTouch, pEvent);
  61. if (m_iIndex >= 0) {
  62. CCTouchDelegate* l_touchAble = m_touchDispatchTable[m_iIndex];
  63. l_touchAble->ccTouchMoved(pTouch, pEvent);
  64. }
  65. }
  66. //结束
  67. void UpperLayer::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){
  68. //super
  69. TouchLogicLayer::ccTouchEnded(pTouch, pEvent);
  70. if (m_iIndex >= 0) {
  71. CCTouchDelegate* l_touchAbleLayer = m_touchDispatchTable[m_iIndex];
  72. l_touchAbleLayer->ccTouchEnded(pTouch, pEvent);
  73. }
  74. }
  75. //点击home键或其它方式引起的取消
  76. void UpperLayer::ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){
  77. }

    推荐阅读