首页 > 其他 > 详细

戏谈cocos2d-x 2.0.4 Touch

时间:2014-04-10 16:30:50      阅读:445      评论:0      收藏:0      [点我收藏+]
先把跟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,通过forceAddHandler这个方法,把她分别提交给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事情也差不多结束了。。。

戏谈cocos2d-x 2.0.4 Touch,布布扣,bubuko.com

戏谈cocos2d-x 2.0.4 Touch

原文:http://blog.csdn.net/xiedantibu/article/details/23351147

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!