大佬教程收集整理的这篇文章主要介绍了【深入了解cocos2d-x 3.x】定时器(scheduler)的使用和原理探究(3),大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
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(); }
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(); //看这里 glview->pollEvents(); } else { Sleep(1); } } return 0; }@H_489_0@run函数中其他不相关的调用我已经去掉了,可以看到mainLoop函数才是真正的主循环
void DisplayLinkDirector::mainLoop() { //做其他不相关的事情 if (! _invalid) { drawScene(); } }看到这里实际上也是调用drawScene函数
void Director::drawScene() { if (! _paused) { _scheduler->update(_deltaTimE); _eventDispatcher->dispatchEvent(_eventAfterupdatE); } //之后才进行绘制 }drawScene要做的事情很多,我将绘制部分都去掉了,值得注意的是 绘制场景会在定时器之后才执行。 @H_489_0@这里可以看到,实际上执行的就是定时器的update函数,那么这个update函数中究竟执行了什么东西呢?
// main loop void scheduler::update(float dt) { _updateHashLocked = true; if (_timeScale != 1.0f) { dt *= _timeScale; } // // 定时器回调 // tListEntry *entry,*tmp; // update定时器中优先级小于0的队列先执行 DL_FOREACH_SAFE(_updatesNegList,entry,tmp) { if ((! entry->paused) && (! entry->markedFordeletion)) { entry->callBACk(dt); } } // 接下来是优先级等于0的 DL_FOREACH_SAFE(_updates0List,tmp) { if ((! entry->paused) && (! entry->markedFordeletion)) { entry->callBACk(dt); } } // 最后是大于0的 DL_FOREACH_SAFE(_updatesPosList,tmp) { if ((! entry->paused) && (! entry->markedFordeletion)) { entry->callBACk(dt); } } // 这里循环的是自定义定时器 for (tHashTimerEntry *elt = _hashForTimers; elt != nullptr; ) { _currentTarget = elt; _currentTargetSalvaged = false; if (! _currentTarget->paused) { // 遍历当前对象附属的所有定时器 for (elt->timerIndex = 0; elt->timerIndex < elt->timers->num; ++(elt->timerIndeX)) { elt->currentTimer = (Timer*)(elt->timers->arr[elt->timerIndex]); elt->currentTimerSalvaged = false; //事实上在这里执行真正的回调 elt->currentTimer->update(dt); if (elt->currentTimerSalvaged) { // 当定时器结束任务了,就应该释放掉 elt->currentTimer->release(); } elt->currentTimer = nullptr; } } // 指向链表的下一对象 elt = (tHashTimerEntry *)elt->hh.next; // 当对象的所有定时器已经执行完成,并且对象附属的定时器为空,则将对象从哈希链表中移除 if (_currentTargetSalvaged && _currentTarget->timers->num == 0) { removeHasHelement(_currentTarget); } } // 移除所有标记为删除的优先级小于0的update定时器元素 DL_FOREACH_SAFE(_updatesNegList,tmp) { if (entry->markedFordeletion) { this->removeupdateFromHash(entry); } } // 移除所有标记为删除的优先级等于0的update定时器元素 DL_FOREACH_SAFE(_updates0List,tmp) { if (entry->markedFordeletion) { this->removeupdateFromHash(entry); } } // 移除所有标记为删除的优先级大于0的update定时器元素 DL_FOREACH_SAFE(_updatesPosList,tmp) { if (entry->markedFordeletion) { this->removeupdateFromHash(entry); } } _updateHashLocked = false; _currentTarget = nullptr; }
void Timer::update(float dt) { // 初次执行 会进入到这个if中初始化 if (_elapsed == -1) { _elapsed = 0; //已执行时间 _timesExecuted = 0; //初始化重复次数 } else { if (_runForever && !_useDelay) {//循环延时函数 _elapsed += dt; if (_elapsed >= _interval) { trigger(); //真正的回调 _elapsed = 0; } } else {//advanced usage _elapsed += dt; if (_useDelay) //延时 { if( _elapsed >= _delay ) { trigger(); //真正的回调 _elapsed = _elapsed - _delay; _timesExecuted += 1; _useDelay = false; } } else //每帧调用 { if (_elapsed >= _interval) { trigger(); //真正的回调 _elapsed = 0; _timesExecuted += 1; } } //回调完成,执行取消函数 if (!_runForever && _timesExecuted > _repeat) { //unschedule timer cancel(); } } } }
trigger(); cancel();第一个函数是真正的回调执行的函数,第二个函数是去掉执行的函数
void TimerTargetSELEctor::trigger() { if (_target && _SELEctor) { (_target->*_SELEctor)(_elapsed); } } void TimerTargetSELEctor::cancel() { _scheduler->unschedule(_SELEctor,_target); }@H_489_0@以上就是定时器的实现原理分析的全过程,定时器的实现在文章中我感觉还是说的不是很清楚。真正去代码中自己走一遍应该会更加明了,对以后的应用也会更得心应手。
以上是大佬教程为你收集整理的【深入了解cocos2d-x 3.x】定时器(scheduler)的使用和原理探究(3)全部内容,希望文章能够帮你解决【深入了解cocos2d-x 3.x】定时器(scheduler)的使用和原理探究(3)所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。