スキップしない待機
概要
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です。
サンプルもモジュールも好きに使って下さい。