トップページ > 記事閲覧
フレームレートについて
名前:P 日時: 2020/01/15 22:43

商用のゲームではどれだけfpsが出ようと、ゲームの進行する速度は常に一定で描画の滑らかさが増すだけというのは、どのような処理になるのでしょうか? この仕組みがよくわからないので、ご教授いただければ…。
メンテ

Page: 1 |

Re: フレームレートについて ( No.1 )
名前:管理人 日時:2020/01/16 00:44

商用のゲームにも色々ありますが、基本的には毎フレーム経過した時間を取得して、 経過時間に応じてゲームを進行させる、という処理を行うことでfpsがどのように なっても一定の動作をするようにしています 例えば、四角形が画面を左右に跳ね回るだけのプログラムをその手法で組むと以下のようになります #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { LONGLONG NowTime ; LONGLONG Time ; float x, add ; float DeltaTime ; int FPS ; int FPSCounter ; LONGLONG FPSCheckTime ; // ウインドウモードで起動 ChangeWindowMode( TRUE ) ; // ScreenFlip を実行しても垂直同期信号を待たない SetWaitVSyncFlag( FALSE ) ; // DXライブラリの初期化 if( DxLib_Init() < 0 ) return -1 ; // 描画先を裏画面にする SetDrawScreen( DX_SCREEN_BACK ) ; // 座標を初期化 x = 0.0f ; // 速度を初期化( 1秒間に移動するドット数 ) add = 200.0f ; // システム時間を取得しておく Time = GetNowHiPerformanceCount() ; // 最初の経過時間は仮に 0.000001f 秒にしておく DeltaTime = 0.000001f ; // FPS計測関係の初期化 FPSCheckTime = GetNowHiPerformanceCount() ; FPS = 0 ; FPSCounter = 0 ; // メインループ while( ProcessMessage() == 0 ) { // 経過時間を考慮した移動( DeltaTime を掛ける ) x += add * DeltaTime ; if( x < 0.0f ) { x = 0.0f ; add = -add ; } if( x > 640.0f ) { x = 640.0f ; add = -add ; } // 画面のクリア ClearDrawScreen() ; // 四角形の描画 DrawBox( ( int )x, 240 - 32, ( int )x + 64, 240 + 32, GetColor( 255,255,255 ), TRUE ) ; // FPSの描画 DrawFormatString( 0, 0, GetColor( 255,255,255 ), "FPS:%d", FPS ) ; // 裏画面の内容を表画面に反映 ScreenFlip() ; // 現在のシステム時間を取得 NowTime = GetNowHiPerformanceCount() ; // 前回取得した時間からの経過時間を秒に変換してセット // ( GetNowHiPerformanceCount で取得できる値はマイクロ秒単位なので 1000000 で割ることで秒単位になる ) DeltaTime = ( NowTime - Time ) / 1000000.0f ; // 今回取得した時間を保存 Time = NowTime ; // FPS関係の処理( 1秒経過する間に実行されたメインループの回数を FPS とする ) FPSCounter ++ ; if( NowTime - FPSCheckTime > 1000000 ) { FPS = FPSCounter ; FPSCounter = 0 ; FPSCheckTime = NowTime ; } } // DXライブラリの後始末 DxLib_End() ; // ソフトの終了 return 0 ; } 移動速度が一定であることが分かるように ScreenFlip で垂直同期信号を待たない設定( SetWaitVSyncFlag( FALSE ); )にして、 あと FPS表示の処理も入っています 1フレームの経過時間の計測には GetNowCount よりも1000倍精度が高い時間を取得できる GetNowHiPerformanceCount を使用します ( GetNowCount はミリ秒( 1/1000秒 )単位なのに対して、GetNowHiPerformanceCount はマイクロ秒( 1/1000000秒 )単位です ) 1フレームの経過時間は変数 DeltaTime に代入するようにしていて、この値に応じて四角形の移動距離が変わるように なっています( 1フレームの経過時間が長ければ一度に沢山移動して、短ければ移動距離も短くなる ) x += add * DeltaTime ; // ←上記プログラムのこの部分です 60fps などの決め打ちの場合は『1秒間待つ』という処理も 60回メインループが実行されるのを待つ という処理となりますが、上記のような処理の場合は毎フレームの DeltaTime の値をカウンターの変数に += で加算していって、カウンター用変数の値が 1.0f を超えたら1秒経過したと判断するような処理になります
メンテ
Re: フレームレートについて ( No.2 )
名前:P 日時:2020/01/16 12:12

ありがとうござます。 例えばこの処理で垂直同期なしでフレームレートを抑える場合はシステム時間を取得するあたりでプロセスを眠らせるといった処理を加えるのですか?
メンテ
Re: フレームレートについて ( No.3 )
名前:P 日時:2020/01/16 20:23

すみません 先程の追記で、垂直同期無しで指定したフレームレートにする場合は、 プログラムサンプルの13のようなものでよろしいのでしょうか?
メンテ
Re: フレームレートについて ( No.4 )
名前:管理人 日時:2020/01/17 02:28

> 例えばこの処理で垂直同期なしでフレームレートを抑える場合はシステム時間を取得するあたりでプロセスを眠らせるといった処理を加えるのですか? はい、ScreenFlip(); と GetNowHiPerformanceCount(); の間にウエイトを入れることでフレームレートを抑えることができます // 裏画面の内容を表画面に反映 ScreenFlip() ; WaitTimer( 16 ); // 現在のシステム時間を取得 NowTime = GetNowHiPerformanceCount() ; > 先程の追記で、垂直同期無しで指定したフレームレートにする場合は、 > プログラムサンプルの13のようなものでよろしいのでしょうか? いえ、プログラムサンプルの13は垂直同期あり前提のプログラムなので、フレームレート固定にする場合は プログラムサンプルの14と同じ処理になります、プログラムサンプルの14の DxLib_Init の呼び出し前に SetWaitVSyncFlag( FALSE ) ; を追加すれば垂直同期無しで固定フレームレートのできあがりです
メンテ
Re: フレームレートについて ( No.5 )
名前:P(解決) 日時:2020/01/17 08:53

わかりました ありがとうございます
メンテ

Page: 1 |

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

   クッキー保存