hgimg3の待ち時間
ZAP 2013/8/2(Fri) 23:39:24|NO.56080
現在、hgimg3でゲームを作成しています。
メインループ中のウェイトとして、
hgsync 17 を入れて、約60fpsの描画速度を維持するようプログラムしているのですが、
処理量に応じて動作が重くなっているように感じられます。
試しに同じプログラムで「hgsync 1」としてみると75fpsくらいになるので、
ループ中の処理が間に合わずに処理オチしているわけではないようです。
レファレンスによれば、
標準のawait命令は「前回waitした時間からの待ち時間を指定します。」
とありますが、
hgsyncは「valで指定した時間(ms)だけウェイトを取ります。」
となっています。
これはつまり、前回のhgsyncからの時間ではなく、単純に指定した時間だけ
ウェイトを取っている、ということなのでしょうか?
そうだとした場合、ゲームの速度を一定にするためには、
1ループにかかった時間を計測し、その差分だけウェイトを取るといった処理を
自前で実装するしかないのでしょうか?
暇人 2013/8/3(Sat) 00:58:39|NO.56085
>これはつまり、前回のhgsyncからの時間ではなく、単純に指定した時間だけ
> ウェイトを取っている、ということなのでしょうか?
そこまでは酷くないがメイン処理で時間食うと時間待ちの誤差か何かが増える感じ
hgimg3の場合いまだにawaitは精度が低いままなのでhgsyncの代わりに使う事も出来ない
>1ループにかかった時間を計測し、その差分だけウェイトを取るといった処理を
> 自前で実装するしかないのでしょうか?
なるべく安定させたいならそうなる
その時もhgsyncでのウェイトは使えない
//FPS固定取得モジュール
#module
#uselib "winmm.dll"
#cfunc _timeGetTime "timeGetTime"
#func _timeBeginPeriod "timeBeginPeriod" sptr
#func _timeEndPeriod "timeEndPeriod" sptr
#uselib "KERNEL32.DLL"
#func global _Sleep "Sleep" sptr
#deffunc timeEndPeriod onexit //タイマー精度を戻す(終了時に自動で呼びだされる)
if tbp {_timeEndPeriod tbp}
return
#deffunc SetFps double fps
if tbp=0{tbp=1 : _timeBeginPeriod tbp} //タイマー精度変更
f_tim=1000.0/fps //1フレームの時間
ms_tim=_timeGetTime() //スタート時間(d3timer()-ms_timでスタートからの時間にする)
fs_tim=0.0 //フレームスタート時間
return f_tim
#deffunc GetFps var fps
to=t
fps_cnt+
fs_tim+f_tim //1フレームの時間を足して次フレームスタート時間にする
await 0//Sleepはawaitの代わりにならないので必ず何処かでawaitが必要
sms=fs_tim-(_timeGetTime()-ms_tim) //次フレームスタート時間からスタートからの時間を引いてスリープ時間にする(結果が負数なら1フレームの時間を越えた)
if sms < 0 {fs_tim-sms} //1フレームの時間以上使用したからオーバー分をフレームスタート時間に加算
_Sleep limit(sms,0,f_tim+1) //小数点以下のスリープは出来ないから最大スリープ時間をf_tim+1にする
t=_timeGetTime()/1000
if t ! to {fps=fps_cnt:fps_cnt=0}
return int(f_tim-sms)
#global
//モジュールここまで
#include "hgimg3.as"
hgini
setfont 16,16,12,1 ; font Tex select(cx,cy,px,mode)
texload dir_exe+"\\sample\\hgimg3\\fontchr.bmp" ; フォントテクスチャの登録
addxfile m_xmodel,dir_exe+"\\sample\\hgimg3\\font_a.x" ; モデルを読み込む
regobj obj, m_xmodel ; オブジェクトの登録
clscolor $80 ; 背景色の設定
//使用サンプル
//FPSを設定
SetFps 60
*rep
repeat 100000 //適当な負荷をかける
temp=cnt
loop
stick key,$3ff
if key&128 : goto *owari
if key&4 : addpos HGOBJ_CAMERA, -0.2, 0.0
if key&1 : addpos HGOBJ_CAMERA, 0.2, 0.0
if key&2 : addpos HGOBJ_CAMERA, 0.0, 0.2
if key&8 : addpos HGOBJ_CAMERA, 0.0, -0.2
addang obj,0,0.05,0
hgdraw ; 描画
fprt "fps"+fps+" ms"+ms,8,8
GetFps fps //指定FPSになるようにawaitして実際のFpsを返す
ms=stat //statにGetFps抜けてからGetFps実行時までの時間をmsで返す
hgsync 0 ; 時間待ちを0に指定
goto*rep
*owari
end
後はモニターのリフレッシュレートに合わせる方法
mod_d3d9vsync(ティアリングを無くしFPS安定化)の更新と、ヘルプ
http://hsp.tv/play/pforum.php?mode=pastwch&num=53549
暇人 2013/8/3(Sat) 01:02:22|NO.56086
> repeat 100000 //適当な負荷をかける
自分の環境だと、これでmsが7前後
16を超えないぐらいの回数にしてテストしてください
ZAP 2013/8/3(Sat) 01:57:38|NO.56089
>暇人さま
ありがとうございます!
原因を教えて頂いたうえにモジュールまで提示して頂いて、たいへん助かりました。
作成中のゲームに組み込んでみたところ、きれいに60fpsで動作するようになりました。
処理速度が気になりだしてからずっと、いったいプログラムの何処がボトルネックに
なっているのか探しまくっていたのですが、結局判らずに困っていたところでした。
仰るとおり、確かにhgimg3でのawaitの精度もよくないようで、
hgsetreq SYSREQ_DEFTIMER 1
でawaitを使うように設定したりしてもみたのですが、余計にFPSが不安定になりました。
せっかくここでタイマーを選べるようになっているのに・・・
開発側でhgimg3を手入れする機会があるのなら、ここは是非とも改善をお願いしたいところですね。
(もうhgimg4に移行するから更新はないのかもしれませんが、最終形として・・・)
暇人 2013/8/3(Sat) 02:52:17|NO.56090
ちょっと補足
hgimg3の場合
> await 0//Sleepはawaitの代わりにならないので必ず何処かでawaitが必要
は無い方が良いかも(hgimg3はhgsyncでも割り込み受け付けるので)
on系やmousewを使用し無いなら影響は無いと思うが・・・
後コメント間違い
> GetFps fps //指定FPSになるようにawaitして実際のFpsを返す
awaitじゃ無くてSleep
ZAP 2013/8/3(Sat) 10:08:56|NO.56098
>暇人さま
補足ありがとうございます。
当方で試したところ、
>await 0//Sleepはawaitの代わりにならないので必ず何処かでawaitが必要
の行をコメントアウトしたら、逆にFPSが45程度と不安定になったので、
存置しておいたほうが良さそうです。
とにかく助かりました。
これで作成を続けられます。