【Cocos2d-x 3.x】 调度器Scheduler类源码分析

本文分析了Cocos2d-x 3.x中的Scheduler类,包括Timer类的结构、Scheduler的实现原理以及schedule和unschedule方法的工作流程。通过源码解读,阐述了Scheduler如何管理和调度定时任务,以及如何处理对象的定时器列表。
摘要由CSDN通过智能技术生成

非个人的全部理解,部分摘自cocos官网教程,感谢cocos官网。



在<CCScheduler.h>头文件中,定义了关于调度器的五个类:Timer,TimerTargetSelector,TimerTargetCallback, TimerScriptHandler和Scheduler,Timer和Scheduler直接继承于Ref类,TimerTargetSelector,TimerTargetCallback和TimerScriptHandler继承自Timer类。


先看看Timer类:

class CC_DLL Timer : public Ref
{
protected:
    Timer();
public:
    /** get interval in seconds */
    inline float getInterval() const { return _interval; };
    /** set interval in seconds */
    inline void setInterval(float interval) { _interval = interval; };
    
    void setupTimerWithInterval(float seconds, unsigned int repeat, float delay);
    
    virtual void trigger() = 0;
    virtual void cancel() = 0;
    
    /** triggers the timer */
    void update(float dt);
    
protected:
    
    Scheduler* _scheduler; // weak ref
    float _elapsed; // 渡过的时间
    bool _runForever; // 标记是否永远运行
    bool _useDelay; // 标记是否使用延迟
    unsigned int _timesExecuted; // 记录已经执行了多少次
    unsigned int _repeat; //0 = once, 1 is 2 x executed 定义要执行的次数,0表示执行1次, 1表示执行2次
    float _delay; // 延迟的时间 
    float _interval; // 时间间隔
};

类中定义了一个Scheduler指针变量 _scheduler,根据注释可以看出,这是一个弱引用,弱引用不会增加它所引用的对象的引用计数;

根据分析Timer类的成员变量,可以知道这是一个用来描述计时器的类;

  1. 每隔 _interval 来触发一次;

  2. _useDelay可以设置定时器触是否使用延迟; _delay是延迟时间;

  3. _repeat可以设置定时器触发的次数; _runforever设置定时器永远执行。

然后看一下Timer类的update函数:

void Timer::update(float dt) //参数dt表示距离上一次update调用的时间间隔
{
    if (_elapsed == -1)// 如果 _elapsed值为-1表示这个定时器是第一次进入到update方法 并做初始化操作。
    {
        _elapsed = 0;
        _timesExecuted = 0;
    }
    else
    {
        if (_runForever && !_useDelay)
        {//standard timer usage
            _elapsed += dt;  //累计渡过的时间。
            if (_elapsed >= _interval)
            {
                trigger();
 
                _elapsed = 0; //触发后将_elapsed清除为0,这里可能会有一小点的问题,因为 _elapsed值有可能大于_interval这里没有做冗余处理,所以会吞掉一些时间,比如 1秒执行一次,而10秒内可能执行的次数小于10,吞掉多少与update调用的频率有关系。
            }
        }    
        else
        {//advanced usage
            _elapsed += dt;
            if (_useDelay)
            {
                if( _elapsed >= _delay )
                {
                    trigger();
                     
                    _elapsed = _elapsed - _delay;//延迟执行的计算
                    _timesExecuted += 1;
                    _useDelay = false; //延迟已经过了,清除_useDelay标记。
                }
            }
            else
            {
                if (_elapsed >= _interval)
                {
                    trigger();
                     
                    _elapsed = 0;
                    _timesExecuted += 1;
 
                }
            }
 
            if (!_runForever && _timesExecuted > _repeat)//触发的次数已经满足了_repeat的设置就取消定时器。
            {    //unschedule timer
                cancel();
            }
        }
    }
}

在update函数里,调用了trigger和cancel函数,trigger是触发函数,cancel是取消定时器。


然后继续看<Scheduler.h>,是TimerTargetSelector,它继承自Timer:

class CC_DLL TimerTargetSelector : public Timer
{
public:
    TimerTargetSelector();

    /** Initializes a timer with a target, a selector and an interval in seconds, repeat in number of times to repeat, delay in seconds. */
    bool initWithSelector(Scheduler* scheduler, SEL_SCHEDULE selector, Ref* target, float seconds, unsigned int repeat, float delay);
    
    inline SEL_SCHEDULE getSelector() const { return _selector; };
    
    virtual void trigger() override;
    virtual void cancel() override;
    
protected:
    Ref* _target; // 关联一个Ref对象,应该为执行定时器的对象
    SEL_SCHEDULE _selector; // _selector是一个函数,是定时器触发时的回调函数
};

然后看看TimerTargetSelector的trigger和cancel函数,它重载了父类Timer的同名虚函数:

void TimerTargetSelector::trigger()
{
    if (_target && _selector)
    {
        (_target->*_selector)(_elapsed);
    }
}

void TimerTargetSelector::cancel()
{
    _scheduler->unschedule(_selector, _target);
}

可以看出,在trigger中,执行了_selector这个回调函数,cancel函数则调用了unscheduler函数来结束,稍后分析。


继续看下一个类TimerTargetCallback:

class CC_DLL TimerTargetCallback : public Timer
{
public:
    TimerTargetCallback();
    
    /** Initialize
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值