スキップしない待機

概要

on~系の命令はstop, wait, await命令などが発生したタイミングで実行されます。
returnでジャンプ先から戻る時は、その次の行の命令から動作を再開します。

また、await命令で待機中にイベントが発生してジャンプすると、「待機」を中断して ジャンプ先に移動。戻ってくる時は次の行から動作を再開します。

つまり、await命令中にイベントが発生してジャンプすると、指定した通りの時間待機をしてくれません。

例えばタイピングゲームの場合だと、キーを押しっぱなしにしただけでfps値が上昇してしまうわけですからこれは困ります。
そこでこれを回避するモジュールを作成してみました。
今考えたらこんなの誰かが作っていそうな気がしますが…まあいいです。気にしたら負けな気がします。(´・ω・`)

モジュール付きサンプル

作成した命令:asleep
使い方や動作:await命令とほぼ同じ。
awaitと違うのはこの命令だけだとon~系の命令の割り込みが出来ません。
on~系での割り込みを使うためには、asleep命令直後にawait命令を入れます。

またループ内で await 0 の代わりとして使うことはできません。asleepだけでは操作が戻ってこなくなりますので注意してください。

サンプルではfps値と、実際にSleep命令に指定された待機時間が確認できます。 どんな操作をしても、待機時間を調整してfps値を安定させるようにしています。


// 
// [ Infomation ]
//  Name      : asleep命令のサンプル
//  SubName   : 
//  Version   : 
//  copyright : 
// 
// [ Update history ]
// 2013/07/27 : 1.0 : サンプル完成。
// 
// [ Comment ]
// 


#include "kernel32.as"
#include "winmm.as"




#module
// ------------------------------------------------------------ //
//
// 命  令  :一定の時間で待つ
//
// 引  数  :int waittime = 0~ : 待ち時間(1ms単位)
//
// 返り値  :stat
//           Sleep関数で実際に待機させた時間。
//
// 機能説明:プログラムの実行を一定時間だけ中断します。
//           
//           await命令と同様に、前回asleepした時間からの待ち時間を指定します。
//           これにより、描画速度の違いなどから時間が早く過ぎることを防止することができます。
//           リアルタイムで更新される画面などの速度を一定に保つ時に使用します。
//           
//           await 0 の代わりにはなりません。長い時間ループが起こる可能性がある場所には
//           waitかawait命令も入れるようにしてください。
//           
//           await命令と異なりon~系の命令によるジャンプを受けつけません。on~系の命令を使う際は、
//            asleep 16
//            await 0
//           などのようにawait命令を続けて記述してください。
//           
//           awati命令で待機中にon~系でジャンプすると待機が解除されてしまいます。
//           このためイベントが発生するとfps値が上昇する現象が起こります。
//           これに対してasleep命令ではon~系でのジャンプでも待機が解除されることはありません。
//           イベント発生によるfps値上昇を防ぐことができます。
//
// ------------------------------------------------------------ //
#deffunc asleep int waittime
	// 実際に待機する時間を算出
	timeGetTime
	tm = stat
	wt  = waittime - (tm - tm0)
	if wt<0 : wt = 0
	
	// 待機
	Sleep wt
	
	timeGetTime
	tm0 = stat
	return wt

#global

;---------------------------------------------------

#include "d3m.hsp"

#const LOGCNT 50

dim wts, LOGCNT
wtsid = 0

// 1ループにかける時間
waittime = 33	// 30 fps
;waittime = 16	// 60 fps
;waittime = 100

onkey gosub *key
k = 0

 
*main
	redraw 1

	// 待機
	asleep waittime
	wt = stat
	
	await 0
	redraw 0 : color 255, 255, 255 : boxf : color : pos 0,0
 
	frame++
	mes "frame : "+frame
	mes "hit : " + k
	mes "" + d3getfps() + " fps"


	// ウェイト時間表示
	wtsid++
	if wtsid >= LOGCNT : wtsid = 0
	wts(wtsid) = wt
	
	av=0.0
	wtmax=0
	wtmin=1000
	// 実際にSleep関数に指定された待機時間をグラフ表示
	pos 100,0
	repeat LOGCNT
		line ((double(ginfo_winx)-100)/LOGCNT)*cnt + 100, wts(cnt)*1
		av += double(wts(cnt))
		if wtmax < wts(cnt) : wtmax = wts(cnt)
		if wtmin > wts(cnt) : wtmin = wts(cnt)
	loop
	
	// 実際にSleep関数に指定された待機時間
	pos 0,100
	mes "wait時間 = " + wt + " msec"
	mes "wait平均 = " + (av/LOGCNT) + " msec"
	mes "wait max = " + wtmax + " msec"
	mes "wait min = " + wtmin + " msec"
	mes "max - min= " + (wtmax-wtmin) + " msec"

	goto *main

// キー入力イベント
*key
	k++
;	Sleep 5
	return

解説

この命令は内部でSleep命令を使用しています。必要な待機時間を計算して安定したfps値になるように待機させています。
また必要な待機時間を計算するためtimeGetTime命令も使用しています。
この2つの命令を使用するため最初にkernel32.asとwinmm.asをincludeしています。

ライセンス

NYSLです。
サンプルもモジュールも好きに使って下さい。

関連記事

  1. ファイルを分けて開発する 動機 HSPで作る時って普通は1個のファイルでガリガリ書いて...
  2. oncmd命令に関するお話 概要 HSPにはWindowメッセージを取得して割り込み実行...
  3. font命令の速度 概要 HSPのFONT命令はその昔「重いのでメインループ内で...
  4. HSP3でのデザインパターン 概要  ソフトウェア開発にはデザインパターン(設計パターン)...
  5. 再帰とローカル変数 調査環境   HSP3での再帰の実装について真面目に調べてみ...
  6. HSP3でのビットシフト 算術シフトって初めて聞きました  HSP3のビットシフトにつ...
  7. テキストデータの読み込み もくじ 新情報を加えたら量が増えてきたので目次を作りました。...