您的位置:首页 > 移动开发 > Cocos引擎

[置顶] Cocos2d-x实现计时器与定时器功能

2017-05-29 12:10 513 查看
笔者最近在写一个计时和定时的功能,上网查看了不少讲述实现计时器定时器的文章,大多都直接采用Cocos2d-x的定时器schedule,通过在schedule方法添加间隔时间的参数去实现计时与定时功能。

但是学过Cocos2d-x定时器schedule的都了解,schedule定时器调用方法是有一定的间隔时间,虽然这个时间间隔很小,只有十几毫秒,一般来说没有太大的影响。但是如果需要计时或者定时的时间较长,那么误差就会增大。比如,假设每次schedule定时器调用方法的时间间隔都固定为0.015s,我们需要计时5分钟即300s(每1s计时一次),结果实际上却是过了304.5s。

为了尽量的消除误差,笔者打算采用schedule定时器与计算系统时间来实现计时和定时功能。

闲话少叙,直接通过代码说话。

计时功能

"HelloWorld.h"
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

class HelloWorld : public cocos2d::Layer
{
public:
int oldTime;  //调用schedule定时器前的时间
int num;      //计时
virtual void update(float dt);  //schedule定时器调用的方法
static cocos2d::Scene* createScene();
virtual bool init();
CR
4000
EATE_FUNC(HelloWorld);
};

#endif


"HelloWorld.cpp"
#include "HelloWorldScene.h"
#include "cocostudio/CocoStudio.h"
#include "ui/CocosGUI.h"
USING_NS_CC;
using namespace cocostudio::timeline;

Scene* HelloWorld::createScene()
{
auto scene = Scene::create();
auto layer = HelloWorld::create();
scene->addChild(layer);
return scene;
}
bool HelloWorld::init()
{
if ( !Layer::init() )
{
return false;
}
struct timeval now;
gettimeofday(&now, NULL);
this->num = 0;    //计时从0开始
CCLOG("%d",this->num);
this->oldTime = now.tv_sec;  //获取调用定时器前的时间
schedule(schedule_selector(HelloWorld::update));
return true;
}
void HelloWorld::update(float dt) {
struct timeval now;
gettimeofday(&now, NULL);
int nowTime = now.tv_sec;   //获取调用定时器后的时间
if ((nowTime - oldTime) == 1)
//判断调用定时器后的时间(可能调用了几次定时器)是否与调用定时器前的时间相差1s
{
this->num++;
CCLOG("%d",this->num);
this->oldTime = nowTime;   //重新设定调用定时器前的时间
}
}


通过上述的方法就可以实现相对误差较少的计时功能了。笔者这里只是简单的实现了一个计时器功能,输出的时间格式是可以优化的,比如输出分秒 (num/60):(num%60),就可以实现完整的计时器功能了

定时功能

"HelloWorld.h"
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

class HelloWorld : public cocos2d::Layer
{
public:
int oldTime;  //调用schedule定时器前的时间
int min;      //定时的分钟数
int sec;      //定时的秒数
virtual void update(float dt);  //schedule定时器调用的方法
static cocos2d::Scene* createScene();
virtual bool init();
CREATE_FUNC(HelloWorld);
};

#endif


"HelloWorld.cpp"
#include "HelloWorldScene.h"
#include "cocostudio/CocoStudio.h"
#include "ui/CocosGUI.h"
USING_NS_CC;
using namespace cocostudio::timeline;

Scene* HelloWorld::createScene()
{
auto scene = Scene::create();
auto layer = HelloWorld::create();
scene->addChild(layer);
return scene;
}
bool HelloWorld::init()
{
if ( !Layer::init() )
{
return false;
}
//实现一个2分钟的定时功能
this->min = 2;   //定时分钟数为2min
this->sec = 0;   //定时秒数为0s
struct timeval now;
gettimeofday(&now, NULL);
this->oldTime = now.tv_sec;
CCLOG("%d:%d",this->min,this->sec);
schedule(schedule_selector(HelloWorld::update));
return true;
}
void HelloWorld::update(float dt) {
struct timeval now;
gettimeofday(&now, NULL);
int nowTime = now.tv_sec;   //获取调用定时器后的时间
if (this->min != 0 || this->sec != 0) { //判断定时是否没有结束
if (nowTime - this->oldTime == 1)
//判断调用定时器后的时间(可能调用了几次定时器)是否与调用定时器前的时间相差1s
{
if (this->sec == 0) {
this->min--;
this->sec = 59;
CCLOG("%d:%d", this->min, this->sec);
}
else if (this->sec != 0) {
this->sec--;
CCLOG("%d:%d", this->min, this->sec);
}
this->oldTime = nowTime;   //重新设定调用定时器前的时间
}
}
else if (this->min == 0 && this->sec == 0) {  //判断定时是否结束
unschedule(schedule_selector(HelloWorld::update));  //取消定时器
CCLOG("end!");
}
}


通过上述方法就可以实现一个误差较小的定时功能了。笔者这里只是简单的实现了一个定时器功能,定时的时间可以改变的,可以把整个方法封装成类,定时的时间通过传参去设置,就可以实现一个完整的定时器方法了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: