一、默认的定时器
1、定时器函数update
(1)每一个节点都有一个默认的update函数,该函数继承与父类,因此当我们使用默认的update函数时需要对它
进行重写。
virtual void update ( float dt) ;
(2)函数参数解释:
update函数里面有一个float dt的参数,这个参数的意义是上一次调用这个函数到本次调用这个函数中间
间隔了多少秒。
对于这个函数参数的意义需要注意一下,游戏设计的过程中通常需要注意到这一点。例如:如果在update
函数体中写位移的逻辑时,需要使“位移增量 * dt”。
dt代表update函数执行的两次执行的时间间隔,可以理解为与设备的帧率有关系。假设有A设备,帧率为60帧/s,
B设备,帧率为80帧/s。则dt_A = 1.0/60s, dt_B = 1.0f / 80s。在单位之间1秒内,设备A调用update函数60次,
设备B调用update函数80次。如果update函数体中移动的逻辑不乘以dt:A设备移动为 60 * offset, B设备移动
80 * offset。那么想象一下,一个由于在不同的设备中产生了不同的移动效果合理吗?
假如我们在update函数体的位移逻辑中乘以这个dt参数呢?设备A移动:60 * offset * 1 / 60 = offset;
设备B移动:80 *offset * 1 / 80 = offset。这样才是一个合理的游戏规则,而不是一个设计bug。
2、默认定时器函数的调用
对于默认定时器函数的调用,我们可以使用scheduleUpdate函数来实现,以此执行默认的update函数,并且
每帧执行一次。
原理:
使用scheduleUpdate()函数来是默认的update函数执行起来的时候,该函数会把当前的节点(类对象:可能
是一个Layer,Node等)添加到指定的队列中。处于该队列中的节点每一帧都会被调用以此默认的update函数。
3、默认定时器函数的关闭
unscheduleUpdate()函数用来关闭默认的定时器函数,相当于把该节点对象从上述队列中移除。
4、示例
我们在默认update函数中打印“I love China, I am a Chinese!”,每调用一次该函数都进行一次计数,
当打印5次之后我们关闭这个默认定时器函数的刷新。
void update ( float dt)
{
static int count = 1 ;
if ( 5 == count)
{
this -> unscheduleUpDate ( ) ;
}
log ( "I love China, I am a Chinese!" ) ;
}
二、自定义定时器
1、定时器函数的自定义
每一个节点只能有一个默认的定时器函数update,并且该默认函数需要进行重写;但是可以有多个自定义的
定时器函数。例如:
void myUpdate ( float dt) ;
void myUpdate ( float dt)
{
log ( "my update" ) ;
}
2、自定义定时器函数的调用
通常使用schedule函数来调用自定义的update函数的运行,schedule函数的声明如下:
void schedule ( SEL_SCHEDULE selector) ;
void schedule ( SEL_SCHEDULE selector, float interval) ;
void schedule ( SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay) ;
void scheduleOnce ( SEL_SCHEDULE selector, float delay) ;
当然这里还有以lambda表达式的形式调用定时器函数,但是这里就不再罗列出来,有兴趣的可以自行查看。
3、自定义定时器函数的停止
void unschedule ( SEL_SCHEDULE selector) ;
void unscheduleAllSelectors ( ) ;
4、示例:
void myUpdate ( float dt)
{
static int count = 1 ;
if ( 5 == count)
{
this -> unschedule ( schedule_selecotr ( MyClass:: myUpdate) ) ;
}
log ( "I love China, I am a Chinese!" ) ;
}
this -> schecule ( schedule_selecotr ( MyClasses:: myUpdate) , 0.1f ) ;