Cocos2d-x 源码分析 : Scheduler(定时器) 源码分析

本文分析了Cocos2d-x 3.1r版本中Scheduler类及其相关Timer的源码,包括Timer的数据结构、Update函数、Scheduler的Schedule与UnSchedule方法、定时模式以及状态管理等核心功能。通过对源码的深入探讨,揭示了3.x版本的新特性。
摘要由CSDN通过智能技术生成

源码版本 3.1r,转载请注明


        我也终于不out了,开始看3.x的源码了,此时此刻的心情只能是wtf!!!!!!!!!!不过也终于告别CC时代了。


        cocos2d-x 源码分析目录

        http://blog.csdn.net/u011225840/article/details/31743129


1.继承结构

           没错,是两张图。(你没有老眼昏花。。我脑子也没有秀逗。。)Ref就是原来的CCObject,而Timer类是与Scheduler类密切相关的类,所以需要把他们放在一起说。Timer和Scheduler的关系就像Data和DataManager的关系。

2.源码分析

2.1 Timer

2.1.1 Timer中的数据

Timer类定义了一个行为执行的间隔,执行的次数等,可以理解为定时器的数据类,而具体的定时器的行为,定义在子类中。Timer中的数据如下:
                
//_elapsed 上一次执行后到现在的时间
	//timesExecuted 执行的次数
	//interval 执行间隔
	//useDelay 是否使用延迟执行
    float _elapsed;
    bool _runForever;
    bool _useDelay;
    unsigned int _timesExecuted;
    unsigned int _repeat; //0 = once, 1 is 2 x executed
    float _delay;
    float _interval;

2.1.2 Update函数

void Timer::update(float dt)
{

	//update方法使用的是模板设计模式,将trigger与cancel的实现交给子类。



	
    if (_elapsed == -1)
    {
        _elapsed = 0;
        _timesExecuted = 0;
    }
	//四种情况
	/*
		1.永久执行并且不使用延迟:基本用法,计算elapsed大于interval后执行一次,永不cancel。
		2.永久执行并且使用延迟:当elapsed大于延迟时间后,执行一次后,进入情况1.
		3.不永久执行并且不使用延迟:情况1结束后,会判断执行次数是否大于重复次数,大于后则cancel。
		4.不永久执行并且使用延迟:情况2结束后,进入情况3.
	*/
    else
    {
        if (_runForever && !_useDelay)
        {//standard timer usage
            _elapsed += dt;
            if (_elapsed >= _interval)
            {
                trigger();

                _elapsed = 0;
            }
        }    
        else
        {//advanced usage
            _elapsed += dt;
            if (_useDelay)
            {
                if( _elapsed >= _delay )
                {
                    trigger();
                    
                    _elapsed = _elapsed - _delay;
                    _timesExecuted += 1;
                    _useDelay = false;
                }
            }
            else
            {
                if (_elapsed >= _interval)
                {
                    trigger();
                    
                    _elapsed = 0;
                    _timesExecuted += 1;

                }
            }

            if (!_runForever && _timesExecuted > _repeat)
            {    //unschedule timer
                cancel();
            }
        }
    }
}
          正如我注释中所说,update使用了模板方法的设计模式思想,将trigger与cancel调用的过程写死,但是不同的子类实现trigger和cancel的方式不同。
           另外需要注意的是,Schedule使用时delay的需求,当有delay与没有delay我在源码中已经分析的很清楚了。

2.2 TimerTargetSelector   && TimerTargetCallback

           前者是针对类(继承自Ref)中的method进行定时,而后者是针对function(普通函数)。
           前者绑定的类型是SEL_SCHEDULE(你问我这是什么?)typedef void (Ref::*SEL_SCHEDULE)(float);一个指向Ref类型的method指针,并且该method必须满足参数是float,返回值是void。后者绑定的类型是ccSchedulerFunc---------typedef std::function<void(float)> ccSchedulerFunc;这是虾米?这是c++11的新特性,其实就是一个函数指针。
           从他们实现的trigger方法中可以更好的看清这一切。
void TimerTargetSelector::trigger()
{
    if (_target && _selector)
    {
        (_target->*_selector)(_elapsed);
    }
}

void TimerTargetCallback::trigger()
{
    if (_callback)
    {
        _callback(_elapsed);
    }
}


最后说一下,TargetCallback中含有一个key,而前者没有。这在下面的源码分析中会看到。(其实原理很简单,SEL_SCHEDULE可以当成key,ccSchedulerFunc不能,因为前者有唯一的标识,如果你不懂这点,欢迎去复习下c++的指向类中方法的函数指针)
    Ref* _target;
    SEL_SCHEDULE _selector;
 ------  ------------------------
    void* _target;
    ccSchedulerFunc _callback;
    std::string _key;



2.3 Scheduler

2.3.1 Schedule && UnSchedule

Schedule有四种重载方法。其中各有两种针对不同的Timer子类,但是都大同小异,在此之前࿰
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值