Cocos2d-x中關於schedule函式的一點理解
阿新 • • 發佈:2019-02-06
今天看到一行程式碼,大意如下:
this->schedule(schedule_selector(HelloWorld::Hello),20.0);
該語句會在20秒之後執行一次Hello函式。
因為函式的引數沒有寫全,所以就想看看schedule函式別的引數預設情況下是什麼情況,發現schedule函式兩個引數的情況下,建構函式如下:
void Node::schedule(SEL_SCHEDULE selector, float interval) { this->schedule(selector, interval, CC_REPEAT_FOREVER, 0.0f); }
第三個引數會呼叫CC_REPEAT_FOREVER,是永久迴圈。
但是第四個引數呼叫的是0.0f,這個地方產生了疑問,因為第四個引數是delay,API文件裡寫的delay是意思是The amount of time that the first tick will wait before execution.按照這個意思,那麼開始的那行程式碼應該是一開始就執行一次,然後再每20秒執行一次。然而這行程式碼在一開始並沒有執行。
於是接著往下翻程式碼,下面就是schedule函式四個引數時的建構函式:
沒發現什麼,繼續翻,在_scheduler->schedule(selector,this,interval,repeat,delay,!_running)裡,發現有如下程式碼:void Node::schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay) { CCASSERT( selector, "Argument must be non-nil"); CCASSERT( interval >=0, "Argument must be positive"); _scheduler->schedule(selector, this, interval , repeat, delay, !_running); }
timer->initWithSelector(this, selector, target, interval, repeat, delay);
繼續看initWithSelector函式,發現其中有程式碼如下:
setupTimerWithInterval(seconds, repeat, delay);
繼續翻setupTimerWithInterval函式的程式碼,程式碼如下:
這裡段程式碼中,可以發現有一個bool型別的變數_useDelay,當delay>0時為true,否則為false.還有一個bool型別變數_runForever,如果傳入的引數是CC_REPEAT_FOREVER時則為true,否則為false.void Timer::setupTimerWithInterval(float seconds, unsigned int repeat, float delay) { _elapsed = -1; _interval = seconds; _delay = delay; _useDelay = (_delay > 0.0f) ? true : false; _repeat = repeat; _runForever = (_repeat == CC_REPEAT_FOREVER) ? true : false; }
_useDelay在void Timer::update(float dt)中有使用,其程式碼如下:
void Timer::update(float dt)
{
if (_elapsed == -1)
{
_elapsed = 0;
_timesExecuted = 0;
}
else
{
if (_runForever && !_useDelay)
{//standard timer usage
_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();
}
}
}
}
其中引數dt為每兩幀的間隔時間,_elapsed初始化為0,當_runForever為true,_useDelay為false時,可以發現是在_elapsed>=_interval的時候才會觸發,觸發後再次將_elapsed置為0。因為_elapsed+=dt,所以_elapsed正是從上次觸發到現在的時間。
這就解釋了為什麼開頭的程式碼會是間隔20秒之後才第一次執行,而不是一開始就執行。