9秒分享 Cocos2d-X2.2版本框架源码分析第二讲

接着最开始的,我们继续来分析Cocos2d-x的框架源码 

接下来,我们来玩什么呢?  对了,定时器..我们现在开始..刚才多少来着,哦,对了,第四个了..我们开始


4cocos2d-x定时器机制


问题1:定时器回调函数,添加到cocos2d-x框架哪里去了。
问题2:定时器回调函数是如何被cocos2d-x回调用起来的
问题3:cocos2d-x框架式如何管理定时器的。

定时器的应用基础cocos2d-x 
Cocos2d-x提供两种定时器 
1)update定时器,每帧被调用,使用scheduleUpdate方法启用。
2)schedule定时器,可设置时间间隔来触发,使用schedule方法启用。
框架与应用界面接口如下:
void scheduleUpdate(void);
void unscheduleUpdate(void);
void schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay);
void schedule(SEL_SCHEDULE selector, float interval);
void scheduleOnce(SEL_SCHEDULE selector, float delay);
void schedule(SEL_SCHEDULE selector);
void unschedule(SEL_SCHEDULE selector);
void unscheduleAllSelectors(void);

问题1:定时器回调函数,添加到cocos2d-x框架哪里去了?
1)        CCNode类注入了调度器对象;
2)        通过schedule()函数,上层应用对象及对象的回调函数入口地址,被添加到调度器CCScheduler中。
3)        调度器为每一个定时器设置CCTimer对象,并保存定时器类目标、回调函数、触发周期,重复次数;在把对应信息保存到m_pHashForTimers链表中。以便后续调度。
代码如下:

9秒分享 Cocos2d-X2.2版本框架源码分析第二讲_第1张图片


9秒分享 Cocos2d-X2.2版本框架源码分析第二讲_第2张图片



问题2:定时器回调函数是如何被调用起来的
顺序如下:
1)AppDelegate对象run函数,按照帧频率调用 void CCDisplayLinkDirector::mainLoop(void)

   
9秒分享 Cocos2d-X2.2版本框架源码分析第二讲_第3张图片


2)mainLoop 函数调用,void CCDirector::drawScene(void)

9秒分享 Cocos2d-X2.2版本框架源码分析第二讲_第4张图片


4)        调度器的update函数发起如下调度

9秒分享 Cocos2d-X2.2版本框架源码分析第二讲_第5张图片


9秒分享 Cocos2d-X2.2版本框架源码分析第二讲_第6张图片


9秒分享 Cocos2d-X2.2版本框架源码分析第二讲_第7张图片

   
同时,如果在调度过程中,有删除定时器操作时,在调度完毕以后再删除。
删掉定时器,只做标记。 

9秒分享 Cocos2d-X2.2版本框架源码分析第二讲_第8张图片


结论1:普通定时器调用顺序:1、系统的事件驱动游戏主循环;2、游戏主循环调用CCScheduler的update方法。3、CCScheduler调用普通定时器对应的CCTimeer对象的update方法;4、CCTime类的updata方法调用定时器对应的回调函数。
结论2:updata定时器,调用顺序比较简单,直接在CCScheduler的update方法中调用。


5coco2d-x触屏实现机制

问题1:触屏的目标对象被加到cocos2d-x框架的什么地方?
问题2:cocos2d-x框架是如何调用目标对象的回调函数?
问题3:CCTouchDispatcher类触屏分发器原理是什么?

1触屏事件基础知识
基本步骤,1)开启触屏功能2);重写registerWithTouchDispatcher方法;3)重写触屏协议函数
例子如下:
  1. // on "init" you need to initialize your instance
  2. bool HelloWorld::init()
  3. {
  4.     //////////////////////////////
  5.     // 1. super init first
  6.     if ( !CCLayer::init() )
  7.     {
  8.         return false;
  9.     }

  10.         //做一个鼠标跟随的效果
  11.         CCSprite *sprite = CCSprite::create("CloseNormal.png");
  12.         sprite->setPosition(ccp(200, 200));
  13.         this->addChild(sprite, 0, 100);

  14.         //开启层触屏支持
  15.         this->setTouchEnabled(true);
  16. }

  17. void HelloWorld::registerWithTouchDispatcher(void)
  18. {
  19.         CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
  20. }

  21. public:
  22.         virtual void registerWithTouchDispatcher(void);

  23.         bool HelloWorld::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) ;
  24.         void HelloWorld::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) ;
  25.         void HelloWorld::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) ;
  26.         void HelloWorld::ccTouchCancelled(cocos2d::CCTouch *pTouch,cocos2d:: CCEvent *pEvent) ;
  27.                 
  28. bool HelloWorld::  (CCTouch *pTouch, CCEvent *pEvent) 

  29.         CCLOG("ddddddd");
  30.         //获取精灵 获取鼠标点击位置,移动精灵到此位置
  31.         CCSprite *sprite = (CCSprite *)this->getChildByTag(100);
  32.         if (sprite == NULL)
  33.         {
  34.                 return false;
  35.         }
  36.         //CCPoint point  = pTouch->getLocationInView();
  37.         //CCPoint glpoint = CCDirector::sharedDirector()->convertToGL(point);
  38.         CCPoint glpoint = pTouch->getLocation();

  39.         sprite->setPosition(glpoint);
  40.         //CCMoveTo* moveto = CCMoveTo::create(3, point);
  41.         //sprite->runAction(moveto);
  42.         return true;
  43. };
复制代码
问题1:重载的函数void HelloWorld::registerWithTouchDispatcher(void),何时被框架执行的?

9秒分享 Cocos2d-X2.2版本框架源码分析第二讲_第9张图片


结论: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进行调用。
代码运作过程参考下图

9秒分享 Cocos2d-X2.2版本框架源码分析第二讲_第10张图片


9秒分享 Cocos2d-X2.2版本框架源码分析第二讲_第11张图片


9秒分享 Cocos2d-X2.2版本框架源码分析第二讲_第12张图片


问题2:cocos2d-x框架是如何回到目标对象的回调函数

9秒分享 Cocos2d-X2.2版本框架源码分析第二讲_第13张图片


结论:
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类相关源码,深入细腻的实验内容在9秒课堂。

by:Net Fly

你可能感兴趣的:(9秒分享 Cocos2d-X2.2版本框架源码分析第二讲)