きちんと同期を取ってみよう
必要なもの
この講座では、DSOUNDEX.DLLを使用します。持っていない方は、ダウンロードしてください。
MIDI同期との違い
MIDI同期は、バックグラウンドでMIDIが鳴っていないと
使えませんでしたが、timer 命令を利用すればMIDIは不要です。
また、分解能の設定もできますので、MIDI同期より細かい単位の時間処理を
行うことができます。(MIDIのSMPTE同期は16分音符単位に固定です)
標準命令との違い
HSPにも gettime という命令がありますが、かなり精度が悪いため、
DSOUNDEX.DLLについてくる timer 命令を使用してみることにします。
プログラムを書くの。
同期を取るには、まず「テンポ」の設定が必要です。
リズム系ゲームを想定していますので、ここではBPMと分解能で速さを設定します。
メインループではタイマを常に監視し、処理を「時間に厳しく」実行しています。
このサンプルは割り込みではなく「ポーリング」なので、CPUパワーを
かなり消費します。さらに、ウィンドウがドラッグされたりすると、処理が止まります。
が、マウスを離すとちゃんとついてきます(コマ落ちはしますが・・・)。
フルスクリーンのゲームならこの辺の問題は発生しません。
#uselib "dsoundex.dll" #func timer timer $0 bpm=120 ;1分間の拍子数 div=64 ;分解能([div]分音符の細かさまで) dectime=240000/div timer:oldtime=stat:mpos=0 ;タイマの初期化 *MAIN opos=mpos : gosub *GETDT ;---フォアグラウンド処理 ;oposがmposに追いつくまで加算しながら、箱を移動する。 palcolor 248 repeat : if mpos=opos : break t=opos&(div-1):gosub *BOX opos+ loop palcolor 249:t=mpos&(div-1):gosub *BOX bar=mpos/div+1:bp=mpos*4/div&3+1 title "第 "+bar+"小節 / "+bp+"拍" ;---フォアグラウンド処理はここまで。 await 20 ;ここの値を変えても、コマ飛びが生じるだけで ;単位時間に対する移動量は変わりません(これが重要) goto *MAIN *GETDT ;時間を計測し、mpos を加算するルーチン timer:dt+=(stat-oldtime)*bpm:oldtime=stat if dt>dectime : repeat dt/dectime:dt-=dectime:mpos+:loop return *BOX : x=(t&7)*16 : y=(t/8)*16 : boxf x,y,x+14,y+14 : return
解説。
*GETDTを呼ぶと、mpos の値が変更されます。この mpos は、経過時間を
指定された分解能で処理した結果です。
mpos は 常に一定の時間対速度比で上昇していきます。
この値を参照することにより、一定の速さで処理を行うことができます。
以上、「きちんと同期を取ってみよう」でした。