きちんと同期を取ってみよう


必要なもの

この講座では、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 は 常に一定の時間対速度比で上昇していきます。
この値を参照することにより、一定の速さで処理を行うことができます。

以上、「きちんと同期を取ってみよう」でした。


HSP講座に戻る