Cocosd-x 3.1r源码分析 : Scheduler(定时器) 源码分析

更新时间:2023-07-08 08:50:19 阅读: 评论:0

唯美的个性签名源码版本  3.1r,转载请注明
cocos2d-x源码分析目录
blog.csdn/u011225840/article/details/31743129
1.继承结构
没错,是两张图。(你没有老眼昏花。。我脑子也没有秀逗。。)Ref就是原来的CCObject,而Timer类是与Scheduler类密切相关的类,所以需要把他们放在一起说。Timer 和Scheduler的关系就像Data和DataManager的关系。
2.源码分析
2.1Timer
2.1.1Timer中的数据
Timer类定义了一个行为执行的间隔,执行的次数等,可以理解为定时器的数据类,而具体的定时器的行为,定义在子类中。Timer中的数据如下:
[cpp]view plaincopy
明朝大太监
1.//_elapd上一次执行后到现在的时间
2.//timesExecuted执行的次数
3.//interval执行间隔
4.//uDelay是否使用延迟执行
5.float_elapd;
6.bool_runForever;
7.bool_uDelay;
8.unsigned int_timesExecuted;
9.unsigned int_repeat;//0=once,1is2x executed
10.float_delay;
11.float_interval;
2.1.2Update函数
[cpp]view plaincopy
1.void Timer::update(float dt)
2.{
3.
4.//update方法使用的是模板设计模式,将trigger与cancel的实现交给子类。
5.
6.
7.
8.
忍不住回头
9.if(_elapd==-1)
10.{
11._elapd=0;
12._timesExecuted=0;
13.}
14.//四种情况
15./*
16.  1.永久执行并且不使用延迟:基本用法,计算elapd大于interval后执行一次,
永不cancel。
17.  2.永久执行并且使用延迟:当elapd大于延迟时间后,执行一次后,进入情况1.
18.  3.不永久执行并且不使用延迟:情况1结束后,会判断执行次数是否大于重复次数,大
于后则cancel。
19.  4.不永久执行并且使用延迟:情况2结束后,进入情况3.
20.*/
21.el
22.{
23.if(_runForever&&!_uDelay)
24.{//standard timer usage
25._elapd+=dt;
26.if(_elapd>=_interval)
27.{
29.武帝山
30._elapd=0;
31.}
32.}
33.el
34.{//advanced usage
35._elapd+=dt;
36.if(_uDelay)
水煮腰花37.{
38.if(_elapd>=_delay)
39.{
41.
42._elapd=_elapd-_delay;
43._timesExecuted+=1;
44._uDelay=fal;
45.}
46.}
47.el
48.{
49.if(_elapd>=_interval)
50.{
52.
53._elapd=0;
54._timesExecuted+=1;
55.
56.}
57.}
58.
59.if(!_runForever&&_timesExecuted>_repeat)
60.{//unschedule timer
61.cancel();
62.}
63.}
64.}
65.}
正如我注释中所说,update使用了模板方法的设计模式思想,将trigger与cancel 调用的过程写死,但是不同的子类实现trigger和cancel的方式不同。
另外需要注意的是,Schedule使用时delay的需求,当有delay与没有delay我在源码中已经分析的很清楚了。
2.2TimerTargetSelector&&TimerTargetCallb ack
前者是针对类(继承自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方法中可以更好的看清这一切。
[cpp]view plaincopy
1.void TimerTargetSelector::trigger()
2.{
3.if(_target&&_lector)
4.{
5.(_target->*_lector)(_elapd);
6.}
7.}
8.
9.void TimerTargetCallback::trigger()
10.{
11.if(_callback)
12.{
13._callback(_elapd);阳刚男孩
14.}
15.}
最后说一下,TargetCallback中含有一个key,而前者没有。这在下面的源码分析中会看到。(其实原理很简单,SEL_SCHEDULE可以当成key,ccSchedulerFunc不能,因为前者有唯一的标识,如果你不懂这点,欢迎去复习下c++的指向类中方法的函数指针)
单位同意报考证明模板[cpp]view plaincopy
1.Ref*_target;
2.SEL_SCHEDULE_lector;
3.------------------------------
4.void*_target;
5SchedulerFunc_callback;
6.std::string_key;
2.3Scheduler
2.3.1Schedule&&UnSchedule
Schedule有四种重载方法。其中各有两种针对不同的Timer子类,但是都大同小异,在此之前,不得不说一个用的非常多的数据结构tHashTimerEntry的
[cpp]view plaincopy
2.{
3Array*timers;
4.void*target;
5.int timerIndex;
6.Timer*currentTimer;
7.bool currentTimerSalvaged;
8.bool paud;
9.UT_hash_handle hh;
10.}tHashTimerEntry;
这用到了开源库uthash,关于该hast的具体用法。请自行谷歌。UT_hash_handle能让我们根据key值找到相应的数据。在这个结构里,target是key值,其他都是数据(除了hh哦)。timers存放着该target相关的所有timer。currentTimerSalvaged的作用是如果你想停止unschedule正在执行的timer时,会将其从timers移除,并retain,防止被自动回收机制回收,然后将此标识为true。下面来看下第一种TimerCallback的Schedule。
[cpp]view plaincopy
1.void Scheduler::schedule(const ccSchedulerFunc&callback,void*target,floa
t interval,unsigned int repeat,float delay,bool paud,const std::string &key)
2.{
3.CCASSERT(target,"Argument target must be non-nullptr");
4.CCASSERT(!pty(),"key should not be empty!");
5.//先在hash中查找该target(key值)是否已经有数据
6.tHashTimerEntry*element=nullptr;
7.HASH_FIND_PTR(_hashForTimers,&target,element);
8.//没有就创建一个,并且将其加入
9.if(!element)
沙僧的简笔画
10.{
11.element=(tHashTimerEntry*)calloc(sizeof(*element),1);
12.element->target=target;

本文发布于:2023-07-08 08:50:19,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1085165.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:执行   使用   源码
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图