有了上一章的游戏主循环的基础,那么便让我们进一步学习每一帧的处理。
本文仅供个人记录和复习,不用于其他用途
基本概念
定时器又称调度器,Cocos2d-x调度器为游戏提供定时事件和定时调用服务。所有Node
对象都知道如何调度和取消调度事件,使用调度器有几个好处:
- 每当
Node
不再可见或已从场景中移除时,调度器会停止 - Cocos2d-x暂停时,调度器也会停止。当Cocos2d-x重新开始时,调度器也会自动继续启动
- Cocos2d-x封装了一个供各种不同平台使用的调度器,使用此调度器你不用关心和跟踪你所设定的定时对象的销毁和停止,以及崩溃的风险
简单点来说,假如游戏中发生了碰撞事件,那么为了检测到这个事件,你需要根据时间来做出相应的判断。那么使用定时器,便能够让游戏更好地处理动态事件。在开发中我们经常会使用到如下3个定时器(这里我并没有使用官方的名词):
- 帧循环定时器
- 自定义定时器
- 一次性定时器
帧循环定时器
帧循环定时器又称默认调度器,该调度器是使用Node
的刷新事件update()
方法,该方法在每帧绘制之前都会被调用一次。由于每帧之间时间间隔较短,所以每帧刷新一次已足够完成大部分游戏过程中需要的逻辑判断。Cocos2d-x中Node
默认是没有启用update()
的,因此你需要重载update()
方法来执行自己的逻辑代码。通过执行schedulerUpdate()
调度器每帧执行update()
,如果需要停止这个调度器,可以使用unschedulerUpdate()
。
我们需要先在头文件中重写update()
:
|
|
然后再在.cpp
文件中实现并且调用:
|
|
从上述代码可以看出,我们在init()
方法中调用了scheduleUpdate()
,然后对update()
方法进行了实现。update()
方法对dt
的值打印了100次,然后结束了定时器,另外,这里的CCLOG
用于输出控制台信息。可能有人会问dt
是什么,其实dt
就是每帧的时间,我们这里用的是默认帧率,也就是60帧每秒,换算一下就是1帧0.0166秒。
自定义定时器
游戏开发中,在某些情况下我们可能不需要频繁的进行逻辑检测,这样可以提高游戏性能。所以Cocos2d-x还提供了自定义调度器,可以实现以一定的时间间隔连续调用某个函数。由于引擎的调度机制,自定义时间间隔必须大于两帧的间隔,否则两帧内的多次调用会被合并成一次调用。所以自定义时间间隔应在0.1秒以上。
另外,取消该调度器可以用这个方法:
|
|
至于具体的实现,我们首先要在头文件中声明update()
方法(与默认调度器不同,名字可以随意取):
|
|
然后在.cpp
文件中实现这个方法:
|
|
事实上自定义定时器有四个参数,分别是回调函数、间隔时间、执行次数、延时。上面代码中的定时器,就是在4s以后,每隔1s执行一次回调函数,一共执行10次。查看CCNode
源文件,会发现自定义定时器进行了重载:
|
|
仔细看看会发现,其实无论你是用哪一个,它们都会调用四个参数的重载方法。另外,解释一下这个CC_REPEAT_FOREVER
,意思就是无限循环。
一次性定时器
游戏中某些场合,你只想进行一次逻辑检测,Cocos2d-x同样提供了单次调度器。这个一次性的定时器只会触发一次,所以一般也用不到取消方法。不过呢,如果非要使用,那么这个取消方法和自定义定时器的一样,但是这个用的很少,因为本来就只触发一次,没必要取消。
|
|
上面这个就是一次性定时器方法,与自定义定时器相比只不过把名字换成了scheduleOnce
,而且只执行一次,因此代码实现也和自定义定时器类似。
选择器
小伙伴们可能对schedule_selector()
这个宏产生了疑问,查看CCRef
文件可以看到如下的定义:
|
好吧,那么CC_SCHEDULE_SELECTOR()
又是什么呢,接着往上找:
|
我们可以看到,CC_SCHEDULE_SELECTOR
其实就是SEL_SCHEDULE
,这里使用了C++的static_cast
强制转换。一般来说,static_cast
用于指针的强制转换,那么接着往上找:
|
|
看到这里,就需要比较良好的C++基础。关于typedef
有很多陷阱,详情请参考我的C++分类博客。SEL_SCHEDULE
代替的是一个类成员函数指针,更多的细节这里不再多说,以后再进行补充。