ゲームプログラミングではWindowsプログラミング(イベント・ドリブン方式)と違い、イベントとは関係なくループし続ける。
これをゲーム・ループと呼ぶ。(詳しくは第2章を参照)
では、このゲームループはどれくらいのスピードで回っているのだろうか?そこで、ゲームループがどれくらいのスピードで回っているかを計測する。スピードは、
1秒間に何回ループするか(FPS)で考える。
1秒間に何回ループするかを調べるには、ゲームループが始まる前に0をセットし、ゲームループが一回ループするたびにカウントアップする。1秒たったら何回ループしたかを表示すればよい。
![]()
ここで問題になるのは、
1秒たったどうかをどうやって調べるかである。
Windowsにはマシンを起動してからどれだけ時間がたっているかを調べるAPI関数として「TimeGetTime関数」「GetTickCount関数」がある。この関数を使い、ゲーム開始時とループ途中の経過時間を調べ、差分が1秒(1000ミリ秒)を超えるかどうかで判断する。![]()
プログラムに組み込むには、
WinMain.cpp内で行うのがよい。【プログラム例】
//============================================================================= // 2Dゲーム基本プログラム3(第6章キャラクタ表示テスト用プログラム) //============================================================================= #include "common.h" //----------------------------------------------------------------------------- // プロトタイプ宣言 //----------------------------------------------------------------------------- ・ ・ ・ //----------------------------------------------------------------------------- // 外部変数(本体) //----------------------------------------------------------------------------- ・ ・ ・ //----------------------------------------------------------------------------- // グローバル変数 //----------------------------------------------------------------------------- static char szWinName[] = "Skeleton"; // ウィンドウクラス名 static char szTitle[] = "2Dゲーム基本プログラム3"; // ウィンドウタイトル名static DWORD backTickCount, nowTickCount; // 時間制御用//============================================================================= // ウィンドウメイン関数(WinMain) //============================================================================= int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode) { HWND hWnd; MSG msg; /* 表示するウィンドウの定義、登録、表示 */ if (!(hWnd = InitApp(hThisInst, nWinMode))) return FALSE; /* Direct Draw Object の初期化 */ if (InitializeDraw(hWnd) != DD_OK) return FALSE;/* FPSの初期設定 */backTickCount = 0;/* ゲーム・ループ */ while (TRUE) { if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) // メッセージがあるかどうか { if (!GetMessage(&msg, NULL, 0, 0)) // メッセージを取得し、WM_QUITかどうか break; TranslateMessage(&msg); //キーボード利用を可能にする DispatchMessage(&msg); //制御をWindowsに戻す } else // ゲームメイン処理 { UpdateFrame(hWnd); Sleep(1); } } return msg.wParam; } //============================================================================= // ウィンドウプロシジャ関数(WindowProcedure) //============================================================================= static LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { ・ ・ ・ } //============================================================================= // 関数名 :InitApp // 機能概要:表示するウィンドウの定義、登録、表示 // 戻り値 :正常終了のとき1、以上終了のとき0 //============================================================================= static HWND InitApp(HINSTANCE hThisInst, int nWinMode) { ・ ・ ・ } //----------------------------------------------------------------------------- // 関数名 : UpdateFrame() // 機能概要: 画面更新処理 //----------------------------------------------------------------------------- static void UpdateFrame(HWND hWnd) {static int fps = 0; // FPSカウントchar buff[80]; // 文字列表示用バッファ/* 現在のキー情報を取得 */ if (!GetKeyboardState(KeyTbl)) return;/* 現在の時間を取得 */nowTickCount = timeGetTime();/* 処理の振り分け */ switch (g_FrameNo) { case START_INIT: StartInit(hWnd); case START_FRAME: StartFrame(hWnd); break; case GAME_INIT: GameInit(hWnd); case GAME_FRAME: GameFrame(hWnd); break; default: OutputDebugString("g_FrameNoの値が例外です。\n"); }/* FPSを求めて表示する */fps++;if (nowTickCount - backTickCount >= 1000){backTickCount = nowTickCount;wsprintf(buff, "%04d FPS\n", fps);OutputDebugString(buff);fps = 0;}/* フリップ処理 */ g_pDDSPrimary->Flip(NULL, 0); }ビルド後、
デバッグ・モードで実行(F5キー)すると、OutputDebugString関数により、約1秒ごとにメッセージ・ウィンドウにFPSが出力される。
プログラム実行中はメッセージ・ウィンドウを見ることはできないので、プログラム終了後に確認する。初めは数値が安定しないが、すぐに
60FPS前後に固定されることが分かる。
プログラムを修正し、FPSが画面に表示されるかどうかを確認する。