cocos2dx 定時器使用 schedule,scheduleUpdate,scheduleOnce

一個遊戲中只有一個schedule(是單例),使用的時候要先獲取對象,如果繼承CCNode 就不用了,因爲已經獲取了。

CCScheduler *

m_pScheduler = CCDirector::sharedDirector()->getScheduler();

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





原文地址:http://blog.csdn.net/zhanghefu/article/details/38466801

cocos2dx三種定時器的使用以及停止schedule,scheduleUpdate,scheduleOnce


首先,什麼是定時器呢?或許你有時候會想讓某個函數不斷的去執行,或許只是執行一次,獲取你想讓他每隔幾秒執行一次,ok,這些都可以統統交給定時器來解決。

cocos2dx中有三種定時器:schedule,scheduleUpdate,scheduleOnce。瞭解其功能便會發現定時器真是太方便了,廢話不多說,我們逐一學習一下。

1、scheduleUpdate

加入當前節點後,程序會每幀都會自動執行一次默認的Update函數。(注:一定是Update函數哦,若想調用其他自己命名的函數則使用schedule)

看例子,走起。

首先在HelloWord類的頭文件中聲明Update函數:

  1. void Update(float dt);   //注意參數類型  
  1. void Update(float dt);   //注意參數類型  
然後在HelloWorld類源文件中實現函數Update:

  1. void HelloWorld::Update(float dt)  
  2. {  
  3.     CCLOG("baibai");  
  4. }  
  1. void HelloWorld::Update(float dt)  
  2. {  
  3.     CCLOG("baibai");  
  4. }  
現在我們可以調用了,在需要他不斷執行的地方加入調用的代碼就ok:

  1. this->scheduleUpdate();     //this是當前節點,如layer,所以可以省略啦。  
  1. this->scheduleUpdate();     //this是當前節點,如layer,所以可以省略啦。  

運行之後你將會看到不斷有baibai被打印出來

2、scheduleUpdate

可以沒隔幾秒執行某個自定義的函數,來看代碼:

首先還是在HelloWorld中聲明所要執行的函數:

  1. void Move(float dt);  
  1. void Move(float dt);  
然後在源文件實現:

  1. void HelloWorld::Move(float dt)  
  2. {  
  3.     CCLOG("baibai");  
  4. }  
  1. void HelloWorld::Move(float dt)  
  2. {  
  3.     CCLOG("baibai");  
  4. }  
現在去執行他,注意參數哦

  1. scheduleOnce(schedule_selector(HelloWorld::Move), 1.0f);//每隔1.0f執行一次,省略參數則表示每幀都要執行  
  1. scheduleOnce(schedule_selector(HelloWorld::Move), 1.0f);//每隔1.0f執行一次,省略參數則表示每幀都要執行  


運行之後,baibai每隔1.0f纔會被打印一次。

3、scheduleOnce

功能:在幾秒之後執行,並且只執行一次。

我們就執行上面所寫過的Move函數吧:

  1. scheduleOnce(schedule_selector(HelloWorld::Move), 1.0f); //在1.0f之後執行,並且只執行一次。  
  1. scheduleOnce(schedule_selector(HelloWorld::Move), 1.0f); //在1.0f之後執行,並且只執行一次。  

運行一下,baibai只是被打印了一次就完了。。。

ok,定時器的調用已經講完,大家不妨自己寫一些函數體驗一下。

但是怎麼讓定時器停止呢?

1、停止執行自己定義函數的定時器:

  1. this->unschedule(schedule_selector(HelloWorld::Move));  
  1. this->unschedule(schedule_selector(HelloWorld::Move));  
2、停止默認定時器:

  1. this->unscheduleUpdate();  
  1. this->unscheduleUpdate();  
3、停止所有定時器:

  1. this->unscheduleAllSelectors();  
  1. this->unscheduleAllSelectors();  

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. //interval,調用時間間隔,如果爲0,建議使用scheduleUpdate
  7. //repeat,回調函數會被執行repeat+1次,kCCRepeatForever是無限次調用
  8. //delay,第一次執行前的延時
  9. void schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay); 
  10. void schedule(SEL_SCHEDULE selector, float interval); 
  11. void scheduleOnce(SEL_SCHEDULE selector, float delay); 
  12. void schedule(SEL_SCHEDULE selector); 
  13. //卸載自定義定時器
  14. void unschedule(SEL_SCHEDULE selector); 
  15. void unscheduleAllSelectors(void);
  16. //恢復所有定時器和動作,OnEnter調用
  17. void resumeSchedulerAndActions(void);
  18. //暫停所有定時器和動作,OnExit調用
  19. void pauseSchedulerAndActions(void);
  20. //scheduleUpdate每幀調用
  21. virtual void update(float delta); 


3.示例

3.1.更新定時器

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

3.2.自定義定時器

  1. //開啓定時器,延時2s執行,執行3+1次,執行間隔1s
  2. this->schedule(schedule_selector(HelloWorld::log),1,3,2);
  3. //回調函數
  4. void HelloWorld::log(float dt) 
  5. CCLog("schedule");
  6. //輸出
  7. 2.004532 
  8. 1.005827 
  9. 1.000238 
  10. 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. CCAssert( selector, "Argument must be non-nil"); 
  3. CCAssert( interval >=0, "Argument must be positive"); 
  4. m_pScheduler->scheduleSelector(selector, thisinterval repeat, delay, !m_bRunning); 

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

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

至於CCSchedule內部是怎麼實現的,以及CCTimer的觸發回調,有興趣的就自己看看源碼吧
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章