作者dirofan (dadssada)
看板C_and_CPP
标题Re: [问题] 我应该直接问音乐游戏的计时器该怎麽做 …
时间Sat Apr 25 23:37:27 2009
不建议采用回圈一直检查时间到了没,不但不准而且相当浪费系统资源。
既然你都已经把时距算出来了,那就好办,小弟提供几种解法。
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
1F:推 crazytea:感谢 我试试看..... 04/26 22:10