[In-depth understanding of cocos2d-x 3. x] timer (sched) use and principle of inquiry (3), cocos2d-xscheduler

Source: Internet
Author: User

[In-depth understanding of cocos2d-x 3. x] timer (sched) use and principle of inquiry (3), cocos2d-xscheduler

The previous article analyzed the definition of the timer. The focus of this article is how the timer runs.

1. Find the timer callback from main

When talking about the running of the timer, you have to touch the main function of cocos2dx, because the timer runs on the main thread and is not a separate thread, therefore, its call is bound to be called every frame in the main function.

The following code is the main function on the win32 platform.

int APIENTRY _tWinMain(HINSTANCE hInstance,                       HINSTANCE hPrevInstance,                       LPTSTR    lpCmdLine,                       int       nCmdShow){    UNREFERENCED_PARAMETER(hPrevInstance);    UNREFERENCED_PARAMETER(lpCmdLine);    // create the application instance    AppDelegate app;    return Application::getInstance()->run();}

Directly calling the run function directly enters the run

Int Application: run () {while (! Glview-> windowShouldClose () {QueryPerformanceCounter (& nNow); if (nNow. quadPart-nLast. quadPart> _ animationInterval. quadPart) {nLast. quadPart = nNow. quadPart-(nNow. quadPart % _ animationInterval. quadPart); director-> mainLoop (); // check glview-> pollEvents ();} else {Sleep (1) ;}} return 0 ;}

Other irrelevant calls in the run function have been removed. You can see that the mainLoop function is the real main loop.

Void DisplayLinkDirector: mainLoop () {// do other unrelated things if (! _ Invalid) {drawScene ();}}
The drawScene function is actually called here.

Void Director: drawScene () {if (! _ Paused) {_ schedcher-> update (_ deltaTime); _ eventDispatcher-> dispatchEvent (_ eventAfterUpdate);} // draw only}
DrawScene has a lot to do. I have removed all the painting parts. It is worth noting that the painting scenario will be executed after the timer.

Here we can see that the update function of the timer is actually executed, so what exactly is executed in this update function?

2. update functions of the timer

First, let's take a look at the Update code.

// Main loopvoid Scheduler: update (float dt) {_ updateHashLocked = true; if (_ timeScale! = 1.0f) {dt * = _ timeScale;} // timer callback // tListEntry * entry, * tmp; // For a queue whose priority is less than 0 in the Update timer, run DL_FOREACH_SAFE (_ updatesNegList, entry, tmp) {if ((! Entry-> paused )&&(! Entry-> markedForDeletion) {entry-> callback (dt) ;}// The following is the DL_FOREACH_SAFE (_ updates0List, entry, tmp) {if ((! Entry-> paused )&&(! Entry-> markedForDeletion) {entry-> callback (dt) ;}// Finally, DL_FOREACH_SAFE (_ updatesPosList, entry, tmp) {if ((! Entry-> paused )&&(! Entry-> markedForDeletion) {entry-> callback (dt) ;}// the custom timer for (tHashTimerEntry * elt = _ hashForTimers; elt! = Nullptr;) {_ currentTarget = elt; _ currentTargetSalvaged = false; if (! _ CurrentTarget-> paused) {// traverses all the timers attached to the current object for (elt-> timerIndex = 0; elt-> timerIndex <elt-> timers-> num; ++ (elt-> timerIndex) {elt-> currentTimer = (Timer *) (elt-> timers-> arr [elt-> timerIndex]); elt-> currentTimerSalvaged = false; // in fact, the real callback elt is executed here-> currentTimer-> update (dt); if (elt-> currentTimerSalvaged) {// when the timer ends the task, elt-> currentTimer-> release ();} elt-> currentTimer = nullptr;} should be released ;}} // point to the next object elt = (tHashTimerEntry *) elt-> hh. next; // when all the timers of the object have been executed and the timer attached to the object is empty, the object will be removed from the hash linked list if (_ currentTargetSalvaged & _ currentTarget-> timers-> num = 0) {removeHashElement (_ currentTarget );}} // remove all update timer Elements marked as deleted with a priority less than 0, DL_FOREACH_SAFE (_ updatesNegList, entry, tmp) {if (entry-> markedForDeletion) {this-> removeUpdateFromHash (entry) ;}// remove all update timer Elements marked as deleted with a priority of 0 DL_FOREACH_SAFE (_ updates0List, entry, tmp) {if (entry-> markedForDeletion) {this-> removeUpdateFromHash (entry) ;}// remove all update timer Elements marked as deleted with a priority greater than 0, DL_FOREACH_SAFE (_ updatesPosList, entry, tmp) {if (entry-> markedForDeletion) {this-> removeUpdateFromHash (entry) ;}}_ updateHashLocked = false; _ currentTarget = nullptr ;}


There are three parts worth noting:

For the third point, we will continue to analyze this update function.
Void Timer: update (float dt) {// the first execution will enter this if to initialize if (_ elapsed =-1) {_ elapsed = 0; // executed time _ timesExecuted = 0; // Number of initialization repetitions} else {if (_ runForever &&! _ UseDelay) {// cyclic delay function _ elapsed + = dt; if (_ elapsed >=_ interval) {trigger (); // real callback _ elapsed = 0 ;}} else {// advanced usage _ elapsed + = dt; if (_ useDelay) // latency {if (_ elapsed >=_ delay) {trigger (); // real callback _ elapsed = _ elapsed-_ delay; _ timesExecuted + = 1; _ useDelay = false ;}} else // call each frame {if (_ elapsed >=_ interval) {trigger (); // real callback _ elapsed = 0; _ timesExecuted + = 1 ;}// the callback is complete. Execute the cancel function if (! _ RunForever & _ timesExecuted> _ repeat) {// unschedule timer cancel ();}}}}

The logic of this large piece of code is very clear, and the delay functions are mainly divided into permanent loop delay functions and limited loop delay functions; the latency function of a finite loop can be divided into the call of each frame and the call of a fixed time according to the optimization. The above code is optimized based on this classification.

In fact, the core functions are

trigger();cancel();
The first function is the real callback execution function, and the second function is to remove the execution function.

void TimerTargetSelector::trigger(){    if (_target && _selector)    {        (_target->*_selector)(_elapsed);    }}void TimerTargetSelector::cancel(){    _scheduler->unschedule(_selector, _target);}

The above is the entire process of analyzing the implementation principle of the timer. In the article, I am still not very clear about the implementation of the timer. It should be clearer to go through the code and be more comfortable with future applications.



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.