• 締切済み

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です。

  • 79562
  • お礼率68% (164/239)

みんなの回答

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

同じような質問に回答したついでに回答 >どうしたらFPSを60にすることが出来るのでしょうか? >多分ここら辺だろうなというところを載せます。 根本的な発想が間違ってます 計測ルーチン変えれば早くなるわけではありません 現状57しかないものを60にしたいのであれば描画に関係する 実ルーチンのほうを改善する必要があります

関連するQ&A

  • FPS処理について

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

  • 描画のカクカクについて

    描画された画像が移動中たまに(動画を見ながら実行すると多く)カクカクするのですが、どうしたらこのカクカクをなくすことができるでしょうか? 多分ここだろうなと言うところを載せます。 //グローバル変数 static HDC g_hdcOff,g_hdcImg[MAX_IMAGE]; static HBRUSH g_hbrBg = NULL; // 背景用ブラシ static HBITMAP g_hbmImg[IMG_MAX]= {NULL}; // 画像のビットマップ //================================================================================ // オフスクリーンへ画像表示 // idx : 画像データの添え字 // x,y : 表示位置x,y // sx,sy : 画像切り出し位置x,y // w,h : 画像切り出し幅、高さ // src : 転送モード指定。通常はSRCCOPY,SRCPAINT,SRCANDなど //================================================================================ void DrawImg(int idx,int x,int y,int sx,int sy,int w,int h,DWORD src) { BitBlt(g_hdcOff,x,y,w,h,g_hdcImg[idx],sx,sy,src); } //================================================================================ // オフスクリーンへ画像表示。マスク表示→画像表示 // idx : 画像データの添え字 // x,y : 表示位置x,y // sx,sy : 画像切り出し位置x,y // w,h : 画像切り出し幅、高さ // mx,my : マスク切り出し位置x,y //================================================================================ void DrawImgMask(int idx,int x,int y,int sx,int sy,int w,int h,int mx,int my) { BitBlt(g_hdcOff,x,y,w,h,g_hdcImg[idx],mx,my,SRCPAINT); BitBlt(g_hdcOff,x,y,w,h,g_hdcImg[idx],sx,sy,SRCAND); } void Draw() { // 画面消去 HBRUSH oldbr = (HBRUSH)SelectObject(g_hdcOff, g_hbrBg); Rectangle(g_hdcOff, -1, -1, CLIENT_WIDTH+1, CLIENT_HEIGHT+1); SelectObject(g_hdcOff, oldbr); //---------------------------------------------------------- // ↓ここから描画処理 // キー状態の更新 KeyUpdate(); // プレイヤー移動 if (KeyIsHold(KC_LEFT)) { g_Player.x -= PL_VELX; if (g_Player.x < PL_LIMITL) g_Player.x = PL_LIMITL; } if (KeyIsHold(KC_RIGHT)) { g_Player.x += PL_VELX; if (g_Player.x > PL_LIMITR-g_ImgData[g_Player.type].w) g_Player.x = PL_LIMITR-g_ImgData[g_Player.type].w; } // プレイヤーの表示 DrawChr(g_Player.type, g_Player.x, g_Player.y); // ↑ここまで描画処理 //---------------------------------------------------------- // 再描画 InvalidateRect(g_hWnd,0,FALSE); UpdateWindow(g_hWnd); } // キャラクタ描画関数 // type : キャラタイプ(eChrType) // x : 表示位置X // y : 表示位置Y void DrawChr(int type,int x,int y) { DrawImgMask(g_ImgData[type].idx, x,y, g_ImgData[type].sx, g_ImgData[type].sy, g_ImgData[type].w, g_ImgData[type].h, g_ImgData[type].mx, g_ImgData[type].my); } int WINAPI 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 { static DWORD before_time; DWORD now_time; DWORD ideal_time=0; static int frame=0; TCHAR buff[100]; DWORD team=0; static long surplus_time=0; now_time=timeGetTime(); if(!before_time) before_time=timeGetTime(); surplus_time=(long)(now_time-before_time); ideal_time=(DWORD)(frame*1000)/60; wsprintf(buff,TEXT("%d %d %d\n"),ideal_time,surplus_time,(long)ideal_time-surplus_time); OutputDebugString(buff); if((long)ideal_time-surplus_time>0) Sleep((long)ideal_time-surplus_time); team=timeGetTime(); team-=before_time; if(team>=1000) { before_time=timeGetTime(); frame=0; } frame++; } Sleep(1); } ・・・ ・・・ ・・・ return (int)msg.wParam; } 環境はVC++2005、C言語とWINAPIっだけです。 説明が足りないのなら補足します。

  • 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();//プログラ ムのメイン部分 ↑    ↑ }        ↑                   ↑                **ここで使ってます** 関数の内部処理は何度も確認したので間違ってないと思います。 ずっとこのバグについて考えいろいろ試しましたが、 結局原因はわからずここに助けを求めに来ました。 お願いします。

  • DLLをGetProcAddress()で実行できない。

    dllの操作の練習をしております。以下のソースのどこがおかしいのでしょうか? add.dllの内容は単にa+bの結果をメッセージボックスに表示させるだけの処理です。add.lib(インポートライブラリ)をリンクさせればうまく動きます。 しかし、GetProcAddress()を使って明示的にdllを呼び出そうとすると、コンパイルエラーで ADD(hWnd,5,5); の行に 「int (__stdcall *)(void)' : 実引数が多すぎます。」 となります。このメッセージの意味もわかりません。 以下のソースのどこがおかしいのでしょうか?コンパイラはVC++6.0でOSはWin2000です。 #include<windows.h> void CALLBACK ADD(HWND hwnd,int a, int b); //ウィンドウプロージャ(ここは別に普通) LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) { switch (msg) { case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd , msg , wp , lp); } int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance , PSTR lpCmdLine , int nCmdShow) { static FARPROC ADD;  //あやしい HWND hWnd; MSG msg; WNDCLASS winc;     //ウィンドウを作る処理 //~(省略)~ /****明示的にdllを呼び出す****/ ADD = GetProcAddress( LoadLibrary(TEXT("add.dll")) , TEXT("ADD")); ADD(hWnd,5,5); /****************************/ while (GetMessage(&msg , NULL , 0 , 0 )) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } お願いします。

  • 配列のポインタについて

    C言語で処理が下記のような処理を作成したいと思っております。 関数の引数によって、データを代入する配列を切り替えたいと考えております。 下記のような処理を考えた場合、if文の中・for文のbuffをどのように処理すれば よいでしょうか? アドバイスよろしくお願い致します。 int a[100][150]; int b[100][150]; void sample(int flg) { int i,j; unsigned short *buff; if(flg == 0){ buff = &a; }else{ buff = &b; } for( j=0 ; j<100 ; j++ ){ for( i=0 ; i<150 ; i++ ){ buff[y][x] = data; x++; } x = 0; y++; } }

  • GetModuleFileNameでエラーが出てしまう。

    #include<windows.h> #include<string.h> // 関数のプロトタイプ宣言 VOID CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime); BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam); // エントリポイント int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; EnumWindows((WNDENUMPROC)EnumWindowsProc,NULL); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam) { char Caption[201]; char FileName[1024]=""; char FindList[1][80]={"Microsoft Internet Explorer"}; GetWindowText(hwnd, Caption, 200); for(int i=0;i<=0;i++) if(NULL!=strstr(Caption,FindList[i])) { HINSTANCE hInst; hInst = (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE); if(GetModuleFileName(hInst, FileName, 1023)!=0) { // ファイル名取得成功したときの動作 MessageBox(NULL,Caption,FileName,MB_OK|MB_SETFOREGROUND); }else{ MessageBox(NULL,Caption,"Error",MB_OK|MB_SETFOREGROUND); } } return true; } 実行するとIEが起動されてたらそのウインドウのキャプションとプログラム名を表示される予定なのですが、 GetModuleFileNameでエラーが返されます。 何が原因なのでしょう?

  • ポインタの引数について。

    C言語初心者です。 既存のプログラムを直そうとしているのですが、ポインタの概念がいまいち理解できていないのか、修正した箇所がうまく動きません。 どうすればよいかをご教示いただけませんでしょうか。 元のプログラムは void sub() { SOCKET s; struct msg r_msg; int time; int cc; cc = sub_recv(s, &r_msg, time); ・・・ } void sub_recv(s,*msg,time) { unsigned char *pack; int cc; int len; pack = (unsigend char *)msg cc = recv(s, (char *)pack, len, 0); if(cc < 0) return(cc); ・・・ } という感じでr_msg構造体にrecvで受け取ったものを入れて行きます。 ccにはrecv()の戻り値でサイズが返ってきて直後のifにはひっかかりません。 構造体の中でサイズが固定されているため、可変にするために以下のようにしたいです。 extern int buflen; void sub() { SOCKET s; unsigned char *r_msg; int time; int cc; r_msg=(char *)malloc(sizeof(char)*buflen ); cc = sub_recv(s, r_msg, time); free(r_msg); ・・・ } void sub_recv(s,*msg,time) { unsigned char *pack; int cc; int len; pack = (unsigend char *)msg /*ここの代入は無意味と思いますがなくしても同様の結果のなので残してます。*/ cc = recv(s, (char *)pack, len, 0); if(cc < 0) return(cc); ・・・ } しかし、このような修正で*r_msgにはrecv()で受け取った内容が入る気がするのですが、 ccには-1が入ってしまい、ifに引っかかって終了してしまいます。 この時のerrnoを見ても104が入り、connection reset by peerといった感じです。 recv()の第二引数にはこれがバッファが用意されてればいいと解釈しておりますが、 これではバッファが1バイトしかとれていないなどあるのでしょうか。 因に、send()がないからというのはありません。 キャストが間違えているなどもあるかもしれませんが、宜しくお願いします。

  • timeSetEventに対するtimeKillEventについて

    SetTimerとの比較も兼ねてtimeSetEvent関連を調べていたのですが CALLBACKの外部で timeSetEventの戻り値を保存しておき、必要な時にそのIDを基に timeKillEventするサンプルは簡単に見つかったのですが timeKillEventは内部で使ってもいいのでしょうか? なるべく端折って書くとたとえば timeBeginPeriod( 8 ); timeSetEvent( 40, 8, TimerProc, 0, TIME_PERIODIC ); とでもした場合に timeSetEventの重ねがけをしない(するならもうちょっと変更) という前提で void CALLBACK TimerProc( UINT ID, UINT, DWORD User, DWORD , DWORD ){ static int d(11); if ( !--d ){ timeKillEvent(ID); timeEndPeriod(8); } } 的なことをしても問題ないのでしょうか? (出力やtimeGetTimeなどの関数を付加して実験してみた結果だけだと、問題なく動いているように見えるのですが、実はすぐには分からないような問題が内部的に発生してる可能性はありますか?)

  • C++ GUIのメッセージループ。

    初心者です。 よろしくお願いします。 とても重く時間の掛かる処理を色んなサイトを参考にスレッドにしてみたんですけど、書き方が悪いのか、再描写がワンテンポ遅れたり、アプリケーションを複数起動したりするとフリーズしてしまったりします。 原因はメッセージループにあるような気がしてるんですが、この書き方はおかしいですか?? どのサイトから引用したのかわからなくなってしまいました。 気付いたことなどあったら何でもいいので教えて貰えたら嬉しいです!よろしくお願いします!! thread01に重い処理が書かれてます。 int thread_call() {   unsigned int dwThreadId[1];   HANDLE hThread[0] = (HANDLE)_beginthreadex(     NULL,     0,     ( unsigned int (__stdcall*)(void*) )thread01,     NULL,     0,     &dwThreadId[0] );   MSG msg;   DWORD dwRet = WAIT_TIMEOUT;   while ( 1 ) {     dwRet = ::MsgWaitForMultipleObjects( sL, hThread, FALSE, INFINITE, QS_ALLEVENTS );     if ( dwRet == WAIT_OBJECT_0 + sL ) {       if ( ::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {         ::TranslateMessage( &msg );         ::DispatchMessage( &msg );       }     } else if ( dwRet >= WAIT_OBJECT_0 && dwRet < WAIT_OBJECT_0 + sL )       break;   }   CloseHandle( hThread[0] );   hThread[0] = NULL; }

  • 小数計算について

    お世話になります。 以下の小数計算方法を教えてください。 時間取得を DWORD start,end; start = start = timeGetTime(); for(int i =0; i<100000; i++){ 何らかの処理; } end = timeGetTime(); int msec = end-start; 上記 msecを1000で割った場合、 小数になるのですが、その場合、小数の変数の型は 何になるのでしょうか? また、求めた小数を用いて、 INT型の変数÷求めた小数 = 小数値(小数第2位まで) を行いたいです。 例えば、 840000 / 64.9 = 12942.99 のような処理をしたいです。 どうぞよろしくお願い致します。

専門家に質問してみよう