0

假设我有这个功能:

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

我想要一个计时器类,使我能够在一定时间后运行该功能,就像这样。

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

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

提前致谢。

4

4 回答 4

2

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

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

于 2013-08-30T10:58:38.317 回答
0

您可以通过自由使用 Functor 委托对象和模板来达到预期的效果:

报警器.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();
}

ADT时间.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;
}
于 2013-08-30T13:17:28.900 回答
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 );
于 2013-08-30T13:48:17.283 回答
0

您可以实现一个简单(可能有点粗糙)的函数,该函数在指定的毫秒数后触发一次性事件,如计时器,使用std::threadstd::chrono设施

像这样的东西:

void doAfter( const std::function<void(void)>& f,
    size_t intervalMs )
{
    std::thread t{[f, intervalMs] () -> void
        {
            auto chronoInterval = std::chrono::milliseconds( intervalMs );
            std::this_thread::sleep_for( chronoInterval );
            f();
        }
    };
    // You can either `t.detach()` the thread, or wait to `join` it in main
}
于 2021-09-05T22:23:09.193 回答