Cocos2dx 2. x timer analysis (1)
1. Create a global timer. In the bool CCDirector: init (void) function, call
// scheduler m_pScheduler = new CCScheduler();
2. the update method of ccschedctor will be called before each frame is rendered // Draw the Scenevoid CCDirector: drawScene (void) {// calculate "global" dt calculateDeltaTime (); // tick before glClear: issue #533 if (! M_bPaused) // call the timer's update method {m_pScheduler-> update (m_fDeltaTime );}}
3. There are several important member variables in ccsched, // The timer struct _ listEntry * m_pUpdatesNegList to be called for each frame; // list of priority <0 // stores the Update of priority <0, and the highest priority is struct _ listEntry * m_pUpdates0List; // list priority = 0 // Update struct _ listEntry * m_pUpdatesPosList where priority = 0 is stored; // list priority> 0 // Update where priority> 0 is stored, lowest priority // convenient and quick search for struct _ hashUpdateEntry * m_pHashForUpdates; // hash used to fetch quickly the list entries for pause, delete, etc // Used for "selectors with interval ", set the time interval for the timer list struct _ hashSelectorEntry * m_pHashForTimers ;//
4,
The update function of CCScheduler is very large, mainly in several loops.
// Main loopvoid CCScheduler: update (float dt) {m_bUpdateHashLocked = true; if (m_fTimeScale! = 1.0f) {dt * = m_fTimeScale;} // Iterate over all the Updates 'selectors tListEntry * pEntry, * pTmp; // updates with priority <0 preferentially calls // pEntry-> target-> update (dt) calls target's update method, for example, inherit from the CCNode class // You can override the update method of CCNode/** Update method will be called automatically every frame if "scheduleUpdate" is called, and the node is "live" * // virtual void update (float delta); DL_FOREACH_SAFE (m_pUpdatesN EgList, pEntry, pTmp) {if ((! PEntry-> paused )&&(! PEntry-> markedForDeletion) {pEntry-> target-> update (dt) ;}// updates with priority = 0 DL_FOREACH_SAFE (m_pUpdates0List, pEntry, pTmp) {if ((! PEntry-> paused )&&(! PEntry-> markedForDeletion) {pEntry-> target-> update (dt) ;}// updates with priority> 0 DL_FOREACH_SAFE (m_pUpdatesPosList, pEntry, pTmp) {if ((! PEntry-> paused )&&(! PEntry-> markedForDeletion) {pEntry-> target-> update (dt) ;}// Iterate over all the custom selectors // traverses the list of timer with time intervals, call the corresponding method for (tHashTimerEntry * elt = m_pHashForTimers; elt! = NULL;) {m_pCurrentTarget = elt; m_bCurrentTargetSalvaged = false; if (! M_pCurrentTarget-> paused) {// The 'Times' array may change while inside this loop for (elt-> timerIndex = 0; elt-> timerIndex <elt-> timers-> num; ++ (elt-> timerIndex) {elt-> currentTimer = (CCTimer *) (elt-> timers-> arr [elt-> timerIndex]); elt-> currentTimerSalvaged = false; elt-> currentTimer-> update (dt ); if (elt-> currentTimerSalvaged) {// The currentTimer told the remove itself. to prevent the timer from // accidentally deallocating itself before finishing its step, we retained // it. now that step is done, it's safe to release it. elt-> currentTimer-> release ();} elt-> currentTimer = NULL;} // elt, at this moment, is still valid // so it is safe to ask this here (issue #490) elt = (tHashTimerEntry *) elt-> hh. next; // only delete currentTarget if no actions were scheduled during the cycle (issue #481) if (m_bCurrentTargetSalvaged & m_pCurrentTarget-> timers-> num = 0) {removeHashElement (m_pCurrentTarget) ;}// Iterate over all the script callbacks // traverses the timer list for the script if (m_pScriptHandlerEntries) {for (int I = m_pScriptHandlerEntries-> count () -1; I> = 0; I --) {CCSchedulerScriptHandlerEntry * pEntry = static_cast
(M_pScriptHandlerEntries-> objectAtIndex (I); if (pEntry-> isMarkedForDeletion () {m_pScriptHandlerEntries-> removeObjectAtIndex (I);} else if (! PEntry-> isPaused () {pEntry-> getTimer ()-> update (dt );}}} // delete all updates that are marked for deletion // updates with priority <0 // delete some useless timers DL_FOREACH_SAFE (m_pUpdatesNegList, pEntry, pTmp) {if (pEntry-> markedForDeletion) {this-> removeUpdateFromHash (pEntry) ;}// updates with priority = 0 DL_FOREACH_SAFE (m_pUpdates0List, pEntry, pTmp) {if (pEntry-> markedForDeletion) {this-> removeUpdateFromHash (pEntry) ;}// updates with priority> 0 DL_FOREACH_SAFE (m_pUpdatesPosList, pEntry, pTmp) {if (pEntry-> markedForDeletion) {this-> removeUpdateFromHash (pEntry) ;}} m_bUpdateHashLocked = false; m_pCurrentTarget = NULL ;}