简体   繁体   English

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

[英]Making a timer that executes a function after a certain amount of time in milliseconds

Let's say I have this function: 假设我有这个功能:

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

And I want a timer class that enables me to run that function after a certain amount of time, Something like this. 我想要一个计时器类,使我能够在一段时间后运行该函数,就像这样。

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

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

Thanks in advance. 提前致谢。

If this is a game loop then one way is to keep of list of events that you want to happen some time in the future where you store a time and a pointer to the function you want to call. 如果这是一个游戏循环,那么一种方法是保留您希望在将来某个时间发生的事件列表,其中您存储时间和指向要调用的函数的指针。 (Or a std::function, or whatever). (或者std :: function,或者其他)。 Keep the list sorted by time so the soonest event is a the top of the list. 保持列表按时间排序,以便最快的事件是列表的顶部。

Then in your main game loop, every loop, check the top of the list to see if the time of that event has been reached yet and if it has pop the event and call the function. 然后在你的主游戏循环中,每个循环,检查列表的顶部,看看是否已经达到该事件的时间,以及它是否已弹出事件并调用该函数。

You can achieve the desired effect by the liberal use of Functor delegate objects and templates: 您可以通过自由使用Functor委托对象和模板来实现所需的效果:

CAlarm.h 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 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 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 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 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;
}

Since you are running on Windows OS, I don't understand why are you reinventing the wheel? 由于您在Windows操作系统上运行,我不明白您为什么要重新发明轮子?

    CComPtr<IReferenceClock> pReferenceClock;

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

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

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

and once you are done, 一旦你完成,

hr = pReferenceClock->Unadvise( adviseCookie );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM