先把我的思路分享一下:

        因为之前有次做游戏中需要一个全局定时器,要求是不随游戏场景切换而停止。第一时间在百度很容易就找到一个源码,GlobalSchedule,但是这份源码实际运行起来是没有效果的,因为每次进入新的场景会清空schedule,导致在AppDelegate中的启动没有任何效果。

       于是在朋友的帮助下,我对这份源码进行了改动,原理是onEnter()事件不会被父节点注销,详情可以参考官方对onEnter函数的解析。

       代码改动后将计时器启动的代码写在了onEnter事件里。这样运行schedule起来就不会被清除了,可以实现全局定时。


【源码】

github地址:https://github.com/winterfeel/NewGlobalSchedule


GlobalSchedule.h  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef GLOBALSCHEDULE_H_  
#define GLOBALSCHEDULE_H_  
   
#include "cocos2d.h"  
USING_NS_CC;  
   
/** 
 *  全局定时器 
 */  
class GlobalSchedule: public CCNode {  
    public:  
        virtual void onEnter();  
        // 开始全局定时器 fInterval: 时间间隔 ; fDelay: 延迟运行  
        static void start(float fInterval = 0.0f, float fDelay = 0.0f);  
        // 停止全局定时器  
        static void stop();  
        // 全局定时器暂停  
        static void pause();  
        // 全局定时器暂停恢复  
        static void resume();  
           
        // 全局定时器主逻辑实现  
        void globalUpdate();  
           
    private:  
        // 构造函数私有化,只能通过 start 来启用全局定时器  
        GlobalSchedule(float fInterval, float fDelay);  
        ~GlobalSchedule();  
           
        // 静态变量保持单例  
        static GlobalSchedule* m_pSchedule;  
};  
   
#endif /* GLOBALSCHEDULE_H_ */


GlobalSchedule.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include "GlobalSchedule.h"  
   
#define SCHEDULE CCDirector::sharedDirector()->getScheduler()  
   
GlobalSchedule* GlobalSchedule::m_pSchedule = NULL;  
   
GlobalSchedule::GlobalSchedule(float fInterval, float fDelay) {  
    CCLog("GlobalSchedule()");  
       
    CCAssert(!m_pSchedule, "已定义,不能重复定义");  
   
    //SCHEDULE->scheduleSelector(  
    //                           schedule_selector(GlobalSchedule::globalUpdate), this, fInterval,  
     ///                          false,  
     //                          kCCRepeatForever, fDelay);  
    this->onEnter();//这里进行了修改,不在这里直接启动计时器,而是在enter里面  
    m_pSchedule = this;  
}  
   
void GlobalSchedule::onEnter()  
{  
    CCNode::onEnter();  
    schedule(schedule_selector(GlobalSchedule::globalUpdate), 60.0f);//在这里启动计时器  
}  
   
GlobalSchedule::~GlobalSchedule() {  
    CCLog("GlobalSchedule().~()");  
       
    unschedule(schedule_selector(GlobalSchedule::globalUpdate));  
}  
   
void GlobalSchedule::globalUpdate() {  
    CCLog("global update");  
    /*这里是你写的计时器发生代码*/  
}  
   
void GlobalSchedule::start(float fInterval, float fDelay) {  
    new GlobalSchedule(fInterval, fDelay);  
}  
   
void GlobalSchedule::stop() {  
    CCLog("GlobalSchedule().stop()");  
       
    CCAssert(m_pSchedule, "未定义");  
    CC_SAFE_DELETE(m_pSchedule);  
}


【总结】

我在游戏中用这份源码可以实现即计时,不过在游戏进入后台的时候只能停止,然后进入前台时重新启动,还没有做到暂停、继续。实现起来应该不难,当时不需要就没写,大家可以自己发挥,写一个完善一下,哈哈~