cocos2d-x 源码剖析(11)
2014-03-10 14:26
435 查看
好久没用动笔写博客了,今天是1024节,还是要表示下。而且今天检查邮箱发现了5个垃圾评论,觉得很高兴,也要来篇文章庆祝下。哈哈。
时间隔得太久,我都不记得我讲到那里来了。原来是打算将几个特殊点的Action为大家结尾,最后一看源码,发现有点杂乱,待我整理好之后再写。今天来讲一讲CCScheduler。之前讲过,在ActionManager创建出来之后立马就加入到CCScheduler中去了,然后用ActionManager来控制不同Action的Update。也就是说CCScheduler是Action能工作的保障。我再贴这段代码回顾下:
而在mainLoop中的drawScene中也只有一个除绘制以外的逻辑,那就是update。
所有的根源都是那个m_pScheduler的update。可见CCScheduler的重要性。CCScheduler的构造函数只是简单的初始化了几个指针变量,没做任何的init逻辑处理。而且它不是单间,虽说cocos2d-x只支持一个scheduler update。需要了解CCScheduler还有一个伴生的概念叫做CCTimer,我们可以叫做定时器。CCScheduler内建了对update函数的支持,如果你要Scheduler自定义的函数就要借助CCTimer了,它就相当于一个适配器。
以上面那个scheduleUpdateForTarget为例,我们看起代码:
前面的检测保障其不能重复添加,但是允许在一帧之间先删除再添加。我们可以发现这部分代码和ActionManager是很像的, 这种标记删除的手法在游戏开发中很常见,如果你要统一管理自己的对象,记得也要采用这种方法,可以避免掉很多问题。与ActionManager不同的是,他内部采用了三个update容器来管理。我们看到
可见,Action的update的优先级是最高的。从注释上我们可以看出,默认的update的优先级是0,而且没有特殊情况下优先级大于0的容器中是没有元素的。这种设计是必要的,因为有些逻辑比较分散,最后又要统一处理。添加到大于0的优先级中就可以了。
上面可以看到真正添加到update容器中的是priorityIn这个函数,添加到容器的步骤要注意几点,新建一个容器元素,排好优先级,而且有个特殊的地方是它用了一个Hash表来快速的update这个列表中的函数。所以还要添加到Hash表中去。上面就是CCScheduler update的大致流程。我们知道CCScheduler除了update之外,还可以指定自定义的函数,也就是下面这个函数做的:
这个函数的参数值简直是丧心病狂,好在CCNode再次封装了一次。这种手法与Action类似,我就不多做介绍了。观其代码:
这些操作简直与Action如出一辙,他为每个新加的Target分配了10个定时器的空间,而且允许重复进入(其作用是更新参数)。再看其update函数,可以说这个函数是cocos2d-x的逻辑主体,他首先处理3个update容器中的元素,再处理自定义的timer,最后删除标记为删除的管理对象。代码我就不贴了。其他一些管理逻辑和要注意的问题与ActionManager是类似的,就不再多啰嗦了。大家可以对比来加深印象。
时间隔得太久,我都不记得我讲到那里来了。原来是打算将几个特殊点的Action为大家结尾,最后一看源码,发现有点杂乱,待我整理好之后再写。今天来讲一讲CCScheduler。之前讲过,在ActionManager创建出来之后立马就加入到CCScheduler中去了,然后用ActionManager来控制不同Action的Update。也就是说CCScheduler是Action能工作的保障。我再贴这段代码回顾下:
// scheduler m_pScheduler = new CCScheduler(); // action manager m_pActionManager = new CCActionManager(); m_pScheduler->scheduleUpdateForTarget(m_pActionManager, kCCPrioritySystem, false);
而在mainLoop中的drawScene中也只有一个除绘制以外的逻辑,那就是update。
// Draw the Scene void CCDirector::drawScene(void) { // calculate "global" dt calculateDeltaTime(); //tick before glClear: issue #533 if(!m_bPaused) { m_pScheduler->update(m_fDeltaTime); } glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); ...... }
所有的根源都是那个m_pScheduler的update。可见CCScheduler的重要性。CCScheduler的构造函数只是简单的初始化了几个指针变量,没做任何的init逻辑处理。而且它不是单间,虽说cocos2d-x只支持一个scheduler update。需要了解CCScheduler还有一个伴生的概念叫做CCTimer,我们可以叫做定时器。CCScheduler内建了对update函数的支持,如果你要Scheduler自定义的函数就要借助CCTimer了,它就相当于一个适配器。
以上面那个scheduleUpdateForTarget为例,我们看起代码:
void CCScheduler::scheduleUpdateForTarget(CCObject *pTarget, int nPriority, bool bPaused) { tHashUpdateEntry *pHashElement = NULL; HASH_FIND_INT(m_pHashForUpdates, &pTarget, pHashElement); if (pHashElement) { #if COCOS2D_DEBUG >= 1 CCAssert(pHashElement->entry->markedForDeletion,""); #endif // TODO: check if priority has changed! pHashElement->entry->markedForDeletion = false; return; } // most of the updates are going to be 0, that's way there // is an special list for updates with priority 0 if (nPriority == 0) { appendIn(&m_pUpdates0List, pTarget, bPaused); } else if (nPriority < 0) { priorityIn(&m_pUpdatesNegList, pTarget, nPriority, bPaused); } else { // priority > 0 priorityIn(&m_pUpdatesPosList, pTarget, nPriority, bPaused); } }
前面的检测保障其不能重复添加,但是允许在一帧之间先删除再添加。我们可以发现这部分代码和ActionManager是很像的, 这种标记删除的手法在游戏开发中很常见,如果你要统一管理自己的对象,记得也要采用这种方法,可以避免掉很多问题。与ActionManager不同的是,他内部采用了三个update容器来管理。我们看到
#define kCCPrioritySystem INT_MIN
可见,Action的update的优先级是最高的。从注释上我们可以看出,默认的update的优先级是0,而且没有特殊情况下优先级大于0的容器中是没有元素的。这种设计是必要的,因为有些逻辑比较分散,最后又要统一处理。添加到大于0的优先级中就可以了。
上面可以看到真正添加到update容器中的是priorityIn这个函数,添加到容器的步骤要注意几点,新建一个容器元素,排好优先级,而且有个特殊的地方是它用了一个Hash表来快速的update这个列表中的函数。所以还要添加到Hash表中去。上面就是CCScheduler update的大致流程。我们知道CCScheduler除了update之外,还可以指定自定义的函数,也就是下面这个函数做的:
scheduleSelector(SEL_SCHEDULE pfnSelector, CCObject *pTarget, float fInterval, unsigned int repeat, float delay, bool bPaused)
这个函数的参数值简直是丧心病狂,好在CCNode再次封装了一次。这种手法与Action类似,我就不多做介绍了。观其代码:
void CCScheduler::scheduleSelector(SEL_SCHEDULE pfnSelector,CCObject*pTarget,float fInterval,unsigned int repeat,float delay,bool bPaused) { CCAssert(pfnSelector,"Argument selector must be non-NULL"); CCAssert(pTarget,"Argument target must be non-NULL"); tHashTimerEntry* pElement=NULL; HASH_FIND_INT(m_pHashForTimers,&pTarget,pElement); if(!pElement) { pElement=(tHashTimerEntry*)calloc(sizeof(*pElement),1); pElement->target=pTarget; if(pTarget) { pTarget->retain(); } HASH_ADD_INT(m_pHashForTimers,target,pElement); // Is this the 1st element ? Then set the pause level to all the selectors of this target pElement->paused=bPaused; } else { CCAssert(pElement->paused==bPaused,""); } if(pElement->timers==NULL) { pElement->timers=ccArrayNew(10); } else { for(unsignedinti=0;i<pElement->timers->num;++i) { CCTimer*timer=(CCTimer*)pElement->timers->arr[i]; if(pfnSelector==timer->getSelector()) { CCLOG("CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: %.4f to %.4f",timer->getInterval(),fInterval); timer->setInterval(fInterval); return; } } ccArrayEnsureExtraCapacity(pElement->timers,1); } CCTimer* pTimer=newCCTimer(); pTimer->initWithTarget(pTarget,pfnSelector,fInterval,repeat,delay); ccArrayAppendObject(pElement->timers,pTimer); pTimer->release(); }
这些操作简直与Action如出一辙,他为每个新加的Target分配了10个定时器的空间,而且允许重复进入(其作用是更新参数)。再看其update函数,可以说这个函数是cocos2d-x的逻辑主体,他首先处理3个update容器中的元素,再处理自定义的timer,最后删除标记为删除的管理对象。代码我就不贴了。其他一些管理逻辑和要注意的问题与ActionManager是类似的,就不再多啰嗦了。大家可以对比来加深印象。
相关文章推荐
- cocos2d-x 源码剖析(15)
- cocos2d-x 源码剖析(16)
- cocos2d-x应用窗口相关源码剖析1
- cocos2d-x 源码剖析(17)
- cocos2d-x 源码剖析(18)
- cocos2d-x源码剖析之场景管理
- 【图像特征提取11】SIFT算法的原理与C源码剖析
- cocos2d-x应用窗口相关源码剖析2
- cocos2d-x 源码剖析(19)
- cocos2d-x源码剖析之精灵对象
- bombing:cocos2d-x应用窗口相关源码剖析3
- cocos2d-x 源码剖析(1)
- cocos2d-x 源码剖析(20)
- cocos2D-X源码分析之从cocos2D-X学习OpenGL(11)----摄像机
- cocos2d-x应用窗口相关源码剖析4
- cocos2d-x 源码剖析(2)
- cocos2d-x 源码剖析(21)
- cocos2d源码剖析
- 【cocos2d-x 源码剖析】启动窗口
- cocos2d-x源码剖析引子