使用C+处理更新循环+;时钟? 我肯定对新的C++计时库有点迷惑。

使用C+处理更新循环+;时钟? 我肯定对新的C++计时库有点迷惑。,c++,milliseconds,chrono,C++,Milliseconds,Chrono,这里我有一个更新循环。它运行两个操作: engine.Update() engine.Render() 这些都是很长的操作,很难说它们需要多长时间 因此,我们测量它们花费了多长时间,然后进行一些计算,并找出在调用render之前逐步调用update的最佳方法 为此,我使用C++11的Chrono功能。我选择它是因为它听起来很划算:更准确,更依赖于平台。我发现我遇到的问题比现在多 下面是我的代码,也是我的主要问题。无论是在这个问题上,还是在正确的操作方法上,都非常需要任何帮助 我在注释中将我的问

这里我有一个更新循环。它运行两个操作:

engine.Update()
engine.Render()
这些都是很长的操作,很难说它们需要多长时间

因此,我们测量它们花费了多长时间,然后进行一些计算,并找出在调用render之前逐步调用update的最佳方法

为此,我使用C++11的Chrono功能。我选择它是因为它听起来很划算:更准确,更依赖于平台。我发现我遇到的问题比现在多

下面是我的代码,也是我的主要问题。无论是在这个问题上,还是在正确的操作方法上,都非常需要任何帮助

我在注释中将我的问题直接标记在有问题的行旁边,我将在下面再次重复

头文件:

class MyClass
{
private:
    typedef std::chrono::high_resolution_clock Clock;
    Clock::time_point mLastEndTime;
    milliseconds mDeltaTime;
}
简化的更新循环

// time it took last loop
milliseconds frameTime;
// The highest we'll let that time go. 60 fps = 1/60, and in milliseconds, * 1000
const milliseconds kMaxDeltatime((int)((1.0f / 60.0f) * 1000.0f)); // It's hard to tell, but this seems to come out to some tiny number, not what I expected!
while (true)
{
    // How long did the last update take?
    frameTime = duration_cast<milliseconds>(Clock::now() - mLastEndTime); // Is this the best way to get the delta time, with a duration cast?
    // Mark the last update time
    mLastEndTime = Clock::now();

    // Don't update everything with the frameTime, keep it below our maximum fps.
    while (frameTime.count() > 0) // Is this the best way to measure greater than 0 milliseconds?
    {
        // Determine the minimum time. Our frametime, or the max delta time?
        mDeltaTime = min(frameTime, kMaxDeltatime);

        // Update our engine.
        engine->Update((long)mDeltaTime.count()); // From here, it's so much easier to deal with code in longs. Is this the best way to shove a long through my code?

        // Subtract the delta time out of the total update time 
        frameTime -= mDeltaTime;
    }
    engine->Render();
}
//上次循环所用的时间
毫秒帧时间;
//我们会让这段时间过去的。60 fps=1/60,以毫秒为单位*1000
常量毫秒kmaxdelatime((int)((1.0f/60.0f)*1000.0f));//这很难说,但这似乎是一个很小的数字,不是我所期望的!
while(true)
{
//上次更新花了多长时间?
frameTime=duration_cast(Clock::now()-mLastEndTime);//这是使用duration cast获取增量时间的最佳方法吗?
//标记上次更新时间
mLastEndTime=Clock::now();
//不要使用帧时更新所有内容,将其保持在最大fps以下。
while(frameTime.count()>0)//这是测量大于0毫秒的最佳方法吗?
{
//确定最短时间。我们的帧时间,还是最大增量时间?
mdelatime=min(帧时间,kmaxdelatime);
//更新我们的引擎。
引擎->更新((long)mdelatime.count());//从这里开始,用long处理代码就容易多了。这是在我的代码中插入long的最好方法吗?
//从总更新时间中减去增量时间
帧时间-=mdelatime;
}
引擎->渲染();
}
主要问题是: 我的时间总是很短。它基本上被困在一个几乎无限的循环中。这是因为kmaxdelatime非常小,但是如果我的目标是每秒60帧,我不是计算了正确的毫秒吗

以下是上面列出的所有问题:

const milliseconds kMaxDeltatime((int)((1.0f / 60.0f) * 1000.0f)); // It's hard to tell, but this seems to come out to some tiny number, not what I expected!

