制作一个在一定时间后执行函数的计时器,以毫秒为单位

时间:2013-08-30 10:28:00

标签: c++ timer

假设我有这个功能:

void changeMap(Player* player, int map) {
      player->setMap(map);
}

我想要一个计时器类,让我能在一段时间后运行该函数,就像这样。

Player* chr;
int mapid = 300;
int milliseconds = 6000;

Timer.Schedule(changeMap(chr, 300), milliseconds);

提前致谢。

3 个答案:

答案 0 :(得分:2)

如果这是游戏循环,那么一种方法是保留您希望在将来某个时间发生的事件列表,其中您存储时间和指向要调用的函数的指针。 (或者std :: function,或者其他)。保持列表按时间排序,以便最快的事件是列表的顶部。

然后在你的主游戏循环中,每个循环,检查列表顶部是否已经达到该事件的时间,以及是否已弹出事件并调用该函数。

答案 1 :(得分:0)

通过自由使用Functor委托对象和模板,您可以实现所需的效果:

CAlarm.h

#ifndef CALARM_H
#define CALARM_H

#include "ADTtime.h"
#include "CStopwatch.h"

template<class FunctionObject>
class Alarm : public StopWatch {

public:

    Alarm(const FunctionObject& fn);
    Alarm(double tickTime, const FunctionObject& fn);

    virtual ~Alarm();

    FunctionObject Tick();

protected:
    FunctionObject _delegate;
    double _tickTime;

private:

};

template<class FunctionObject>
Alarm<FunctionObject>::Alarm(const FunctionObject& fn)
    : StopWatch(), _delegate(fn), _tickTime(1.0) { }

template<class FunctionObject>
Alarm<FunctionObject>::Alarm(double tickTime, const FunctionObject& fn)
    : StopWatch(), _delegate(fn), _tickTime(tickTime) { }

template<class FunctionObject>
Alarm<FunctionObject>::~Alarm() {
    if(_isRunning) Stop();
}

template<class FunctionObject>
FunctionObject Alarm<FunctionObject>::Tick() {
    if(IsRunning() == false) return _delegate;

    if(GetElapsedTimeInSeconds() >= _tickTime) {
        Reset();
        _delegate();
    }
    return _delegate;
}

#endif

CStopwatch.h

#ifndef CSTOPWATCH_H
#define CSTOPWATCH_H

#include "ADTtime.h"

class StopWatch : public ADTTime {

public:

    StopWatch();
    virtual ~StopWatch();

    void Start();
    void Restart();
    void Stop();
    void Reset();

    virtual void CalculateElapsedTime();

    virtual double GetElapsedTimeInSeconds();
    virtual double GetElapsedTimeInMilliseconds();

protected:

private:

};

#endif

CStopwatch.cpp

#include "CStopwatch.h"

StopWatch::StopWatch() : ADTTime() {
    /* DO NOTHING. ALL INITIALIZATION HAPPENS IN BASE CLASS */
}
StopWatch::~StopWatch() {
    _startTime = -1;
    _endTime = -1;
    _deltaTime = -1.0;
    _isRunning = false;
}

void StopWatch::Start() {
    if(_isRunning == true) return;
    _startTime = clock();
    _isRunning = true;
}
void StopWatch::Stop() {
    if(_isRunning == false) return;
    _isRunning = false;
    CalculateElapsedTime();
}
void StopWatch::Restart() {
    Reset();
    Start();
}
void StopWatch::Reset() {
    Stop();
    _startTime = 0;
    _endTime = 0;
    _deltaTime = 0.0;
}
void StopWatch::CalculateElapsedTime() {
    _endTime = clock();
    _deltaTime = difftime(_startTime, _endTime);
}

double StopWatch::GetElapsedTimeInSeconds() {
    CalculateElapsedTime();
    return -ADTTime::GetElapsedTimeInSeconds();
}
double StopWatch::GetElapsedTimeInMilliseconds() {
    CalculateElapsedTime();
    return -ADTTime::GetElapsedTimeInMilliseconds();
}

ADTTime.h

#ifndef ADTTIME_H
#define ADTTIME_H

#include <ctime>

class ADTTime {

public:

    clock_t GetStartTime() const;
    clock_t GetStartTime();

    double GetStartTimeInSeconds() const;
    double GetStartTimeInSeconds();

    clock_t GetEndTime() const;
    clock_t GetEndTime();

    double GetEndTimeInSeconds() const;
    double GetEndTimeInSeconds();

    virtual double GetElapsedTimeInSeconds();
    virtual double GetElapsedTimeInMilliseconds();

    virtual void CalculateElapsedTime()=0;

    bool IsRunning() const;
    bool IsRunning();

    virtual void Start()=0;
    virtual void Restart()=0;
    virtual void Stop()=0;
    virtual void Reset()=0;

    ADTTime();
    virtual ~ADTTime();

protected:

    bool _isRunning;
    clock_t _startTime;
    clock_t _endTime;
    double _deltaTime;

private:

};

#endif

CADTTime.cpp

#include "ADTtime.h"

clock_t ADTTime::GetStartTime() const {
    return _startTime;
}
clock_t ADTTime::GetStartTime() {
    return static_cast<const ADTTime&>(*this).GetStartTime();
}

double ADTTime::GetStartTimeInSeconds() const {
    return static_cast<double>((_startTime / CLOCKS_PER_SEC));
}
double ADTTime::GetStartTimeInSeconds() {
    return static_cast<const ADTTime&>(*this).GetStartTimeInSeconds();
}

clock_t ADTTime::GetEndTime() const {
    return _endTime;
}
clock_t ADTTime::GetEndTime() {
    return static_cast<const ADTTime&>(*this).GetEndTime();
}

double ADTTime::GetEndTimeInSeconds() const {
    return static_cast<double>((_endTime / CLOCKS_PER_SEC));
}
double ADTTime::GetEndTimeInSeconds() {
    return static_cast<const ADTTime&>(*this).GetEndTimeInSeconds();
}

double ADTTime::GetElapsedTimeInSeconds() {
    return _deltaTime / CLOCKS_PER_SEC;
}
double ADTTime::GetElapsedTimeInMilliseconds() {
    return _deltaTime;
}

bool ADTTime::IsRunning() const {
    return _isRunning;
}
bool ADTTime::IsRunning() {
    return static_cast<const ADTTime&>(*this).IsRunning();
}

ADTTime::ADTTime() : _isRunning(false), _startTime(-1), _endTime(-1), _deltaTime(-1.0) { }

ADTTime::~ADTTime() {
    _isRunning = false;
    _startTime = -1;
    _endTime = -1;
    _deltaTime = -1.0;
}

答案 2 :(得分:0)

由于您在Windows操作系统上运行,我不明白您为什么要重新发明轮子?

    CComPtr<IReferenceClock> pReferenceClock;

    HRESULT hr = CoCreateInstance( CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, IID_IReferenceClock, (void**)&pReferenceClock );

    hr = pReferenceClock->AdviseTime( ... );

    // or, hr = pReferenceClock->AdvisePeriodic( ... );

一旦你完成,

hr = pReferenceClock->Unadvise( adviseCookie );