最近在学习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的调度了。