Cocos2d-x之CCTouchDispatcher事件分发

 使用过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 coordinates
CCPoint CCTouch::getLocationInView() const

    //获取屏幕坐标
    return m_point; 
}
              
// returns the current previous location in screen coordinates
CCPoint CCTouch::getPreviousLocationInView() const

    //获取上一次的屏幕坐标
    return m_prevPoint; 
}
              
// returns the current touch location in OpenGL coordinates
CCPoint CCTouch::getLocation() const

    //获取在opengl坐标系中的坐标
    return CCDirector::sharedDirector()->convertToGL(m_point); 
}
              
// returns the previous touch location in OpenGL coordinates
CCPoint CCTouch::getPreviousLocation() const

    //获取上一次在opengl坐标系中的位置
    return CCDirector::sharedDirector()->convertToGL(m_prevPoint);  
}
              
// returns the delta position between the current location and the previous location in OpenGL coordinates
CCPoint 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__
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值