先把跟Touch相关的类列一下:
EAGLView
CCEGLView
CCEGLViewProtocol
EGLTouchDelegate
CCTouchDispatcher
CCTouchHandler
CCStandardTouchHandler
CCTargetedTouchHandler
CCTouchDelegate
CCTargetedTouchDelegate
CCStandardTouchDelegate
CCLayer
CCTouch
EAGLView 真正的 view Cocosd-x 已经把各个平台的 view 已经封装成 EAGLView. 在 EAGLView 中含有
1. - ( void )touchesBegan:( NSSet *)touches withEvent:( UIEvent *)event 2. - ( void )touchesMoved:( NSSet *)touches withEvent:( UIEvent *)event 3. - ( void )touchesEnded:( NSSet *)touches withEvent:( UIEvent *)event 4. - ( void )touchesCancelled:( NSSet *)touches withEvent:( UIEvent *)event
上诉四个方法能直接监听反馈用户的点击事件。同时能获取点击的坐标,以及有几个手指点击移动,再分别通过调用CCEGLViewProtocol的以下四个方法
1. virtual void handleTouchesBegin( int num, int ids[], float xs[], float ys[]);
2. virtual void handleTouchesMove( int num, int ids[], float xs[], float ys[]);
3 . virtual void handleTouchesEnd( int num, int ids[], float xs[], float ys[]);
4. virtual void handleTouchesCancel( int num, int ids[], float xs[], float ys[]);
将touches***方法中的信息传递到handleTouches***方法中.(其中通过 cocos2d :: CCEGLView :: sharedOpenGLView ()-> handleTouches*** (i, ids, xs, ys)来调用以上四个方法, sharedOpenGLView返回的是CCEGLView,由于CCEGLView是 CCEGLViewProtocol的子类,不过 handleTouches***这些方法的主要逻辑处理还是在 CCEGLViewProtocol处理的)。CCEGLViewProtocol类中有个 EGLTouchDelegate * m_pDelegate属性,在 handleTouches*** 方法中主要是把触摸点point放到 CCTouch中,再把其放入CCSet中。通过m_pDelegate -> touches*** (&set, NULL )方法将CCSet信息传递给 CCTouchDispatcher。关于CCTouchDispatcher这个类,她可是出生于名门世家-EGLTouchDelegate,EGLTouchDelegate有四个我们熟悉的方法也就是:
1. virtual void touchesBegan( CCSet * touches, CCEvent * pEvent) = 0 ;
2. virtual void touchesMoved( CCSet * touches, CCEvent * pEvent) = 0 ;
3. virtual void touchesEnded( CCSet * touches, CCEvent * pEvent) = 0 ;
4. virtual void touchesCancelled( CCSet * touches, CCEvent * pEvent) = 0 ;
CCEvent继承于CCObject,关于CCTouch他也是继承于CCObject,她能获取
1.CCPoint getLocation() const ;
2. CCPoint getPreviousLocation() const ;
3. CCPoint getStartLocation() const ;
4. CCPoint getDelta() const ;
5. CCPoint getLocationInView() const ;
6. CCPoint getPreviousLocationInView() const ;
7. CCPoint getStartLocationInView() const ;
上诉四个方法都是虚函数,真正的实现方法都在 CCTouchDispatcher中,但是在CCTouchDispatcher中的上诉四个方法其实也没干了什么大不了的事情,他们都做了相同的事情就是统一回调了CCTouchDispatcher中的 void CCTouchDispatcher ::touches( CCSet *pTouches, CCEvent *pEvent, unsigned int uIndex)方法,根据uIndex来区分是Began呢还是Moved等相关事件,所以上面讲了一堆,其实真正干事情的就只有 CCTouchDispatcher中的 touches方法,通过这个方法把触摸事件分发 出去,那怎么分发事件的呢?说道这,咱还是得回顾下其他知识。
先聊聊 CCTouchDelegate吧,这位老祖宗还真是祖宗。它有一堆的虚函数
/*******CCTargetedTouchDelegate 单点触摸*****/
1. virtual bool ccTouchBegan( CCTouch *pTouch, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouch); CC_UNUSED_PARAM (pEvent); return false ;};
2. virtual void ccTouchMoved( CCTouch *pTouch, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouch); CC_UNUSED_PARAM (pEvent);}
3. virtual void ccTouchEnded( CCTouch *pTouch, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouch); CC_UNUSED_PARAM (pEvent);} 4. virtual void ccTouchCancelled( CCTouch *pTouch, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouch); CC_UNUSED_PARAM (pEvent);}
/**********CCStandardTouchDelegate****多点触摸***********/
5. virtual void ccTouchesBegan( CCSet *pTouches, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouches); CC_UNUSED_PARAM (pEvent);} 6. virtual void ccTouchesMoved( CCSet *pTouches, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouches); CC_UNUSED_PARAM (pEvent);} 7. virtual void ccTouchesEnded( CCSet *pTouches, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouches); CC_UNUSED_PARAM (pEvent);} 8. virtual void ccTouchesCancelled( CCSet *pTouches, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouches); CC_UNUSED_PARAM (pEvent);}
上诉CCTargetedTouchDelegate以及CCStandardTouchDelegate都是CCTouchDelegate的子类,分别对应于单点触摸以及多点触摸。当然CCTouchDelegate的子类还有CCLayer。CCLayer含有他爸的全部方法,也就是单点触摸,多点触摸的方法她都有了。当然不能同时响应单点触摸以及多点触摸,其实多点触摸也就包含了单点触摸。CCLayer是通过ccTouchesMode这个结构来区分单点触摸以及多点触摸的-kCCTouchesAllAtOnce/kCCTouchesOneByOne.
讲了半天的CCTouchDelegate以及子类,那它怎么跟CCTouchDispatcher勾搭上啊,其实很简单,就只需要到CCTouchDispatcher注册一下。接下来重点将下 CCLayer是怎么注册的。CCLayer藏的很深,她仅仅就是让我们通过CCLayer ::setTouchEnabled( bool enabled)这个方法设置下是否能触摸,她就去乖乖的到CCTouchDispatcher注册去了。
下面具体看看setTouchEnabled做了啥事情吧,他去找了 CCLayer中的 registerWithTouchDispatcher()这个方法,在这个方法中,他会去到 CCDirector中找到CCTouchDispatcher(CCTouchDispatcher * pDispatcher = CCDirector :: sharedDirector ()-> getTouchDispatcher () ),其实CCTouchDispatcher在CCDirector的初始化中,他就生出来了。找到CCTouchDispatcher后也就方便了,通过 ccTouchesMode这个值判断是去注册单点呢,还是多点呢,CCLayer中ccTouchesMode默认值是kCCTouchesAllAtOnce。具体方法:pDispatcher-> addStandardDelegate ( this , 0 );//标准多点触摸。pDispatcher-> addTargetedDelegate ( this , m_nTouchPriority , true );//正统的单点触摸,注意这个true,这玩意就是个火药桶,如果他是true的时候,你一玩完,就偷偷的把 CCSet中的CCTouch给释放了,具体要看证据还是得在 CCTouchDispatcher中的touches才能看到,当然他仅仅只针对单点触摸,谁叫你单点啊。
好了现在也注册到CCTouchDispatcher了,也是属于有身份的合法公民了,跟着政府就好。那现在我们就看这个政府CCTouchDispatcher是怎么管理这个触摸小国家的吧。CCTouchDispatcher管理这个国家也不是亲力亲为的,她也请了外援 CCTouchHandler,这个Handler还拖家带口的,有两个亲儿子 CCStandardTouchHandler以及CCTargetedTouchHandler。
CCTouchHandler主要干的啥事情呢?保存CCTouchDelegate以及 priority这两个东东。 CCTouchDelegate就不需要怎么说了,他到 CCTouchDispatcher一报到,CCTouchDispatcher二话不说,把 CCTouchDelegate 以及 CCTouchDelegate的 priority直接扔给 CCTouchHandler,给打包下。当然CCTouchHandler也不是蛮干,先看看CCTouchDelegate你是 CCTargetedTouchDelegate还是CCStandardTouchDelegate呀, CCTouchHandler验明了CCTouchDelegate的身份之后自己也不直接上去,而是叫自己的儿子 CCStandardTouchHandler以及CCTargetedTouchHandler两个活宝上去打包的。打包方法:
1. static CCTouchHandler * handlerWithDelegate( CCTouchDelegate *pDelegate, int nPriority);//在该方法中会调用initWithDelegate
2. virtual bool initWithDelegate( CCTouchDelegate *pDelegate, int nPriority);
对了关于上面两个方法对于CCStandardTouchHandler以及CCTargetedTouchHandler都有不同的个性化,特别是CCTargetedTouchHandler,谁叫他打包的是 CCTargetedTouchDelegate呀, CCTargetedTouchDelegate这玩意有个bSwallowsTouches,是否吞了该触摸。也就是在上文讲到的true,在 addTargetedDelegate中如果将 bSwallowsTouches设为true,则当你触发完事件后,她就把你从触发的点上删除。所以此处CCTargetedTouchHandler针对CCTargetedTouchDelegate的特殊需求,也得满足不是,我就把你的bSwallowsTouches一并打包和 CCTouchDelegate以及 nPriority。 CCTouchHandler通过两个乖儿子,把CCTouchDelegate相关属性一并打包,就去向 CCTouchDispatcher总理报到了。这到哪报到呢,就是上文说的 void CCTouchDispatcher ::addStandardDelegate( CCTouchDelegate *pDelegate, int nPriority)以及 void CCTouchDispatcher ::addTargetedDelegate( CCTouchDelegate *pDelegate, int nPriority, bool bSwallowsTouches)这两个方法啊。在这两个方法中都能将打包好的 CCTouchHandler,通过f orceAddHandler 这个方法,把她分别提交给 m_pStandardHandlers以及m_pTargetedHandlers两个CCArray *大官人那,哪天CCTouchDispatcher想找哪个 CCTouchHandler的时候,直接找两个大官人就好。好了上面说了一堆终于把 CCTouchDelegate跟CCTouchDispatcher不得不说的事情说完了。
终于得做点事情了,前面也谈到了当有触摸事件来的时候,不管是 Began还是Moved啥的,一并都去 void touches( CCSet *pTouches, CCEvent *pEvent, unsigned int uIndex);这个办事处。这地方也就相当于总理大衙门-中南海,不管是触摸的消息 CCSet,还是CCTouchHandler都得在这交代的一清二百。上文所说的m_pStandardHandlers以及m_pTargetedHandlers通过遍历找到CCTouchHandler,然后将CCTouchHandler总理处理的结果传递到下面各个小罗罗上。
1. pHandler-> getDelegate ()-> ccTouchBegan (pTouch, pEvent);
2.pHandler-> getDelegate ()-> ccTouchesBegan (pMutableTouches, pEvent);
pHandler-> getDelegate ()也就是被打包封装的CCTouchDispatcher,现在就是被解绑了而已。
好了,说到这关于细说touch事情也差不多结束了。。。
EAGLView 真正的 view Cocosd-x 已经把各个平台的 view 已经封装成 EAGLView. 在 EAGLView 中含有
1. - ( void )touchesBegan:( NSSet *)touches withEvent:( UIEvent *)event 2. - ( void )touchesMoved:( NSSet *)touches withEvent:( UIEvent *)event 3. - ( void )touchesEnded:( NSSet *)touches withEvent:( UIEvent *)event 4. - ( void )touchesCancelled:( NSSet *)touches withEvent:( UIEvent *)event
上诉四个方法能直接监听反馈用户的点击事件。同时能获取点击的坐标,以及有几个手指点击移动,再分别通过调用CCEGLViewProtocol的以下四个方法
1. virtual void handleTouchesBegin( int num, int ids[], float xs[], float ys[]);
2. virtual void handleTouchesMove( int num, int ids[], float xs[], float ys[]);
3 . virtual void handleTouchesEnd( int num, int ids[], float xs[], float ys[]);
4. virtual void handleTouchesCancel( int num, int ids[], float xs[], float ys[]);
将touches***方法中的信息传递到handleTouches***方法中.(其中通过 cocos2d :: CCEGLView :: sharedOpenGLView ()-> handleTouches*** (i, ids, xs, ys)来调用以上四个方法, sharedOpenGLView返回的是CCEGLView,由于CCEGLView是 CCEGLViewProtocol的子类,不过 handleTouches***这些方法的主要逻辑处理还是在 CCEGLViewProtocol处理的)。CCEGLViewProtocol类中有个 EGLTouchDelegate * m_pDelegate属性,在 handleTouches*** 方法中主要是把触摸点point放到 CCTouch中,再把其放入CCSet中。通过m_pDelegate -> touches*** (&set, NULL )方法将CCSet信息传递给 CCTouchDispatcher。关于CCTouchDispatcher这个类,她可是出生于名门世家-EGLTouchDelegate,EGLTouchDelegate有四个我们熟悉的方法也就是:
1. virtual void touchesBegan( CCSet * touches, CCEvent * pEvent) = 0 ;
2. virtual void touchesMoved( CCSet * touches, CCEvent * pEvent) = 0 ;
3. virtual void touchesEnded( CCSet * touches, CCEvent * pEvent) = 0 ;
4. virtual void touchesCancelled( CCSet * touches, CCEvent * pEvent) = 0 ;
CCEvent继承于CCObject,关于CCTouch他也是继承于CCObject,她能获取
1.CCPoint getLocation() const ;
2. CCPoint getPreviousLocation() const ;
3. CCPoint getStartLocation() const ;
4. CCPoint getDelta() const ;
5. CCPoint getLocationInView() const ;
6. CCPoint getPreviousLocationInView() const ;
7. CCPoint getStartLocationInView() const ;
上诉四个方法都是虚函数,真正的实现方法都在 CCTouchDispatcher中,但是在CCTouchDispatcher中的上诉四个方法其实也没干了什么大不了的事情,他们都做了相同的事情就是统一回调了CCTouchDispatcher中的 void CCTouchDispatcher ::touches( CCSet *pTouches, CCEvent *pEvent, unsigned int uIndex)方法,根据uIndex来区分是Began呢还是Moved等相关事件,所以上面讲了一堆,其实真正干事情的就只有 CCTouchDispatcher中的 touches方法,通过这个方法把触摸事件分发 出去,那怎么分发事件的呢?说道这,咱还是得回顾下其他知识。
先聊聊 CCTouchDelegate吧,这位老祖宗还真是祖宗。它有一堆的虚函数
/*******CCTargetedTouchDelegate 单点触摸*****/
1. virtual bool ccTouchBegan( CCTouch *pTouch, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouch); CC_UNUSED_PARAM (pEvent); return false ;};
2. virtual void ccTouchMoved( CCTouch *pTouch, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouch); CC_UNUSED_PARAM (pEvent);}
3. virtual void ccTouchEnded( CCTouch *pTouch, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouch); CC_UNUSED_PARAM (pEvent);} 4. virtual void ccTouchCancelled( CCTouch *pTouch, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouch); CC_UNUSED_PARAM (pEvent);}
/**********CCStandardTouchDelegate****多点触摸***********/
5. virtual void ccTouchesBegan( CCSet *pTouches, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouches); CC_UNUSED_PARAM (pEvent);} 6. virtual void ccTouchesMoved( CCSet *pTouches, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouches); CC_UNUSED_PARAM (pEvent);} 7. virtual void ccTouchesEnded( CCSet *pTouches, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouches); CC_UNUSED_PARAM (pEvent);} 8. virtual void ccTouchesCancelled( CCSet *pTouches, CCEvent *pEvent) { CC_UNUSED_PARAM (pTouches); CC_UNUSED_PARAM (pEvent);}
上诉CCTargetedTouchDelegate以及CCStandardTouchDelegate都是CCTouchDelegate的子类,分别对应于单点触摸以及多点触摸。当然CCTouchDelegate的子类还有CCLayer。CCLayer含有他爸的全部方法,也就是单点触摸,多点触摸的方法她都有了。当然不能同时响应单点触摸以及多点触摸,其实多点触摸也就包含了单点触摸。CCLayer是通过ccTouchesMode这个结构来区分单点触摸以及多点触摸的-kCCTouchesAllAtOnce/kCCTouchesOneByOne.
讲了半天的CCTouchDelegate以及子类,那它怎么跟CCTouchDispatcher勾搭上啊,其实很简单,就只需要到CCTouchDispatcher注册一下。接下来重点将下 CCLayer是怎么注册的。CCLayer藏的很深,她仅仅就是让我们通过CCLayer ::setTouchEnabled( bool enabled)这个方法设置下是否能触摸,她就去乖乖的到CCTouchDispatcher注册去了。
下面具体看看setTouchEnabled做了啥事情吧,他去找了 CCLayer中的 registerWithTouchDispatcher()这个方法,在这个方法中,他会去到 CCDirector中找到CCTouchDispatcher(CCTouchDispatcher * pDispatcher = CCDirector :: sharedDirector ()-> getTouchDispatcher () ),其实CCTouchDispatcher在CCDirector的初始化中,他就生出来了。找到CCTouchDispatcher后也就方便了,通过 ccTouchesMode这个值判断是去注册单点呢,还是多点呢,CCLayer中ccTouchesMode默认值是kCCTouchesAllAtOnce。具体方法:pDispatcher-> addStandardDelegate ( this , 0 );//标准多点触摸。pDispatcher-> addTargetedDelegate ( this , m_nTouchPriority , true );//正统的单点触摸,注意这个true,这玩意就是个火药桶,如果他是true的时候,你一玩完,就偷偷的把 CCSet中的CCTouch给释放了,具体要看证据还是得在 CCTouchDispatcher中的touches才能看到,当然他仅仅只针对单点触摸,谁叫你单点啊。
好了现在也注册到CCTouchDispatcher了,也是属于有身份的合法公民了,跟着政府就好。那现在我们就看这个政府CCTouchDispatcher是怎么管理这个触摸小国家的吧。CCTouchDispatcher管理这个国家也不是亲力亲为的,她也请了外援 CCTouchHandler,这个Handler还拖家带口的,有两个亲儿子 CCStandardTouchHandler以及CCTargetedTouchHandler。
CCTouchHandler主要干的啥事情呢?保存CCTouchDelegate以及 priority这两个东东。 CCTouchDelegate就不需要怎么说了,他到 CCTouchDispatcher一报到,CCTouchDispatcher二话不说,把 CCTouchDelegate 以及 CCTouchDelegate的 priority直接扔给 CCTouchHandler,给打包下。当然CCTouchHandler也不是蛮干,先看看CCTouchDelegate你是 CCTargetedTouchDelegate还是CCStandardTouchDelegate呀, CCTouchHandler验明了CCTouchDelegate的身份之后自己也不直接上去,而是叫自己的儿子 CCStandardTouchHandler以及CCTargetedTouchHandler两个活宝上去打包的。打包方法:
1. static CCTouchHandler * handlerWithDelegate( CCTouchDelegate *pDelegate, int nPriority);//在该方法中会调用initWithDelegate
2. virtual bool initWithDelegate( CCTouchDelegate *pDelegate, int nPriority);
对了关于上面两个方法对于CCStandardTouchHandler以及CCTargetedTouchHandler都有不同的个性化,特别是CCTargetedTouchHandler,谁叫他打包的是 CCTargetedTouchDelegate呀, CCTargetedTouchDelegate这玩意有个bSwallowsTouches,是否吞了该触摸。也就是在上文讲到的true,在 addTargetedDelegate中如果将 bSwallowsTouches设为true,则当你触发完事件后,她就把你从触发的点上删除。所以此处CCTargetedTouchHandler针对CCTargetedTouchDelegate的特殊需求,也得满足不是,我就把你的bSwallowsTouches一并打包和 CCTouchDelegate以及 nPriority。 CCTouchHandler通过两个乖儿子,把CCTouchDelegate相关属性一并打包,就去向 CCTouchDispatcher总理报到了。这到哪报到呢,就是上文说的 void CCTouchDispatcher ::addStandardDelegate( CCTouchDelegate *pDelegate, int nPriority)以及 void CCTouchDispatcher ::addTargetedDelegate( CCTouchDelegate *pDelegate, int nPriority, bool bSwallowsTouches)这两个方法啊。在这两个方法中都能将打包好的 CCTouchHandler,通过f orceAddHandler 这个方法,把她分别提交给 m_pStandardHandlers以及m_pTargetedHandlers两个CCArray *大官人那,哪天CCTouchDispatcher想找哪个 CCTouchHandler的时候,直接找两个大官人就好。好了上面说了一堆终于把 CCTouchDelegate跟CCTouchDispatcher不得不说的事情说完了。
终于得做点事情了,前面也谈到了当有触摸事件来的时候,不管是 Began还是Moved啥的,一并都去 void touches( CCSet *pTouches, CCEvent *pEvent, unsigned int uIndex);这个办事处。这地方也就相当于总理大衙门-中南海,不管是触摸的消息 CCSet,还是CCTouchHandler都得在这交代的一清二百。上文所说的m_pStandardHandlers以及m_pTargetedHandlers通过遍历找到CCTouchHandler,然后将CCTouchHandler总理处理的结果传递到下面各个小罗罗上。
1. pHandler-> getDelegate ()-> ccTouchBegan (pTouch, pEvent);
2.pHandler-> getDelegate ()-> ccTouchesBegan (pMutableTouches, pEvent);
pHandler-> getDelegate ()也就是被打包封装的CCTouchDispatcher,现在就是被解绑了而已。
好了,说到这关于细说touch事情也差不多结束了。。。