Re: [問題] 我應該直接問音樂遊戲的計時器該怎麼做 …

看板C_and_CPP (C/C++)作者 (dadssada)時間16年前 (2009/04/25 23:37), 編輯推噓1(100)
留言1則, 1人參與, 最新討論串1/1
不建議採用迴圈一直檢查時間到了沒,不但不準而且相當浪費系統資源。 既然你都已經把時距算出來了,那就好辦,小弟提供幾種解法。 1.單純的讓它sleep(時距),再做事,但重點在於你的sleep要能夠精確到milli甚至micro 但是正常情況下,Windows的sleep並不能做到這麼準,你可以參考黑暗執行緒的說明 http://blog.darkthread.net/blogs/darkthreadtw/archive/2007/03/29/673.aspx 但是這種做法不能跨平台,你可以考慮用select()來做,網路上很多範例 { struct timeval tval; tval.tv_sec = 0; tval.tv_usec = 10; select(0,NULL,NULL,NULL,&tval); } 2.更進階的操作,你可以參考boost asio裡的timer,還可以分為async及sync兩種用法 應該是最優雅的寫法,但殺雞要不要用牛刀就看你自己了 http://www.boost.org/doc/libs/1_38_0/doc/html/boost_asio/tutorial.html 如果你的音樂會mix多軌在做播放,用sleep/select的方式會需要比較多threads,但如 果採用asynchronous的方式,可以一個thread就能解決,但相對也比較複雜。 不過,要精準播放audio不是一件那麼容易的事情,就算你能夠擁有一個很準的timer,在 系統層/硬體層都還有許多難關要克服,才能處理的很漂亮。 不過一般的小軟體應該不會碰到這些問題就是了。 ※ 引述《crazytea (............)》之銘言: : 其實前面的碼表問題本來是希望能夠自己解決, : 沒想到問的詞不達意還無法解決問題 囧 : 所以就直接問了! : 音樂遊戲一定要藉由精準的時間判定來播放botton : 該在幾秒案就該在幾秒按 : 雖然拍子跟秒數之間有公式可以算(bpm) : 例如:150 bpm (即 1 分鐘 150拍 ) : 但是算到後來一拍的時間也是幾百 ms : 要如何計算從音樂開始播放後 : 每隔固定時間(拍子)播放botton : 是我現在的瓶頸~~ : 我有下載跳舞機模擬器( stepMania ) 的原始碼來看, : 但是由於程式過於龐大, : 目前只針對timeGetTime()尋找整個專案 : 找到相關程式碼如下: : static bool g_bTimerInitialized; : static DWORD g_iStartTime; : static void InitTimer() : { : if( g_bTimerInitialized ) : return; : g_bTimerInitialized = true; : timeBeginPeriod( 1 ); : g_iStartTime = timeGetTime(); : } : int64_t ArchHooks::GetMicrosecondsSinceStart( bool bAccurate ) : { : if( !g_bTimerInitialized ) : InitTimer(); : int64_t ret = (timeGetTime() - g_iStartTime) * int64_t(1000); : if( bAccurate ) : { : ret = FixupTimeIfLooped( ret ); : ret = FixupTimeIfBackwards( ret ); : } : return ret; : } : uint64_t ArchHooks::FixupTimeIfLooped( uint64_t usecs ) : { : static uint64_t last = 0; : static uint64_t offset_us = 0; : /* The time has wrapped if the last time was very high and the current time is : very low. */ : const uint64_t i32BitMaxMs = uint64_t(1) << 32; : const uint64_t i32BitMaxUs = i32BitMaxMs*1000; : const uint64_t one_day = uint64_t(24*60*60)*1000000; : if( last > (i32BitMaxUs-one_day) && usecs < one_day ) : offset_us += i32BitMaxUs; : last = usecs; : return usecs + offset_us; : } : uint64_t ArchHooks::FixupTimeIfBackwards( uint64_t usecs ) : { : static uint64_t last = 0; : static uint64_t offset_us = 0; : if( usecs < last ) : { : /* The time has moved backwards. Increase the offset by the amount we moved. : */ : offset_us += last - usecs; : } : last = usecs; : return usecs + offset_us; : } : 還是搞不懂他在幹啥? : 或是有更好的方法嗎? -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.43.78.61

04/26 22:10, , 1F
感謝 我試試看.....
04/26 22:10, 1F
文章代碼(AID): #19you-9U (C_and_CPP)
文章代碼(AID): #19you-9U (C_and_CPP)