CCScheduler调度器调度规则心得

来源:互联网 发布:mysql 事件是否开启 编辑:程序博客网 时间:2024/05/19 00:14

最近在学习cocos2d-x引擎,看完源码之后有一些心得体会,在此与大家分享交流:)

版本:2.0.4


scheduler的调度模式:scheduler的调度模式分为两种,一种是按照优先级来调度的,在cocos2d-x中优先级分为三部分,小于零,大于零,等于零,在更新节点的时候按照优先级由小至大的顺序来进行更新,更新的操作则为直接调用节点自身的update()函数。至于为什么分开成为三个链表其实我也不太清楚,如果有了解的朋友的话欢迎留下你的看法~ 下面我们来看一下三个调度队列的命名以及其中的元素组成,这里面引用了一个哈希表来进行存储,至于具体的哈希表实现等,可以参照这个博客的内容

http://blog.csdn.net/llaisi530/article/details/8893657


 struct _listEntry *m_pUpdatesNegList;        // list of priority < 0    struct _listEntry *m_pUpdates0List;            // list priority == 0    struct _listEntry *m_pUpdatesPosList;        // list priority > 0


typedef struct _listEntry{    struct    _listEntry    *prev, *next;    CCObject    *target;        // not retained (retained by hashUpdateEntry)    int                    priority; //优先级    bool                paused;//用于记录节点是否需要更新    bool                markedForDeletion; // selector will no longer be called and entry will be removed at end of the next tick 这个用处在后面会再讲    } tListEntry;

有的朋友可能会发现,在三个链表下面,还有另外一个链表,但这个列表准确来说并不用于调度,只用于快速查询(找出某个节点位于哪个调度队列)

struct _hashUpdateEntry *m_pHashForUpdates; // hash used to fetch quickly the list entries for pause,delete,etc

typedef struct _hashUpdateEntry{    tListEntry            **list;        // Which list does it belong to ?    tListEntry            *entry;        // entry in the list    CCObject    *target;        // hash key (retained)    UT_hash_handle        hh;} tHashUpdateEntry;

讲完第一种调度方式,接下来就是第二种调度方式按照自定义定时器来进行调度,在这种调度里面,不再是直接调用节点自身的update()函数而是设定一个或多个回调函数,下面就是保存定时器的链表声明,存储的结构体信息以及CCTIMER的内部成员。

struct _hashSelectorEntry *m_pHashForSelectors;

typedef struct _hashSelectorEntry{    ccArray                      *timers; //ccArray数组用于保存所有的自定义定时器,即一个节点能够拥有多个定时器    CCObject            *target;    // hash key (retained) //执行更新的目标节点    unsigned int                timerIndex;    CCTimer                        *currentTimer;    bool                        currentTimerSalvaged;    bool                        paused; //是否暂停该节点的更新动作    UT_hash_handle                hh;} tHashSelectorEntry;

CCTimer类的内部成员
public:    SEL_SCHEDULE m_pfnSelector; //自定义的回调函数    float m_fInterval;         //回调函数可以有自身的执行时间protected:    CCObject *m_pTarget;  //执行回调函数的目标节点    float m_fElapsed;     //等待时间    bool m_bRunForever;  //是否每次都更新,如果是的话就可以无视等待时间每帧更新    bool m_bUseDelay;    //是否有延时,有延时的话就会在第一次执行时延时执行    unsigned int m_nTimesExecuted; //记录执行更新的次数    unsigned int m_nRepeat; //0 = once, 1 is 2 x executed    float m_fDelay;      //延迟时间    int m_nScriptHandler;//这个本人也没太弄明白,如果有大神看到的话请指点,谢谢^^

看完这些的时候,再看回CCScheduler里面的update函数,便十分清晰明了了,可以看到,里面先从优先级调度开始执行,就是从negList开始,依次执行里面各个节点自身的update()函数。然后再到0List,再到posList(),之后再到自定义的定时器,在自定义的定时器里面,又遍历了每个目标节点中的timers数组,以遍历它的所有自定义定时器。而最后呢,则执行删除操作,也就是对链表中markForDeletion的节点进行清理。

这样一个流程下来,便结束了CCScheduler的调度了。

原创粉丝点击