看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《turtle314 (會彈吉他屌屁)》之銘言: : 遇到的問題: (題意請描述清楚) 各位鄉民不好意思我又來了,上次PO時間的問題 : 我想有可能是因為每台電腦所算出的幀數不同而讓計數器有點差異。 : (因為連計數器兩台同時進行都會有這種問題@@,只好把問題歸咎到這) : 希望得到的正確結果:算出每台電腦幀數後,該如何和程式更新時間做搭配, : 讓每台電腦都是用FPS 60/s 或其他數字來做運算,應該就可以讓程式更新速度一樣。 這問題很簡單 我不知道為什麼沒人講到重點 如果要讓每台電腦固定在 FPS 60 意指固定 16.66 msec 畫出一張 frame 然而不同電腦畫出一張 frame 的速度不同 所以你要做的就是畫完一張 frame 後 使用 Sleep 暫停一小段時間 好讓畫每個 frame 所花的時間大約是 17msec 以下是使用這個方法的程式碼: while(...){ DWORD frame_start = GetTickCount(); // game update here updateGame(); render(); ... // calculate spent time DWORD spent_msec = GetTickCount() - frame_start; // sleep until 17msec is used if(spent_msec < 17) Sleep(17 - spent_msec); } 但是呢,這樣做並不是好方法 首先一個技術上的問題是 GetTickCount 誤差約在 10msec~16msec 左右 (from MSDN) 這和我們要求每張 frame 間隔 17msec 相比,實在是太大的誤差。 上面的問題可以用 QueryPerformanceCounter 來解決 不過我們會面臨另一個問題:如果有些人電腦就是太慢 導至它們每張 frame 的處理時間會超過 17msec 呢? 也許我們可以改成固定 30 frame/sec 但目前的遊戲大部份不是這樣處理的 (同樣地,跑不到30fps的人也會產生問題) 而是採用不固定 fps 的方式 把「畫出上一張 frame 的時間」傳進 gameUpdate 當中 也就是像這樣: DWORD spent_msec = 0; while(...){ DWORD frame_start = GetTickCount(); updateGame(spent_msec); render(); spent_msec = GetTickCount() - frame_start; } 而在 updateGame 中要跟據上一張 frame 花的時間 去更新遊戲中各元件 (以你的例子來說就是音符) 的位置 void updateGame(DWORD spent_msec) { // 計算音符的位置 // 新位置 = 舊位置 + 音符速度 * 時間 note.position += note.velocity * 0.001 * spent_msec; // ... } 理論上用 QueryPerformanceCounter 會好一點 但使用起來會有一些其它考量 (在多核心 CPU 上,BIOS 的 bug 可能會導致它回傳意料外的結果,詳見 MSDN) 簡單起見我還是用 GetTickCount 來示範 以上. -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.32.15.163
yauhh:水 10/29 12:00
final01:在real time的書裡學過 ? 10/29 12:22
wendly777:使用timeBeginPeriod(1),timeGetTime()的誤差會小於1ms 10/29 14:28
wendly777:QueryPerformanceCounter是用來算需求遠小於1ms的情況 10/29 14:29
littleshan:感謝樓上補充 10/29 14:58
VictorTom:推:) 10/29 15:47