HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2013
1124
ほむawaitを使わないFPSの制限について6解決


ほむ

リンク

2013/11/24(Sun) 16:09:42|NO.58437

await命令は使わずに、プログラムの中の一部の描画処理で
フレームレートを制限したいと考えています。

30FPS以上で動作していた場合は描画のみ30FPS(33msに一度)で行われるようにする予定です。

音楽ゲームを作っているので、プログラム全体のフレームレートを下げると
キー入力の時刻取得の精度が低くなってしまいます。

プログラム本体のフレームレートを下げずに、画面の描画のフレームレートだけを
制限する方法をご存知の方いましたら教えていただきたいです。
よろしくお願いします。


---これまでの経緯(飛ばしてもらっても構いません)

30FPSに制限するために、
前回の描画処理を行った時刻から33ms以上経っていれば
次の描画処理を行う、という形をとっていたのですが

実際にプログラムを動かしていたところ、40FPS程度で動作していたので
一度描画された次のループでは約25ms経過しているということになります。
これでは次のループで描画処理はスキップされて約50ms経過した2ループ目で
描画処理が行われてしまうことになり、結果的に20FPSで動作している時と
変わらない描画速度でカクカクになってしまいました。



この記事に返信する


きのよー

リンク

2013/11/24(Sun) 16:37:44|NO.58439

await命令を使わずに、ということを勝手にawait 33を使わないっていう解釈しをたけどあってるかな…?


stime=gettime(4)*3600000+gettime(5)*60000+gettime(6)*1000+gettime(7) fps=30//制限FPS *main buftime=ntime\1000//実測式FPSを出すための準備 ntime=gettime(4)*3600000+gettime(5)*60000+gettime(6)*1000+gettime(7) if ntime\1000<buftime:cunt=cunt2:cunt2=0 if ntime-otime>=1000/fps:gosub *draw await goto *main *draw //描画を似せてawaitで負荷をかける await 5 redraw 0 color 255,255,255 boxf color 0,0,0 buf=3000 buf2=buf/2 line cos(M_PI/buf2*(ntime\buf))*100+320,sin(M_PI/buf2*(ntime\buf))*100+240,cos(M_PI/buf2*(ntime\buf))*-100+320,sin(M_PI/buf2*(ntime\buf))*-100+240 pos 0,0 mes "算出式FPS:"+(1000/(ntime-otime)) mes "実測式FPS:"+cunt redraw 1 otime=ntime cunt2++ return

実際にFPS40になる理由がわからなかったけど、ストックの管理をしっかりすれば問題ない。
あと、必ずメインのgettime以外はgettimeを使わないこと。



掘木

リンク

2013/11/24(Sun) 16:55:46|NO.58441

FPSの制限ならば、本来流れがこうなるような気がします。

;T:1区画33msの区切り。 ;A:内部処理 ;B:描画処理 ; T|------|------|------|------|------|------|--- ... ; A|---| |---| |---| |---| |---| |---|---| |---| ... ; B |-| |-| |-| |-| |-| |-| ... ; ;time-tableの1区画に対して、その区画内で描画が一度も行われていなければ描画をする ;そうでなければ内部処理を行う。(描画処理の次は内部処理である必要がある)
図を単純に信用するとこんな感じでしょうか?

#uselib "winmm.dll" #cfunc timeGetTime "timeGetTime" #define WAITTIME 33 time1 = timeGetTime() *main repeat //-------------- // ここに内部処理 //-------------- await 1 time2 = timeGetTime() if ( time2 - time1 >= WAITTIME ){ time1 += ( time2 - time1 ) / WAITTIME * WAITTIME break } loop //-------------- // ここに描画処理 //-------------- goto *main
書いてる間にきのよーさんが書き込んでいた・・・。


実際の対処なしのプログラムの挙動が40FPSで、
その後対処を行ったのが20FPSに落ちたとのことですが、それだけ見ると
描画+内部処理で25msの負荷に対して、内部処理のみでも25msになっているように思えます。
本当に描画処理が除外できているのでしょうか。通常は描画処理のほうが重い気がするのですが。



暇人

リンク

2013/11/24(Sun) 18:15:30|NO.58443

gettime(7)は自分の環境だと16ms前後の精度しかなくてフレーム管理には使えない


#uselib "winmm.dll" #cfunc timeGetTime "timeGetTime" title "gettime(7)" screen 1,640,480,0,ginfo_wx2,ginfo_wy1 title "timeGetTime" gsel 0,1 await 100 repeat 100 pos (ginfo_cy>=450)*120+ginfo_cx,(ginfo_cy<450)*ginfo_cy a=gettime(7) await cnt b=gettime(7) mes "await "+cnt+"("+str((b-a+1000)\1000)+")" loop gsel 1,1 await 100 repeat 100 pos (ginfo_cy>=450)*120+ginfo_cx,(ginfo_cy<450)*ginfo_cy a=timeGetTime() await cnt b=timeGetTime() mes "await "+cnt+"("+str(b-a)+")" loop



ほむ

リンク

2013/11/24(Sun) 19:07:54|NO.58446

ありがとうございます。

>>きのよーさん
>await 33を使わないっていう解釈しをたけどあってるかな…?
awaitを使ってプログラム自体の進行速度を
遅くすることは避けたいのでメインループに新たにawait命令を
追加するようなことはしたくない、という意味です。

7行目では33ms経過したら描画処理、ということだと思いますが
私の今の状況を再現するためにメインループ中のFPSを40(8行目のawaitを25)に
して描画のawaitを無しに、制限FPSを30にすると
描画処理のFPSはやはり25になって
毎回1ループ描画がスキップされて同じ状況のように思えます。
書き換え方が間違っていたら本当にすみません。


>>掘木さん
わかりやすい図をありがとうございます。まさにその通りです。

>本当に描画処理が除外できているのでしょうか。
経緯のところに書いてある方法で描画処理をスキップした時は
内部上は50FPSくらいになります。
画面が更新されるのが毎秒20回なのでカクカクに見える、ということです。

スクリプトの挙動は求めていたものと同じようでした。
ありがとうございます。
肝心の描画処理へと移る仕組みがしっかりと理解できていないので
(13行目の WAITTIME * WAITTIME の意味など)
しばらく考えてみようと思います。

>>暇人さん
確かにスクリプトを実行してみると数値が後ろの値を越してしまってるのもありますね..
参考にさせていただきます。


質問文について
フレームレートという言葉の使い方を間違えていた気がします。
質問文ではフレームレートという言葉を
メインループ(キー判定や描画すべて含む)が1秒あたりにループする回数のことでも
使っていました。本来は1秒あたりの描画に関しての事を指すんですよね。
すみませんでした。

堀木さんのスクリプトを参考に、納得のいくものが作れる気がしたので
解決とさせていただきます。



ほむ

リンク

2013/11/24(Sun) 19:12:28|NO.58447

NO.58446 訂正です

きのよーさんへの返信
>描画処理のFPSはやはり25になって

FPSは20でした、すみません。



ほむ

リンク

2013/11/24(Sun) 19:38:27|NO.58448

連レスすみません。

>>掘木さん
>内部処理のみでも25msになっているように思えます。
描画処理を含めて40FPSだと、スキップするようにすれば
描画処理のフレームレートは20以上出るはずですよね..
(実際には25FPS程度でした)
動作がカクカクしていたのを見て勝手に頭の中で1回スキップされて50ms..と
考えて発言してしまいました。すみません


先ほどの返信内容も間違っていることになります
>画面が更新されるのが毎秒20回
毎秒20回というのは誤りでした。



ONION software Copyright 1997-2023(c) All rights reserved.