• ベストアンサー

FPS処理について

FPSの計測固定したいのですが、どうやったらいいかわかりません。どのように処理すればよいのでしょうか? あるサイトに載っていたのですが、 if (timeGetTime() - dwStart >= 1000.0/FPS) { // 時間更新 dwStart = timeGetTime(); fps=0; // 描画処理 Draw(); } } これで求まるのでしょうか?またもし間違っていたら、どういうふうに直せばよいのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.5

 こんばんは。  16ミリ秒のウェイトをかければ良い、と言う事になります。  手っ取り早くは、Sleep(16)とする事です。  その他DirectDrawのWaitForVerticalBlankメソッドを使う手段もあります。  http://msdn.microsoft.com/ja-jp/library/cc355951.aspx  後、windows2000以降では、デフォルトでtimeGetTime()の精度が10ミリ秒に設定されていた、と記憶しています。必ずtimeBeginPeriod()を呼び出して精度を設定してください。  以下はFPSをタイトルバーに表示します。また、Draw()関数の処理時間が16ミリ秒を超えた場合、ノーウェイトで通過します。  参考程度に。  #include<windows.h> #include<mmsystem.h> #pragma comment(lib, "winmm.lib") void Draw() { //ココで描写する } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CLOSE: ::DestroyWindow(hwnd); return 0; case WM_NCDESTROY: ::PostQuitMessage(0); return 0; } return ::DefWindowProc(hwnd, message, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pszArgs, int showCmd) { WNDCLASSEX wc = {sizeof(wc)}; wc.lpszClassName = TEXT("FPSTEST"); wc.lpfnWndProc = &::WndProc; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW); wc.hInstance = hInst; wc.hCursor = LoadCursor(NULL, IDC_ARROW); if(!::RegisterClassEx(&wc)) return 0; HWND hwnd = ::CreateWindowEx( 0, wc.lpszClassName, NULL, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, 0); ::ShowWindow(hwnd, SW_SHOW); TIMECAPS tc; ::timeGetDevCaps(&tc, sizeof(tc)); ::timeBeginPeriod(tc.wPeriodMin); DWORD dwStart = ::timeGetTime(); DWORD dwLast = 0; DWORD dwFps = 0; MSG msg; while(1) { if(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == TRUE) { if(::GetMessage(&msg, NULL, 0, 0) == FALSE) break; ::TranslateMessage(&msg); ::DispatchMessage(&msg); } else { const DWORD dwDrawStart = ::timeGetTime(); ::Draw(); const int iDrawTime = ::timeGetTime() - dwDrawStart; DWORD dwWait = max(16 - iDrawTime, 0); ::Sleep(dwWait); dwLast = ::timeGetTime(); if(dwLast - dwStart >= 1000) { TCHAR buf[256]; ::wsprintf(buf, TEXT("[Frame Per Second : %d]"), dwFps); ::SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)buf); dwStart = dwLast; dwFps = 0; } else { ++dwFps; } } } ::timeEndPeriod(tc.wPeriodMin); return msg.wParam; }

taiyaki_10
質問者

お礼

回答ありがとうございます。大変参考になりまいた。ありがとうございました。

その他の回答 (4)

  • koi1234
  • ベストアンサー率53% (1866/3459)
回答No.4

>どうやったらFPSを固定できますかという質問です。 環境(OSやコンパイラ)が分からないので一般論しかいえませんが タイマー割り込みつくって割り込みごとに描画させるしかないでしょう

  • koi1234
  • ベストアンサー率53% (1866/3459)
回答No.3

#2補足兼追記 #1さんの関数で言いたいこととしては(勝手に想像で書いてますが基本は同じ思いだと思います) まず ・自分で描画した回数を取得する(何回描画したのかをカウントする) ・どこかで1秒間の計測を行い↑で求めた回数を取得する これを行うことでFPSが求められますってことです 質問文のソースではそもそも何回描画したかが取得できません (どこにFPS求めるコードがあるんですか状態) だから#1さんはDraw()関数の後に描画カウントインクリメントしています 後は自分の環境に合わせてそのソースを埋め込むことで取得できます (人が書いたソースそのまま書けばいいってもんじゃありません) って書いてる間に補足がついてたのでさらに追加 >// nCnt 描画枚数のカウント >if ( nCnt >= 60 ) { // 60FPSの場合 あなたが求めたいのはFPSでしょ? この書き方は60フレーム書き換えるために必要な時間がどのぐらいか って様な書き方になります(やりたい事とソースコードが一致してません)

taiyaki_10
質問者

お礼

回答ありがとうございます。質問の仕方が間違っていました。どうやったらFPSを固定できますかという質問です。すみませんでした。

  • koi1234
  • ベストアンサー率53% (1866/3459)
回答No.2

#1さんの提示ソースで >FPSが490~540になってしまって ってありえないと思いますが一体どんな処理をしてるのでしょうか? 根本的な思い違いをされているような気がします #1さん書いてますがFPSというと普通は1秒間に描画更新される回数(フレーム数)を意味します どんなものを表示して測定ルーチンをどこに書いているのでしょうか? (#1さんのコードをどのように使ったのでしょう?)

taiyaki_10
質問者

お礼

回答有難うございます。 確か // dwStart 前回の計測時間 // nCnt 描画枚数のカウント if ( nCnt >= 60 ) { // 60FPSの場合   float tmp = (timeGetTime() - dwStart) / 1000.0f;   // 時間の更新   dwStart = timeGetTime();   FPS = (float)nCnt / tmp; _stprintf(buff,T_("%f\n"),FPS); OutputDebugString(buff) } Draw(); nCnt++; だったと思います。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

FPS自体が 1秒間の描画枚数を意味するのであれば 何枚か描画するのにかかった時間を計って 除算するほうがいいかと思います // dwStart 前回の計測時間 // nCnt 描画枚数のカウント if ( nCnt >= 60 ) { // 60FPSの場合   float tmp = (timeGetTime() - dwStart) / 1000.0f;   // 時間の更新   dwStart = timeGetTime();   FPS = (float)nCnt / tmp; } Draw(); nCnt++; といった具合でしょうか # 見当違いならご容赦ください …

taiyaki_10
質問者

お礼

そのソースでやってみましたが、FPSが490~540になってしまって動作は早いです。nCntも初期化していなかったのでif()の中で処理したのですがダメでした。

関連するQ&A

  • FPSについて

    一つ質問なのですが、FPSの計測したいのですが、以下のソースでやるとFPSが57になってしまうのですが。 どうしたらFPSを60にすることが出来るのでしょうか? 多分ここら辺だろうなというところを載せます。 void FPSCount(void){ static DWORD before_time = timeGetTime(); // 以前の時間 DWORD now_time = timeGetTime(); // 現在の時間 static DWORD fps_ctr = 0; TCHAR buff[80]; // 文字列表示用バッファ if(now_time - before_time >= 1000){ // 初期化 before_time = now_time; *fps = fps_ctr;     wsprintf(buff,_T("%d\n"),fps_ctr);     OutputDebugString(buff);     fps_ctr = 0; } fps_ctr++; } // エントリポイント int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )      ・      ・      ・ // メッセージループ while(true) { if (PeekMessage(&msg, NULL, 0,0,PM_REMOVE)) { if (msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } else { // 同期処理 if (timeGetTime() - dwStart >= 1000.0/FPS) { FPSCount(); // 時間更新 dwStart = timeGetTime(); fps=0; // 描画処理 Draw(); } } Sleep(1); } timeEndPeriod(1); // 終了処理 Cleanup(); // 戻り値を返します。 return (int)msg.wParam; } } です。 環境はVC+2005です。

  • C# ゲーム作成 FPSと描画処理に関して

    環境はVisualStudioC#Expressを使っています。 今回動きのあるゲームを作ろうと思ったのですが、 最も基本となるFPSの処理と再描画の処理が理解できません・・・。 簡単な動きのないアプリケーションくらいしか作れない程度のレベルなので、かなり細かいところになると分からないと思います。 プログラムだけ書かれてもどこにそれを書けばよいのか分からないほどだと思います。FPSに関してはTimerコンポーネントを使ってみたのですがうまくいきません。 そこで教えていただきたいことは、 (1)簡単なFPSのサンプルプログラム(出来れば精度とかもあるのでみなさんが普通にゲームに使っているようなものを) (2)簡単な再描画処理のサンプルプログラム (3)C#ゲーム作成にオススメなサイトや本 出来ればVisualStudio前提の説明だとありがたいです。 とりあえず球が『60FPSで動き、画面も再描画される』ことが目的です。

  • FPS計測数値が変わらないゲーム

    ゲームによっては、 FPSの計測数値が固定されているものがありますか? どんなに高スペックのビデオカードにしても、 FPSが上がらないゲームです。

  • FPS制御について

    今DirectDrawを使ったプログラムを組んでいて、そのプロジェクト内でFPSの制御関数(図1)を作りました。その関数は引数を1つ持っていて、その引数に渡した値がそのままフレームレートになるはずなのですが、実際は引数に指定した値よりもフレームレートが落ちています。   図1 FpsControl(60); ↑           1/60フレームレート FPS制御をしていない時にFPSを計ったときには500~600fps は出ていましたので処理自体が遅いわけではないと思います。 FPS制御関数はメッセージループ部分(図2)で使っています。   図2 while(TRUE){ //メッセージがある場合 if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)){ if(msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); }else{ //メッセージが無い場合 if(FpsControl(60))Game_Main();//プログラ ムのメイン部分 ↑    ↑ }        ↑                   ↑                **ここで使ってます** 関数の内部処理は何度も確認したので間違ってないと思います。 ずっとこのバグについて考えいろいろ試しましたが、 結局原因はわからずここに助けを求めに来ました。 お願いします。

  • timeGetTimeについて

    宜しくお願いします。 http://www.tsg.ne.jp/sept/prg/memo/timegettime.asp 上記のサイトを参照してtimeGetTimeを利用して実行時間の計測をしています。 このサイトにはmmsystem.hをインクルード,winmm.libとリンクしデータ型はDWORD型とあります。 しかし,そうしなくともwindows.hをインクルードしdouble型でtimeGettime();を読み込んでも値を読み込んでくれます。そしておそらく正確な数値のようなのですが,これでも大丈夫なのでしょうか。また,なぜこれでもできるのでしょうか。 御指南ください。使っているコンパイラはBCCでC言語で組んでいます。

  • オーナードローボタンでのバグ

    オーナードローボタンでのバグについて質問です。 ボタンの更新(再描画)を何度も繰り返すと、 再描画をしてもうまく表示(再描画)されなくなるのですが、 何が原因なのでしょうか? さらに、ボタンの再描画がうまく行かなくなった後に、 プロパティシートを開くとおかしくなります(ウィンドウの枠しか表示されない)。 ちなみに、ボタンの再描画処理をしないようにしてみた所、 こういう現象はありませんでした。 開発環境 XP Visual Studio 2005 C、C++でWindowsAPIを使用しています。

  • ドラッグ中の処理

    計測器制御でVB6を使っています。 リアルタイムで取ってきたデータをグラフ表示させているのですが、グラフのウインドウをマウスでドラッグしてしまうと、その間グラフの更新が止まってしまいます。(マウスを離すと途中から再開します。) 具体的には While グラフ描画 DoEvents Wend のような構造になっています。 いい解決方法はないでしょうか?

  • PCゲームプレイ中にFPSが低くて処理落ちしてしまいます。

    PCゲームプレイ中にFPSが低くて処理落ちしてしまいます。 Allods online という3D MMORPGをプレイしています。 スペック的には問題ないんですが常時30付近のFPSしか出ず、処理不足でカクついてしまいます。 ゲーム内の環境設定を最高~最低に変えても全く変化がありません。 しかし裏でJaneを起動してタスクバーに置いておくと処理不足が解消されて軽い場所(キャラ選択画面など)で300FPS越え 常時150FPS~100FPS出るようになります。 Jane以外でもFireFoxで特定のサイトを開いたりしてると同じようになります。 なぜかIEではなりません。 ちなみにOSのクリーンインストール、GPUドライバ変更どれも効果なしです。 FF14のベンチマークテストは同スペックのPCとほぼ同じLow4000出ました。 PCスペック i7 860 Men 4g xp sp3 GTS250 何か解決策分かる方いましたらどんな情報でもいいのでよろしくおねがいします

  • C#のpictureBoxの描画のタイミング

    C#のpictureBoxの描画について質問します。 drawにpictureBoxの描画コードが有りますがあり、Form1() の InitializeComponent();の 後(コードA)では、描画できませんが、button1_Click(コードB)では、描画できるようです。 Q1)プログラムの起動時に、描画できる方法はありますか? public Form1() { InitializeComponent(); 処理コード draw(); //コードA } private void button1_Click(object sender,EventArgs e) { draw(); //コードB }

  • Delphiのスレッドプログラミング

    ゲームプログラムなんですが、計算するルーチンと描画を行うルーチンの二部構成で現在プログラムを作っています。計算は随時行い、描画は余裕があるときに行うというやり方で、最大限のフレームレートを出そうとしています。 で、いままで、Application.onIdleを使って画面描画していたものを、スレッドを使ってみることにしました。メインスレッドで計算を行い、サブスレッドで描画を行うという方法を考えたのですが・・・。 onIdleを使っているうちは、描画が忙しくなってくる→onIdleが発生しなくなる→描画を間引く→負荷が減るといった構図で丁度よかったのですが・・・。 ---------(描画を行うサブスレッド)--------- While(true) do begin   Start := TimeGetTime;   Synchronize(); // ここでメインスレッド経由でVCLに描画   Stop := TimeGetTime;   If (Stop - Start < 33) then Sleep(33 - stop - start); // 描画が33ms以下で済めば、30FPSになるようにwaitを入れる end; ---------------------------------------- このような方法で最大30FPSを確保しようとしたのですが、描画に負荷がかかってくると、メインスレッドにあるタイマが遅延してしまい、全体がガタガタになってしまいました。OnIdle使用時は描画よりメインの数値計算が優先されていたので、問題なかったのですが・・・。 根本的にマズいんでしょうか、コレ・・・。