制作真正可用的Cocos2d-x全局定时器

2015年03月17日 09:14 0 点赞 0 评论 更新于 2025-11-21 17:23

思路分享

在之前开发游戏的过程中,我遇到了需要一个全局定时器的需求,该定时器要求不随游戏场景的切换而停止。最初,我在百度上很容易就找到了一份名为 GlobalSchedule 的源码。然而,实际运行这份源码时,却发现它并没有达到预期的效果。经过分析,我发现每次进入新的场景时,schedule 会被清空,这就导致在 AppDelegate 中启动定时器的操作没有任何作用。

后来,在朋友的帮助下,我对这份源码进行了修改。修改的原理是利用 onEnter() 事件不会被父节点注销这一特性,具体详情可以参考官方对 onEnter 函数的解析。我将计时器启动的代码移到了 onEnter 事件里,这样改动后,运行 schedule 就不会被清除,从而实现了全局定时的功能。

源码

代码仓库地址

完整代码可在我的 GitHub 仓库 中查看。

GlobalSchedule.h

#ifndef GLOBALSCHEDULE_H_
#define GLOBALSCHEDULE_H_

#include "cocos2d.h"
USING_NS_CC;

/**
*  全局定时器
*/
class GlobalSchedule: public CCNode {
public:
virtual void onEnter();
// 开始全局定时器 fInterval: 时间间隔 ; fDelay: 延迟运行
static void start(float fInterval = 0.0f, float fDelay = 0.0f);
// 停止全局定时器
static void stop();
// 全局定时器暂停
static void pause();
// 全局定时器暂停恢复
static void resume();

// 全局定时器主逻辑实现
void globalUpdate();

private:
// 构造函数私有化,只能通过 start 来启用全局定时器
GlobalSchedule(float fInterval, float fDelay);
~GlobalSchedule();

// 静态变量保持单例
static GlobalSchedule* m_pSchedule;
};

#endif /* GLOBALSCHEDULE_H_ */

GlobalSchedule.cpp

#include "GlobalSchedule.h"

#define SCHEDULE CCDirector::sharedDirector()->getScheduler()

GlobalSchedule* GlobalSchedule::m_pSchedule = NULL;

GlobalSchedule::GlobalSchedule(float fInterval, float fDelay) {
CCLog("GlobalSchedule()");
CCAssert(!m_pSchedule, "已定义,不能重复定义");

// 不在这里直接启动计时器,而是在 enter 里面
this->onEnter();
m_pSchedule = this;
}

void GlobalSchedule::onEnter() {
CCNode::onEnter();
// 在这里启动计时器
schedule(schedule_selector(GlobalSchedule::globalUpdate), 60.0f);
}

GlobalSchedule::~GlobalSchedule() {
CCLog("GlobalSchedule().~()");
unschedule(schedule_selector(GlobalSchedule::globalUpdate));
}

void GlobalSchedule::globalUpdate() {
CCLog("global update");
/*这里是你写的计时器发生代码*/
}

void GlobalSchedule::start(float fInterval, float fDelay) {
new GlobalSchedule(fInterval, fDelay);
}

void GlobalSchedule::stop() {
CCLog("GlobalSchedule().stop()");
CCAssert(m_pSchedule, "未定义");
CC_SAFE_DELETE(m_pSchedule);
}

总结

在我的游戏开发中,使用这份修改后的源码成功实现了计时功能。不过,目前该定时器在游戏进入后台时只能停止,进入前台时需要重新启动,还没有实现暂停和继续的功能。但我认为实现这些功能应该并不困难,当时由于项目需求,我没有进行相关的开发。大家可以根据自己的需求对代码进行完善,进一步优化这个全局定时器。

作者信息

boke

boke

共发布了 3994 篇文章