1. 程式人生 > >Cocos2d-x中關於schedule函式的一點理解

Cocos2d-x中關於schedule函式的一點理解

今天看到一行程式碼,大意如下:

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函式四個引數時的建構函式:

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);
}
沒發現什麼,繼續翻,在_scheduler->schedule(selector,this,interval,repeat,delay,!_running)裡,發現有如下程式碼:
timer->initWithSelector(this, selector, target, interval, repeat, delay);
繼續看initWithSelector函式,發現其中有程式碼如下:
setupTimerWithInterval(seconds, repeat, delay);
繼續翻setupTimerWithInterval函式的程式碼,程式碼如下:
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;
}
這裡段程式碼中,可以發現有一個bool型別的變數_useDelay,當delay>0時為true,否則為false.還有一個bool型別變數_runForever,如果傳入的引數是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秒之後才第一次執行,而不是一開始就執行。