Cocos2d-x之CCTouchDispatcher事件分发

来源:互联网 发布:单片机与plc的区别知乎 编辑:程序博客网 时间:2024/06/06 00:15
 使用过CCLayer的都应该知道,CCLayer的众多父类中有CCTouchDelegate这么一个类,他使CCLayer能接收touch事件成为可能。cocos2d-x的touch事件是由CCTouchDispatcher这个touch分发器类来进行派发的,所有需要接收touch事件的对象都必须注册到CCTouchDispatcher中,而只有继承于CCTouchDelegate的对象才能被注册到touch分发器中。        先看看cocos2d-x的touch事件的触发流程,我们能看得见的游戏界面我且称之为视图(view),touch的产生正是从视图开始的,在程序的消息处理中心检测到touch事件时,将事件整理成CCTouch的集合并传递给注册在视图内的touch分发器CCTouchDispatcher,这个touch分发器是在导演类设置openglView的时候注册的://1、直接设置touch分发器void CCDirector::setTouchDispatcher(CCTouchDispatcher* pTouchDispatcher){    //设置touch分发器    if (m_pTouchDispatcher != pTouchDispatcher)    {        CC_SAFE_RETAIN(pTouchDispatcher);        CC_SAFE_RELEASE(m_pTouchDispatcher);        m_pTouchDispatcher = pTouchDispatcher;    }    }//2、导演类初始化的时候创建touch分发器bool CCDirector::init(void){    ......    //导演类初始化的时候生成touch分发器    m_pTouchDispatcher = new CCTouchDispatcher();    m_pTouchDispatcher->init();                    ... ...                     return true;}void CCDirector::setOpenGLView(CCEGLView *pobOpenGLView){    CCAssert(pobOpenGLView, "opengl view should not be null");                     if (m_pobOpenGLView != pobOpenGLView)    {        ......        //注册touch分发器到openglView中,接收view传递过来的touch事件                          m_pobOpenGLView->setTouchDelegate(m_pTouchDispatcher);        m_pTouchDispatcher->setDispatchEvents(true);    }}在查看touch分发器怎么处理touch事件之前,先了解传递的数据CCTouch,CCtouch的数据很简单,只有属性:int m_nId;CCPoint m_point;CCPoint m_prevPoint;CCTouch.cpp:// returns the current touch location in screen coordinatesCCPoint CCTouch::getLocationInView() const{     //获取屏幕坐标    return m_point; }              // returns the current previous location in screen coordinatesCCPoint CCTouch::getPreviousLocationInView() const{     //获取上一次的屏幕坐标    return m_prevPoint; }              // returns the current touch location in OpenGL coordinatesCCPoint CCTouch::getLocation() const{     //获取在opengl坐标系中的坐标    return CCDirector::sharedDirector()->convertToGL(m_point); }              // returns the previous touch location in OpenGL coordinatesCCPoint CCTouch::getPreviousLocation() const{     //获取上一次在opengl坐标系中的位置    return CCDirector::sharedDirector()->convertToGL(m_prevPoint);  }              // returns the delta position between the current location and the previous location in OpenGL coordinatesCCPoint CCTouch::getDelta() const{         //返回当前和上次位置在opengl坐标系中差值    return ccpSub(getLocation(), getPreviousLocation()); }CCTouch提供查询坐标点的接口。   所有能接收touch事件的对象都需要继承于CCTouchDelegate,这个类定义了接收touch事件的众多接口,CCTouchDelegateProtocol.h:class CC_DLL CCTouchDelegate{public:               CCTouchDelegate() {}               virtual ~CCTouchDelegate()    {    }               virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent); return false;};    // optional               virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent);}    virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent);}    virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent);}               // optional     virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);}     virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);}     virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);}     virtual void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);}           };                     //此类型的触控对象,可以通过ccTouchBegan的返回值决定此次touch是否有后续的反馈//返回值为false的时候,此次touch后续的moved、ended、cancelled都不再反馈给此触控对象//具备touch阻断功能的触控对象 class CC_DLL CCTargetedTouchDelegate : public CCTouchDelegate { public:     /** Return YES to claim the touch.      @since v0     */     virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) { CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent);return false;};                 // optional     virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent);}     virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent);}     virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent);} };            //此类型的触控对象不具有阻止后续反馈的功能,一次touch事件,触控对象将接收到所有的后续反馈 //典型的触控对象接收多点触控数据 class CC_DLL CCStandardTouchDelegate : public CCTouchDelegate { public:     // optional     virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);}     virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);}     virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);}    virtual void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);} };其中定义了两种触控对象,一种是接收单触控并具有阻挡策略,另一种是接收多点触控    touch分发器中,将触控对象转换为触控对象句柄CCTouchHandler之后,才进行存储和处理的,CCTouchHandler.h://触控对象的句柄,相当于一个容器,保存了触控对象以及触控对象的触控优先级class CC_DLL  CCTouchHandler : public CCObject{public:    virtual ~CCTouchHandler(void);             /** delegate */    //触控对象的获取与设置    CCTouchDelegate* getDelegate();    void setDelegate(CCTouchDelegate *pDelegate);             /** priority */    //触控优先级的获取与设置    int getPriority(void);    void setPriority(int nPriority);             /** enabled selectors */    //好像没有什么用处    int getEnabledSelectors(void);    void setEnalbedSelectors(int nValue);             /** initializes a TouchHandler with a delegate and a priority */    //初始化触控句柄,参数为触控对象和触控优先级    virtual bool initWithDelegate(CCTouchDelegate *pDelegate, int nPriority);         public:    /** allocates a TouchHandler with a delegate and a priority */    //创建一个触控句柄,参数为触控对象和触控优先级    static CCTouchHandler* handlerWithDelegate(CCTouchDelegate *pDelegate, int nPriority);         protected:    CCTouchDelegate *m_pDelegate;    int m_nPriority;    int m_nEnabledSelectors;};         /** CCStandardTouchHandler It forwards each event to the delegate. */         //典型触控句柄class CC_DLL  CCStandardTouchHandler : public CCTouchHandler{public:    /** initializes a TouchHandler with a delegate and a priority */    virtual bool initWithDelegate(CCTouchDelegate *pDelegate, int nPriority);         public:    /** allocates a TouchHandler with a delegate and a priority */    static CCStandardTouchHandler* handlerWithDelegate(CCTouchDelegate *pDelegate, int nPriority);};         /** CCTargetedTouchHandler Object than contains the claimed touches and if it swallows touches. Used internally by TouchDispatcher *///具有touch阻断功能的触控句柄class CC_DLL  CCTargetedTouchHandler : public CCTouchHandler{public:    ~CCTargetedTouchHandler(void);             /** whether or not the touches are swallowed */    //是否阻止touch事件冒泡,继续分发给接下来的其他对象    bool isSwallowsTouches(void);    void setSwallowsTouches(bool bSwallowsTouches);             /** MutableSet that contains the claimed touches */    //获取集合、此集合中保存了touch对象,针对这些touch对象,触控对象将接收他们的后续反馈    CCSet* getClaimedTouches(void);             /** initializes a TargetedTouchHandler with a delegate, a priority and whether or not it swallows touches or not */    bool initWithDelegate(CCTouchDelegate *pDelegate, int nPriority, bool bSwallow);         public:    /** allocates a TargetedTouchHandler with a delegate, a priority and whether or not it swallows touches or not */    static CCTargetedTouchHandler* handlerWithDelegate(CCTouchDelegate *pDelegate, int nPriority, bool bSwallow);         protected:    bool m_bSwallowsTouches;    CCSet *m_pClaimedTouches;};触控对象句柄也有两种,单点触控对象句柄具有一个集合属性 CCSet *m_pClaimedTouches,用来存储得到认可的touch事件,使该事件的后续反馈将对这个触控对象有效。        接下来看看touch分发器的具体实现,看看他是怎么样分发touch消息的,主要分发逻辑在touches方法中。CCTouchDispatcher.h:#ifndef __TOUCH_DISPATCHER_CCTOUCH_DISPATCHER_H__#define __TOUCH_DISPATCHER_CCTOUCH_DISPATCHER_H__     #include "CCTouchDelegateProtocol.h"#include "cocoa/CCObject.h"#include "cocoa/CCArray.h"     NS_CC_BEGIN     /** * @addtogroup input * @{ */     typedef enum{    ccTouchSelectorBeganBit = 1 << 0,    ccTouchSelectorMovedBit = 1 << 1,    ccTouchSelectorEndedBit = 1 << 2,    ccTouchSelectorCancelledBit = 1 << 3,    ccTouchSelectorAllBits = ( ccTouchSelectorBeganBit | ccTouchSelectorMovedBit | ccTouchSelectorEndedBit | ccTouchSelectorCancelledBit),} ccTouchSelectorFlag;          enum {    CCTOUCHBEGAN,    CCTOUCHMOVED,    CCTOUCHENDED,    CCTOUCHCANCELLED,             ccTouchMax,};     class CCSet;class CCEvent;     struct ccTouchHandlerHelperData {    // we only use the type//    void (StandardTouchDelegate::*touchesSel)(CCSet*, CCEvent*);//    void (TargetedTouchDelegate::*touchSel)(NSTouch*, CCEvent*);    int  m_type;};          class CC_DLL EGLTouchDelegate{public:    virtual void touchesBegan(CCSet* touches, CCEvent* pEvent) = 0;    virtual void touchesMoved(CCSet* touches, CCEvent* pEvent) = 0;    virtual void touchesEnded(CCSet* touches, CCEvent* pEvent) = 0;    virtual void touchesCancelled(CCSet* touches, CCEvent* pEvent) = 0;         virtual ~EGLTouchDelegate() {}};     class CCTouchHandler;struct _ccCArray;    class CC_DLL CCTouchDispatcher : public CCObject, public EGLTouchDelegate{public:    ~CCTouchDispatcher();    bool init(void);    CCTouchDispatcher()         : m_pTargetedHandlers(NULL)        , m_pStandardHandlers(NULL)        , m_pHandlersToAdd(NULL)        , m_pHandlersToRemove(NULL)                 {}     public:    /** Whether or not the events are going to be dispatched. Default: true */    //是否分发touch事件    bool isDispatchEvents(void);    void setDispatchEvents(bool bDispatchEvents);         /** Adds a standard touch delegate to the dispatcher's list.     See StandardTouchDelegate description.     IMPORTANT: The delegate will be retained.     */    //添加接收touch事件的典型触控对象    void addStandardDelegate(CCTouchDelegate *pDelegate, int nPriority);         /** Adds a targeted touch delegate to the dispatcher's list.     See TargetedTouchDelegate description.     IMPORTANT: The delegate will be retained.     */    //添加接受touch事件的,具有阻断功能的触控对象    void addTargetedDelegate(CCTouchDelegate *pDelegate, int nPriority, bool bSwallowsTouches);         /** Removes a touch delegate.     The delegate will be released     */    //移除触控对象    void removeDelegate(CCTouchDelegate *pDelegate);         /** Removes all touch delegates, releasing all the delegates */    void removeAllDelegates(void);         /** Changes the priority of a previously added delegate. The lower the number,    the higher the priority */    void setPriority(int nPriority, CCTouchDelegate *pDelegate);         void touches(CCSet *pTouches, CCEvent *pEvent, unsigned int uIndex);         virtual void touchesBegan(CCSet* touches, CCEvent* pEvent);    virtual void touchesMoved(CCSet* touches, CCEvent* pEvent);    virtual void touchesEnded(CCSet* touches, CCEvent* pEvent);    virtual void touchesCancelled(CCSet* touches, CCEvent* pEvent);     public:    CCTouchHandler* findHandler(CCTouchDelegate *pDelegate);protected:    void forceRemoveDelegate(CCTouchDelegate *pDelegate);    void forceAddHandler(CCTouchHandler *pHandler, CCArray* pArray);    void forceRemoveAllDelegates(void);    void rearrangeHandlers(CCArray* pArray);    CCTouchHandler* findHandler(CCArray* pArray, CCTouchDelegate *pDelegate);     protected:         //两个队列,用来保存注册进来的单触控对象和多点触控对象     CCArray* m_pTargetedHandlers;     CCArray* m_pStandardHandlers;          //触控对象队列是否被锁定不可增删改    bool m_bLocked;         //是否有触控对象在等待添加到触控队列中    bool m_bToAdd;         //是否有触控对象在等待从触控队列中移除掉    bool m_bToRemove;         //保存等待加入触控队列的触控对象     CCArray* m_pHandlersToAdd;          //保存等待从触控队列中删除的触控对象    struct _ccCArray *m_pHandlersToRemove;         //是否将推出    bool m_bToQuit;         //是否分发touch事件    bool m_bDispatchEvents;         // 4, 1 for each type of event    struct ccTouchHandlerHelperData m_sHandlerHelperData[ccTouchMax];};     // end of input group/// @}     NS_CC_END     #endif // __TOUCH_DISPATCHER_CCTOUCH_DISPATCHER_H__