トップページ > 記事閲覧
描画は60FPS、内部処理は60FPS以上で処理したい
名前:was-blue.0793 日時: 2020/08/05 17:53

初歩的な質問であるかもしれませんが、質問します。 描画処理を60(ないし120、30、144など任意の数値)FPSで固定しつつ、内部的な処理をPCが許す限り(例として秒間1000回以上)高速に行いたいです。 これは3Dのゲームで顕著ですが、一定以上のFPSで動かそうとすると表示されるオブジェクトなどがちらつく現象がみられるためです。 しかし、音楽ゲームなど内部的な処理をPCが許す限り高速に行いたいのですが、SetVSyncFlagで垂直同期を設定すると描画でちらつくか、内部処理が秒間で描画のFPSと同じ回数しか行えなくなるかのどちらかの問題が発生します。 例として以下の関数があり、Draw関数は秒間60回、Update関数はPCが許す限り何度でも呼び出したいです。 void Draw() { //something draw process } void Update() { //something update process } このことに関しまして、皆様の見識をお伺いしたいです。
メンテ

Page: 1 |

Re: 描画は60FPS、内部処理は60FPS以上で処理したい ( No.2 )
名前:管理人 日時:2020/08/06 00:58

すみません、一つ確認させてください > SetVSyncFlagで垂直同期を設定すると描画でちらつく というのは、 『SetWaitVSyncFlag( FALSE ); を実行して垂直同期信号を待たない設定にすると描画でちらつく』 ↑こちらの意味の認識で間違いないでしょうか?
メンテ
Re: 描画は60FPS、内部処理は60FPS以上で処理したい ( No.3 )
名前:ギウ 日時:2020/08/06 07:33

Update()の中でキー入力を何回でも取りたいとかでしょうか?
メンテ
Re: 描画は60FPS、内部処理は60FPS以上で処理したい ( No.4 )
名前:was-blue.0793 日時:2020/08/06 08:29

>>管理人さん その解釈で合っています。 垂直同期を待たないと画面がちらつき、待つと内部処理の回数が描画できる回数と同じ回数まで減ってしまいます。 >>ギウさん サンプルの提示ありがとうございます。 例えば音楽ゲームで、入力の取得は高速で行わないと判定に大きな支障が出るところ、垂直同期を待つ設定を切るだけだと 特に3Dオブジェクトを使う場合において致命的なほど画面がちらついたため、描画は60FPSに固定しつつ内部処理を高速に行う必要があります。
メンテ
Re: 描画は60FPS、内部処理は60FPS以上で処理したい ( No.5 )
名前:管理人 日時:2020/08/08 00:00

> その解釈で合っています。 ご返答ありがとうございます 了解です > 垂直同期を待たないと画面がちらつき、待つと内部処理の回数が描画できる回数と同じ回数まで減ってしまいます。 描画のスレッドと内部処理のスレッドを別々のスレッドにするという方法が良いかもしれません 描画のスレッドでは描画のみ行い、ScreenFlip で垂直同期信号待ちもするのでどんなに高速に処理されても 画面のリフレッシュレートと同じフレームレートとなります 内部処理のスレッドでは ScreenFlip は使用しないので垂直同期信号待ちも無く、PCの性能の許す限り フレームレートが上がります ただ、DXライブラリは複数のスレッドからDXライブラリの関数が呼ばれることを想定していませんので、 描画のスレッドでは描画・画像・画面関係の関数のみ使用して、 内部処理のスレッドでは描画・画像・画面関係の関数は一切呼ばないようにする必要があります ( 描画のスレッドが完全に止まっていて、描画・画像・画面関係の関数が二つのスレッドで同時に呼ばれる ことが絶対に無い、という状況でしたら内部処理のスレッドでも描画・画像・画面関係の関数を呼んでも大丈夫ですが… )
メンテ
Re: 描画は60FPS、内部処理は60FPS以上で処理したい ( No.6 )
名前:ギウ 日時:2020/08/08 08:10

>was-blue.0793 さん あ、サンプルを書いたのは私ではないです。 >管理人様 キー入力を更新するには、ProcessMessage を呼ばないといけないんでしたっけ? その場合、スレッドにしても大丈夫でしょうか。
メンテ
Re: 描画は60FPS、内部処理は60FPS以上で処理したい ( No.7 )
名前:was-blue.0793 日時:2020/08/08 17:21

>>管理人さん "内部処理"にはキーボードやゲームパッドの入力の受け取りが含まれ、そこでもDXライブラリの関数を使っているため、スレッドを分けることができません。 GetNowCount()関数などを使って最後に描画処理をした時間と現在の時間の差分を取り、差分が1/60秒以上になったら描画処理を行うという手法があります。 ClearDrawScreen()とScreenFlip()を呼ぶまで画面の表示が変わらなければ、この手法を使えそうですが……
メンテ
Re: 描画は60FPS、内部処理は60FPS以上で処理したい ( No.8 )
名前:名無 日時:2020/08/09 09:19

すみません。そもそも根本的な部分なのですが、 「音楽ゲームでPCのゆるす限り内部処理を行う」とありますが、 環境に応じてゲームの内部処理速度が変化するのは、ゲームとして破綻していると思うのですが。 リズムゲームにおいても、コンソールの内部処理は描画処理と同回数しか行われず、 判定に大きな支障が出るのは、むしろ一定にしないことだと思うのですが如何でしょうか。 また、描画処理を垂直同期を用いて行う場合、当然ながら「垂直同期の直後」に描画処理を行うことになります。 そのため、画面に表示される状態と内部の状態に差が発生します。 いくら判定が細かくても、画面表示が遅れては意味がない気がします。 (描画処理に必要な時間の予測でもできれば、話は別でしょうが) そのため、「ラグを減らすなら垂直同期なし」「公平性を保つなら垂直同期あり、もしくは処理速度一定」あたりがベストだと思います。
メンテ
Re: 描画は60FPS、内部処理は60FPS以上で処理したい ( No.9 )
名前:was-blue.0793 日時:2020/08/09 14:25

>>名無さん 当該音楽ゲームでは、ノートの判定を正しい時間とデバイスが操作された時間の差分を取り行っているため、内部処理と描画処理を同期させた場合は完全に正確なタイミングでノートを押すことが難しくなり、 またノートの完全に正確なタイミングをフレームに合うように補正することも意図的にノートの完全に正確なタイミングにズレを発生させることになりますので、 いずれにしてもゲーム性を損なってしまうものと考えています。 しかし、3Dオブジェクトを表示する処理で致命的にちらついてしまう現象が発生したため、 ちらつきを発生させず、判定を可能な限り厳密に行う(描画を60FPS、内部処理を可能な限り高速に行うのも1つの方法です)ことを実現しようとしています。
メンテ
Re: 描画は60FPS、内部処理は60FPS以上で処理したい ( No.10 )
名前:管理人 日時:2020/08/09 20:36

> ギウさん > キー入力を更新するには、ProcessMessage を呼ばないといけないんでしたっけ? > その場合、スレッドにしても大丈夫でしょうか。 私としては描画処理を別スレッドにして、キー入力判定などは DxLib_Init や DxLib_End, ProcessMessage などを呼ぶメインスレッドで行うイメージです > was-blue.0793さん > "内部処理"にはキーボードやゲームパッドの入力の受け取りが含まれ、そこでもDXライブラリの関数を使っているため、スレッドを分けることができません。 was-blue.0793さん的には『内部処理』を DxLib_Init 、DxLib_End などを呼ぶメインスレッドとは別のスレッドにするイメージでしょうか? 私としては現状のメインスレッドで行う処理から描画処理のみを別スレッドで行うイメージです メインスレッド( もともとあるスレッド )   DxLib_Init, DxLib_End の呼び出しや   LoadGraph, LoadSound を使ったファイルの読み込み   描画処理以外のメインループで行う処理全部を行う 描画のスレッド   メインスレッドから描画処理のみを抜き出したスレッド   ClearDrawScreen, DrawGraph や DrawExtendGraph や ScreenFlip など   描画に関わる処理のみを行う > GetNowCount()関数などを使って最後に描画処理をした時間と現在の時間の差分を取り、差分が1/60秒以上になったら描画処理を行うという手法があります。 案外こちらの方法で良いかもしれません 仮にこちらの手法にする場合、時間の計測はより正確な GetNowHiPerformanceCount を使用されることをお勧めします ( 1/60秒は 16.66666666...ミリ秒なのですが、GetNowCount で取得できるのはミリ秒の整数値なので、 16 か 17 を 1/60秒とする必要があり、1フレーム毎に 0.666666...ミリ秒のズレが発生してしまうので… ) > ClearDrawScreen()とScreenFlip()を呼ぶまで画面の表示が変わらなければ、この手法を使えそうですが…… SetDrawScreen( DX_SCREEN_BACK ); で描画先を裏画面にしていれば、ScreenFlip を呼ぶまでディスプレイに表示される内容は変化しません
メンテ
Re: 描画は60FPS、内部処理は60FPS以上で処理したい ( No.11 )
名前:ギウ 日時:2020/08/10 07:55

>管理人様 ということは、GetJoypadDirectInputStateやCheckHitKeyは、「関数を呼んだ時の最新情報を取得できる」と考えて大丈夫でしょうか。 (ProcessMessageを実行しないと入力情報が更新されないかと思ってました)
メンテ
Re: 描画は60FPS、内部処理は60FPS以上で処理したい ( No.12 )
名前:管理人 日時:2020/08/10 22:13

> ギウさん > ということは、GetJoypadDirectInputStateやCheckHitKeyは、「関数を呼んだ時の最新情報を取得できる」と考えて大丈夫でしょうか。 > (ProcessMessageを実行しないと入力情報が更新されないかと思ってました) ゲームパッドの入力に関しては常に「関数を呼んだ時の最新情報を取得できる」となっています キーボードの入力に関しては <デフォルトの動作> ProcessMessage を実行しないと入力情報が更新されない( 標準APIを使用 ) <SetUseDirectInputFlag( TRUE );を DxLib_Init の前に呼んでいる> 関数を呼んだ時の最新情報を取得できる( DirectInputを使用 ) となっています ( 理由の詳細は失念したのですが、DirectInput を使用してキーボード入力を取得すると 挙動がおかしいことがあったので、デフォルトではキーボード入力に関しては標準APIを使用しています )
メンテ
Re: 描画は60FPS、内部処理は60FPS以上で処理したい ( No.13 )
名前:ギウ 日時:2020/08/11 08:23

>管理人様 詳細ありがとうございます! 上記の、描画とそれ以外をスレッドで分ける案が良いですね。
メンテ
Re: 描画は60FPS、内部処理は60FPS以上で処理したい ( No.14 )
名前:was-blue.0793(解決) 日時:2020/08/13 19:58

>>管理人さん ScreenFlip()関数を呼ぶまで画面表示が変化しなければ、現在の時間と最後に更新した時間との差分をとってその時間が一定以上になれば描画処理を行うという処理を行えば当該処理を実現できることを確認しました。 処理を実現できそうな目途が立ちましたので解決とさせていただきます。皆様のご協力に感謝いたします。
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存