frameTime = duration_cast<milliseconds>(Clock::now() - mLastEndTime); // Is this the best way to get the delta time, with a duration cast?

while (frameTime.count() > 0) // Is this the best way to measure greater than 0 milliseconds?

engine->Update((long)mDeltaTime.count()); // From here, it's so much easier to deal with code in longs. Is this the best way to shove a long through my code?
const毫秒kmaxdelatime((int)((1.0f/60.0f)*1000.0f));//这很难说,但这似乎是一个很小的数字,不是我所期望的!
frameTime=duration_cast(Clock::now()-mLastEndTime);//这是获得增量时间的最佳方法吗?有持续时间的演员阵容吗?
while(frameTime.count()>0)//这是测量大于0毫秒的最佳方法吗?
引擎->更新((长)mdelatime.count());//从这里开始,用long处理代码就容易多了。这是在我的代码中插入长代码的最好方法吗?
我很抱歉搞混了,伙计们。我觉得有了这个时空图书馆我就像个白痴。大多数的帮助站点,或者参考资料,甚至是直接代码本身,阅读和理解我所应用的内容都非常混乱。我应该如何搜索解决方案或代码的指针非常受欢迎

编辑:
Joachim指出std::min/max在毫秒内工作正常!更新代码以反映更改。

使用
std::chrono
时,应尽可能避免转换持续时间或将持续时间转换为原始整数值。相反,您应该坚持使用自然持续时间,并利用持续时间类型提供的类型安全性

以下是一系列具体建议。对于每个建议,我将引用您的原始代码行,然后展示如何重新编写这些行


没有理由使用手动转换常量进行此类计算。相反,您可以:

typedef duration<long,std::ratio<1,60>> sixtieths_of_a_sec;
constexpr auto kMaxDeltatime = sixtieths_of_a_sec{1};

而是使用:

while (frameTime > milliseconds(0))

最好编写始终使用
chrono::duration
类型的代码,而不是使用泛型整数类型,但如果您确实需要获得泛型整数类型(例如,如果您必须将
long
传递给第三方API),则可以执行以下操作:

auto mDeltaTime = ... // some duration type

long milliseconds = std::chrono::duration_cast<std::duration<long,std::milli>>(mDeltaTime).count();
third_party_api(milliseconds);
typedef std::common_type<decltype(frameTime),decltype(kMaxDeltatime)>::type common_duration;
auto mDeltaTime = std::min<common_duration>(frameTime, kMaxDeltatime); 
要获得增量,您应该执行以下操作:

auto mDeltaTime = ... // some duration type

long milliseconds = std::chrono::duration_cast<std::duration<long,std::milli>>(mDeltaTime).count();
third_party_api(milliseconds);
typedef std::common_type<decltype(frameTime),decltype(kMaxDeltatime)>::type common_duration;
auto mDeltaTime = std::min<common_duration>(frameTime, kMaxDeltatime); 
typedef std::common_type::type common_duration;
auto-mdelatime=std::min(帧时间,kmaxdelatime);

至于多次使用的
min
/
max
函数,很容易为它们创建简单的重载函数。@JoachimPileborg你能详细说明一下吗?你为什么有一个“忙循环”?“投票是邪恶的”。如果你想要一个延迟,为什么不在计时器上加个挡块呢?@MintyAnt哦,这是一个很好的理由,也是解决常见问题的常用方法。但这与处理器不能100%运行无关……不,kmaxdelatime的值是正确的(16)。我不知道你的程序为什么陷入循环。下面是我根据您的原始示例拼凑的一些代码,它按预期工作:我知道这已经过去很久了,但是std::common_类型调用不能在linux上使用clang++为我编译。它说“不存在名为“type”的成员”,这导致min调用也无法编译。我认为这与初始值设定项列表有关,使编译器出错。
engine->Update((long)mDeltaTime.count()); // From here, it's so much easier to deal with code in longs. Is this the best way to shove a long through my code?
auto mDeltaTime = ... // some duration type

long milliseconds = std::chrono::duration_cast<std::duration<long,std::milli>>(mDeltaTime).count();
third_party_api(milliseconds);
auto milliseconds = mDeltaTime/milliseconds(1);
typedef std::common_type<decltype(frameTime),decltype(kMaxDeltatime)>::type common_duration;
auto mDeltaTime = std::min<common_duration>(frameTime, kMaxDeltatime);