Cocos2d-x之CCTouchDispatcher事件分发
2013-03-28 11:43
387 查看
使用过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__
相关文章推荐
- Cocos2d-x之CCTouchDispatcher事件分发
- cocos2d ccLayer响应触摸事件方法:CCStandardTouchDelegate 与 CCTargetedTouchDelegate
- cocos2d JS touch屏幕点击事件监听 cc.EventListener.TOUCH
- cocos2d ccLayer响应触摸事件方法:CCStandardTouchDelegate 与 CCTargetedTouchDelegate
- Quick-Cocos2d-x游戏开发触摸捕获事件 cc.NODE_TOUCH_CAPTURE_EVENT
- cocos2d JS touch屏幕点击事件监听 cc.EventListener.TOUCH
- [寒江孤叶丶的Cocos2d-x之旅_23]Cocos2d-x LUA实现事件分发器 lua EventDispatcher
- cocos2d ccLayer响应触摸事件方法:CCStandardTouchDelegate 与 CCTargetedTouchDelegate
- quick-cocos2d-x游戏开发【10】——触摸捕获事件 cc.NODE_TOUCH_CAPTURE_EVENT
- Cocos2d-x之Touch事件处理机制 提供两种触摸事件处理机制:CCStandardTouchDelegate和CCTargetedTouchDelegate。
- quick-cocos2d-x游戏开发【10】——触摸捕获事件 cc.NODE_TOUCH_CAPTURE_EVENT
- [Cocos2d-x 2.3]Touch操作事件是如何分发的
- Andriod 从源码的角度详解View,ViewGroup的Touch事件的分发机制
- Android:30分钟弄明白Touch事件分发机制
- Android--Touch 事件的分发和消费机制
- Andriod 从源码的角度详解View,ViewGroup的Touch事件的分发机制
- cocos2d-x中关于touch事件的响应
- Android的Touch事件分发机制简单探析
- Andriod 从源码的角度详解View,ViewGroup的Touch事件的分发机制
- android touch事件分发流程