c++ - 时间类问题

标签 c++ winapi timer

我正在设计一个时间类,它只会在预定义的时间后执行一个操作,但我仍然无法找到重置时间的方法。无论如何,是将时间重置为零还是暂时停止并恢复时间?

因此,我的目标是在每次满足条件 A 时重置时间,这样它就不会搞砸 delayTime 函数,它仍然保持以前的时间并最终导致错误的时间计算。

if ( condition A )
{
    if ( time.delayTime( 5.0f ) )
    {           
        doActionA();
    }
}

时间类.h

#ifndef _TIMECLASS_H_
#define _TIMECLASS_H_

#include <windows.h>


class TimeClass
{
public:
    TimeClass();
    ~TimeClass();
    bool delayTime( float second );
    float getSecond();
    void reset();

private:
    float getGameTime();

    float currentTime;
    UINT64 ticks;
    float time;
    float  timeAtGameStart;
    UINT64 ticksPerSecond;
};

#endif

时间类.cpp

#include "TimeClass.h"


TimeClass::TimeClass()
{
    // We need to know how often the clock is updated
    if( !QueryPerformanceFrequency((LARGE_INTEGER *)&ticksPerSecond) )
        ticksPerSecond = 1000;

    // If timeAtGameStart is 0 then we get the time since
    // the start of the computer when we call GetGameTime()
    timeAtGameStart = 0;
    timeAtGameStart = getGameTime();
}


float TimeClass::getGameTime()
{
    // This is the number of clock ticks since start
    if( !QueryPerformanceCounter((LARGE_INTEGER *)&ticks) )
        ticks = (UINT64)timeGetTime();

    // Divide by frequency to get the time in seconds
    time = (float)(__int64)ticks/(float)(__int64)ticksPerSecond;

    // Subtract the time at game start to get
    // the time since the game started
    time -= timeAtGameStart;

    return time;
}


bool TimeClass::delayTime( float second )
{
    currentTime = getGameTime();
    static float totalTime = second + getGameTime();

    if ( currentTime >= totalTime )
    {
        totalTime = second + getGameTime();
        return true;
    }
    else
    {
        return false;
    }
}


float TimeClass::getSecond()
{
    currentTime = getGameTime();
    static float totalTime = 1 + getGameTime();

    if ( currentTime >= totalTime )
    {
        totalTime = 1 + getGameTime();
        return currentTime;
    }
    else
    {
        return currentTime;
    }
}


void TimeClass::reset()
{
    timeAtGameStart = 0;
    timeAtGameStart = getGameTime();
}


TimeClass::~TimeClass()
{
}

最佳答案

标准库

如前所述,只需使用 std::chrono::high_resolution_clock .如果您使用 Visual C++ 编译器,则会有一个实际的 bug report关于 high_resolution_clock 的分辨率,它与 QueryPerformanceCounter 相同。

示例

auto t1 = std::chrono::high_resolution_clock::now();
// Do something
auto t2 = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1);
double dt = duration.count();

时间类

您现在面临的主要问题是您使用的是静态变量。您正在寻找一种方法来从 delayTime 之外的另一个函数重置静态变量。如果你会引入成员变量来摆脱静态变量,它会让事情变得容易得多(注意:函数中的静态变量是不好的做法,因为它们持有状态 => 不利于多线程)。那么像这样的事情呢:

class Event {
    std::chrono::high_resolution_clock::time_point lastEventOccurred;
    double timeBetweenEvents;
public:
    Event(double timeBetweenEvents)
       : timeBetweenEvents(timeBetweenEvents)
       , lastEventOccurred(std::chrono::high_resolution_clock::now()) { }

    bool ready() {
       auto currentTime = std::chrono::high_resolution_clock::now();
       auto elapsedTime = std::chrono::duration_cast<std::chrono::duration<double>>(currentTime - lastEventOccurred).count();

       if(elapsedTime > timeBetweenEvents) {
           reset();
           return true;
       } else
           return false;
    }

    void reset() {
       lastEventOccurred = std::chrono::high_resolution_clock::now();
    }
};

用法:

Event evtDelay = Event(5.0);

if(condition A) {
    if(evtDelay.ready()) {
        doActionA();
    }
} else if(condition B) {
    evtDelay.reset();
}

另一种方法是使用捕获状态和更新方法。如我所见,您正在将其用于游戏,因此可以在游戏的更新方法中完成更新。假设事件有一个类似 {Active, Inactive} 的状态和一个耗时的成员,每次调用更新时,如果状态为事件,则添加自上次更新调用以来耗时。因此,就绪函数只会检查耗时是否大于定义的阈值。

class Event {
    std::chrono::high_resolution_clock::time_point lastUpdateCall;
    double timeBetweenEvents;
    double elapsedTime;
    bool active;
public:
    Event(double timeBetweenEvents)
       : timeBetweenEvents(timeBetweenEvents)
       , lastUpdateCall(std::chrono::high_resolution_clock::now()) 
       , elapsedTime(0.0) 
       , active(true) { }

    bool ready() {
       return elapsedTime >= timeBetweenEvents;
    }

    void reset() {
       elapsedTime = 0.0;
    }

    void setActive(bool state) { 
       active = state; 
    }

    void update() {
       auto currentTime = std::chrono::high_resolution_clock::now();

       if(active) {
          auto dt = std::chrono::duration_cast<std::chrono::duration<double>>(currentTime - lastUpdateCall).count();
          elapsedTime += dt;
       }

       lastUpdateCall = currentTime;
    }
};

关于c++ - 时间类问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19180218/

相关文章:

c++ - 是否有 winapi 调用可以在控制台中设置颜色,如 'color xx' 命令?

c - 如何将 win32 WndProc 包装到 C++ 类中?

c++ - C++14 是否要求删除表达式必须调用 `void operator::delete(void*, std::size_t)` 而不是 `void::operator delete(void*)` ?

c++ - 在 std::remove_if 执行期间遍历容器是否安全?

winapi - Windows 文件历史记录 API : Adding Include Rule

组合框上的 C# 10 秒定时器选择索引

java - 如何检测多次点击并最终在 Android 应用程序中仅触发一次更新

swift - 如何在 Swift 中设置定时器

c++ - c++ 中 vector 的 bad_alloc 异常

c++ - 为什么用 `0x62A`字体打印字符 "Calibri",而字符 `0x660E`不是?