[英]Handling an update loop using C++ Chrono?
我對新的C ++ chrono庫肯定有點失落。
這里我有一個更新循環。 它運行兩個操作:
engine.Update()
engine.Render()
這些都是長期操作,而且很難說它們有多長。
因此,我們測量他們花了多長時間,然后進行一些計算並找出在調用渲染之前逐漸調用更新的最佳方法。
為此,我正在使用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();
}
主要問題是:我的mDeltaTime總是很小。 它基本上停留在幾乎無限的循環中。 這是因為kMaxDeltatime非常小,但如果我的目標是每秒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?
我很抱歉這些混亂的人。 我覺得這個計時庫是個白痴。 大多數幫助網站,或參考資料,甚至直接代碼本身都非常令人困惑,無法閱讀和理解我正在應用它。 我非常歡迎指向我應該如何搜索解決方案或代碼的指針!
編輯:Joachim指出std :: min / max工作正常毫秒! 更新了代碼以反映變化。
使用std::chrono
,應盡可能避免轉換持續時間或將持續時間轉換為原始整數值。 相反,你應該堅持使用自然持續時間並利用持續時間類型提供的類型安全性。
以下是一系列具體建議。 對於每個推薦,我將引用原始代碼的行,然后顯示我將如何重寫這些行。
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!
沒有理由用手動轉換常量進行這種計算。 相反,你可以這樣做:
typedef duration<long,std::ratio<1,60>> sixtieths_of_a_sec;
constexpr auto kMaxDeltatime = sixtieths_of_a_sec{1};
frameTime = duration_cast<milliseconds>(Clock::now() - mLastEndTime); // Is this the best way to get the delta time, with a duration cast?
您可以將值保留為其本機類型:
auto newEndTime = Clock::now();
auto frameTime = newEndTime - mLastEndTime;
mLastEndTime = newEndTime;
while (frameTime.count() > 0) // Is this the best way to measure greater than 0 milliseconds?
而是使用:
while (frameTime > milliseconds(0))
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?
最好編寫始終使用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);
要么:
auto milliseconds = mDeltaTime/milliseconds(1);
要獲得delta,您應該執行以下操作:
typedef std::common_type<decltype(frameTime),decltype(kMaxDeltatime)>::type common_duration;
auto mDeltaTime = std::min<common_duration>(frameTime, kMaxDeltatime);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.