Re: [問題] 我應該直接問音樂遊戲的計時器該怎麼做 …
不建議採用迴圈一直檢查時間到了沒,不但不準而且相當浪費系統資源。
既然你都已經把時距算出來了,那就好辦,小弟提供幾種解法。
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
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章