【玩轉cocos2d-x之十一】定時器schedule

原創作品,轉載請標明:http://blog.csdn.net/jackystudio/article/details/12848473


如果我們想定時執行一個動作怎麼辦?CCScheduler幫了我們一個大忙。


1.概況

CCNode內部封裝了一個

  1. CCScheduler *m_pScheduler;  

正是通過它我們可以很輕鬆地完成一些定時功能,所以定時器是節點所具備的功能。

定時器分爲2種,一種是更新定時器,執行的頻率是每幀執行一次,另一種則是自定義回調函數的定時器(最小值是一幀),關於回調函數和函數指針的相關基礎可參見http://blog.csdn.net/jackystudio/article/details/11720325


2.API

  1. //更新定時器,每幀調用1次。每個節點只能有1個被調度的update函數  
  2. void scheduleUpdate(void);  
  3. //卸載更新定時器  
  4. void unscheduleUpdate(void);  
  5.   
  6. //自定義定時器,如果重複調用,那調用間隔會更新,而不會再次調用  
  7. //interval,調用時間間隔,如果爲0,建議使用scheduleUpdate  
  8. //repeat,回調函數會被執行repeat+1次,kCCRepeatForever是無限次調用  
  9. //delay,第一次執行前的延時  
  10. void schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay);  
  11. void schedule(SEL_SCHEDULE selector, float interval);  
  12. void scheduleOnce(SEL_SCHEDULE selector, float delay);  
  13. void schedule(SEL_SCHEDULE selector);  
  14. //卸載自定義定時器  
  15. void unschedule(SEL_SCHEDULE selector);  
  16. void unscheduleAllSelectors(void);  
  17.   
  18. //恢復所有定時器和動作,OnEnter調用  
  19. void resumeSchedulerAndActions(void);  
  20. //暫停所有定時器和動作,OnExit調用  
  21. void pauseSchedulerAndActions(void);  
  22.   
  23. //scheduleUpdate每幀調用  
  24. virtual void update(float delta);  


3.示例

3.1.更新定時器

  1. //開啓定時器  
  2. this->scheduleUpdate();  
  3.   
  4. //虛函數update  
  5. void HelloWorld::update(float delta)  
  6. {  
  7.     CCLog("%f",delta);  
  8. }  
  9.   
  10. //輸出,這裏設置了60fps,調用間隔1/60s  
  11. 0.016667  
  12. 0.016676  
  13. 0.016657  
  14. 0.016669  

3.2.自定義定時器

  1. //開啓定時器,延時2s執行,執行3+1次,執行間隔1s  
  2. this->schedule(schedule_selector(HelloWorld::log),1,3,2);  
  3.   
  4. //回調函數  
  5. void HelloWorld::log(float dt)  
  6. {  
  7.     CCLog("schedule");  
  8. }  
  9.   
  10. //輸出  
  11. 2.004532  
  12. 1.005827  
  13. 1.000238  
  14. 1.001019  

4.schedule_selector和SEL_SCHEDULE

看到上面的schedule_selector了吧,這又是個什麼玩意?看看它的宏定義。

  1. #define schedule_selector(_SELECTOR) (SEL_SCHEDULE)(&_SELECTOR)  
原來是把函數指針轉化爲SEL_SCHEDULE型指針,那SEL_SCHEDULE又是什麼?

  1. typedef void (CCObject::*SEL_SCHEDULE)(float);  
也沒啥,就是定義了一個帶有float參數函數指針。所以我們在使用自定義Schedule的時候,回調函數一定要記得帶上一個float參數,它記錄了兩次執行的間隔。如果忘了,可是會出現類型轉換錯誤的異常。這種方式在callfunc_selector,menu_selector等也以同樣的方式出現。


5.誰來調用回調函數

但是有沒有發現,如果這個回調函數是個全局函數或者static函數也就算了,偏偏它是個成員函數,成員函數需要實例來調用,可是從調用方法來看,好像沒傳入調用對象?

  1. this->schedule(schedule_selector(HelloWorld::log),1,3,2);  

是的,還記得一開頭說的CCNode內部封裝的m_pScheduler嗎?

  1. CCScheduler *m_pScheduler;  
原來CCNode幫我們實現了:

  1. void CCNode::schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay)  
  2. {  
  3.     CCAssert( selector, "Argument must be non-nil");  
  4.     CCAssert( interval >=0, "Argument must be positive");  
  5.   
  6.     m_pScheduler->scheduleSelector(selector, this, interval , repeat, delay, !m_bRunning);  
  7. }  

原來this這個時候被傳入了,同時傳入的參數還有m_bRunning,m_bRunning表示節點是否在運行中(是否在舞臺上),OnEnter的時候賦值true,OnExit的時候賦值false,所以在執行定時器的時候還必須確保節點有在運行。

這樣確實用起來怪怪的,所以在cocos2d-x v3.0版本中,參數和函數指針用一個宏打包起來了~

至於CCSchedule內部是怎麼實現的,以及CCTimer的觸發回調,有興趣的就自己看看源碼吧,我也寫不來,源碼有點長啊。哭


發佈了107 篇原創文章 · 獲贊 45 · 訪問量 126萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章