原創作品,轉載請標明:http://blog.csdn.net/jackystudio/article/details/12848473
如果我們想定時執行一個動作怎麼辦?CCScheduler幫了我們一個大忙。
1.概況
CCNode內部封裝了一個
- CCScheduler *m_pScheduler;
正是通過它我們可以很輕鬆地完成一些定時功能,所以定時器是節點所具備的功能。
定時器分爲2種,一種是更新定時器,執行的頻率是每幀執行一次,另一種則是自定義回調函數的定時器(最小值是一幀),關於回調函數和函數指針的相關基礎可參見http://blog.csdn.net/jackystudio/article/details/11720325。
2.API
- //更新定時器,每幀調用1次。每個節點只能有1個被調度的update函數
- void scheduleUpdate(void);
- //卸載更新定時器
- void unscheduleUpdate(void);
- //自定義定時器,如果重複調用,那調用間隔會更新,而不會再次調用
- //interval,調用時間間隔,如果爲0,建議使用scheduleUpdate
- //repeat,回調函數會被執行repeat+1次,kCCRepeatForever是無限次調用
- //delay,第一次執行前的延時
- void schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay);
- void schedule(SEL_SCHEDULE selector, float interval);
- void scheduleOnce(SEL_SCHEDULE selector, float delay);
- void schedule(SEL_SCHEDULE selector);
- //卸載自定義定時器
- void unschedule(SEL_SCHEDULE selector);
- void unscheduleAllSelectors(void);
- //恢復所有定時器和動作,OnEnter調用
- void resumeSchedulerAndActions(void);
- //暫停所有定時器和動作,OnExit調用
- void pauseSchedulerAndActions(void);
- //scheduleUpdate每幀調用
- virtual void update(float delta);
3.示例
3.1.更新定時器
- //開啓定時器
- this->scheduleUpdate();
- //虛函數update
- void HelloWorld::update(float delta)
- {
- CCLog("%f",delta);
- }
- //輸出,這裏設置了60fps,調用間隔1/60s
- 0.016667
- 0.016676
- 0.016657
- 0.016669
3.2.自定義定時器
- //開啓定時器,延時2s執行,執行3+1次,執行間隔1s
- this->schedule(schedule_selector(HelloWorld::log),1,3,2);
- //回調函數
- void HelloWorld::log(float dt)
- {
- CCLog("schedule");
- }
- //輸出
- 2.004532
- 1.005827
- 1.000238
- 1.001019
4.schedule_selector和SEL_SCHEDULE
看到上面的schedule_selector了吧,這又是個什麼玩意?看看它的宏定義。
- #define schedule_selector(_SELECTOR) (SEL_SCHEDULE)(&_SELECTOR)
- typedef void (CCObject::*SEL_SCHEDULE)(float);
5.誰來調用回調函數
但是有沒有發現,如果這個回調函數是個全局函數或者static函數也就算了,偏偏它是個成員函數,成員函數需要實例來調用,可是從調用方法來看,好像沒傳入調用對象?
- this->schedule(schedule_selector(HelloWorld::log),1,3,2);
是的,還記得一開頭說的CCNode內部封裝的m_pScheduler嗎?
- CCScheduler *m_pScheduler;
- void CCNode::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");
- m_pScheduler->scheduleSelector(selector, this, interval , repeat, delay, !m_bRunning);
- }
原來this這個時候被傳入了,同時傳入的參數還有m_bRunning,m_bRunning表示節點是否在運行中(是否在舞臺上),OnEnter的時候賦值true,OnExit的時候賦值false,所以在執行定時器的時候還必須確保節點有在運行。
這樣確實用起來怪怪的,所以在cocos2d-x v3.0版本中,參數和函數指針用一個宏打包起來了~
至於CCSchedule內部是怎麼實現的,以及CCTimer的觸發回調,有興趣的就自己看看源碼吧,我也寫不來,源碼有點長啊。