问题1:触屏的目标对象被加到cocos2d-x框架的什么地方?
问题2:cocos2d-x框架是如何调用目标对象的回调函数?
问题3:CCTouchDispatcher类触屏分发器原理是什么?
1触屏事件基础知识 |
基本步骤,1)开启触屏功能2);重写registerWithTouchDispatcher方法;3)重写触屏协议函数 例子如下: |
// on "init" you need to initialize your instance bool HelloWorld::init() { // // 1. super init first if ( !CCLayer::init() ) { return false; }
//做一个鼠标跟随的效果 CCSprite *sprite = CCSprite::create("CloseNormal.png"); sprite->setPosition(ccp(200, 200)); this->addChild(sprite, 0, 100);
//开启层触屏支持 this->setTouchEnabled(true); }
void HelloWorld::registerWithTouchDispatcher(void) { CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true); }
public: virtual void registerWithTouchDispatcher(void);
bool HelloWorld::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) ; void HelloWorld::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) ; void HelloWorld::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) ; void HelloWorld::ccTouchCancelled(cocos2d::CCTouch *pTouch,cocos2d:: CCEvent *pEvent) ;
bool HelloWorld:: (CCTouch *pTouch, CCEvent *pEvent) { CCLOG("ddddddd"); //获取精灵 获取鼠标点击位置,移动精灵到此位置 CCSprite *sprite = (CCSprite *)this->getChildByTag(100); if (sprite == NULL) { return false; } //CCPoint point = pTouch->getLocationInView(); //CCPoint glpoint = CCDirector::sharedDirector()->convertToGL(point); CCPoint glpoint = pTouch->getLocation();
sprite->setPosition(glpoint); //CCMoveTo* moveto = CCMoveTo::create(3, point); //sprite->runAction(moveto); return true; }; |
问题1:重载的函数void HelloWorld::registerWithTouchDispatcher(void),何时被框架执行的?
结论:HelloWorld层被第一次载入场景是,会被执行onEnter函数。onEnter函数执行重载函数registerWithTouchDispatcher的调用。 |
问题2:问题1:触屏的目标对象及目标回到函数加到cocos2d-x框架的哪里了? 当然,也可以这么问:registerWithTouchDispatcher执行了哪些功能? 1、 CCTouchDispatcher类是cocos2d-x的触屏分发器,通过组合的方式由大管家CCDirector初始化;(参考CCDirector类的创建章节介绍。) 2、 CCTouchHandler类负责初始化把实现触屏协议类对象、优先级、触屏信息记录下来。 3、 初始化好的CCTouchHandler类对象,被CCTouchDispatcher类保存在成员变量CCArray* m_pHandlersToAdd中。以便cocos2d-x进行调用。 代码运作过程参考下图
|
|
|
问题2:cocos2d-x框架是如何回到目标对象的回调函数
结论: 1) CCEGLView:: WindowProc过程回调函数处理触屏消息,比如鼠标点击、滑屏。 2) 调用消息派发器类CCTouchDispatcher,进行消息处理。 3) 在CCTouchDispatcher类的touches函数中进行各种消息机制的处理及用户重载鞋业函数的调用。 |
问题3:CCTouchDispatcher类是如何处理消息派发的?也可以这么问:CCTouchDispatcher类触屏分发器原理是什么? 1) CCTouchDispatcher类能处理单点、多点触屏协议事件 2) CCTouchDispatcher类通过 void addStandardDelegate(CCTouchDelegate *pDelegate, int nPriority)和 void addTargetedDelegate(CCTouchDelegate *pDelegate, int nPriority, bool bSwallowsTouches)函数完成用触屏协议实现对象的注册。 3) CCTouchDispatcher类把注册信息存入到CCArray* m_pTargetedHandlers和CCArray* m_pStandardHandlers成员变量中。为保证不再循环时改变容器内容,CCTouchDispatcher类又引入了CCArray* m_pHandlersToAdd和 struct _ccCArray *m_pHandlersToRemove成员变量,用于暂时保存分发事件时目标对象的增删。 4) CCTouchDispatcher类的两个协议CCTargetedTouchDelegate /CCStandardTouchDelegate派发顺序 首先派发事件给CCTargetedTouchDelegate, 再派发事件给CCStandardTouchDelegate 5) CCTouchDispatcher类是触屏传递顺序描述如下: 1.CCLayer 只有一层的情况: virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); a.返回false,则ccTouchMoved(),ccTouchEnded()不会再接收到消息 b.返回true,则ccTouchMoved(),ccTouchEnded()可以接收到消息 2.CCLayer 有多层的情况: virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); a.返回false,则本层的ccTouchMoved(),ccTouchEnded()不会再接收到消息,但是本层之下的其它层会接收到消息 b.返回true,则本层的ccTouchMoved(),ccTouchEnded()可以接收到消息,但是本层之下的其它层不能再接收到消息 3.有自定义接收触摸消息的精灵的情况: virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); a.返回false,则此精灵的ccTouchMoved(),ccTouchEnded()不会再接收到消息,而此精灵所在的层会接收到触摸消息(如果精灵所在层没有设置接收触摸消息,则向下传递) b.返回true,则此精灵的ccTouchMoved(),ccTouchEnded()会继续接收消息,并消耗此消息(即不再向所在层和其他层传递) 感兴趣的读者可以再仔细阅读CCTouchDispatcher类相关源码,深入细腻的实验内容在bombing课堂。 |