ゲームメイン処理の考え方とプログラム

どのようなゲームも、大体次のような流れで作成されている。

  1. オープニング表示(タイトル画面、オープニングムービーなど)
  2. ゲームメイン
  3. エンディング表示(ゲームオーバー画面、エンディングムービーなど)

1.考え方

これらを全て行うプログラムを作るには、次のような考え方で行うとよい。

《解説》

※キー入力については次項で解説する

2.実際のプログラム

前項で作成したプログラムに、上記のフローチャートのようにゲームメイン処理を追加する方法を解説する。

2-1 前準備

ゲームメイン処理に必要なマクロ、外部変数、プロトタイプ宣言の作成を次のように行う。

#include <stdio.h>
#include <windows.h>    // WindowsAPIを使用可能にする
#include <windowsx.h>
#include <d3d8.h>       // DirectX8ヘッダファイル
#include <d3dx8.h>      // D3DXヘッダファイル

// マクロの定義
#define WINMODE FALSE // ウィンドウモードの指定(TRUE:ウィンドウモード/FALSE:フルスクリーン)
#define SCREEN_WIDTH	640	// ウィンドウの幅
#define SCREEN_HEIGHT	480	// ウィンドウの高さ
/* ゲームの状態を識別する(フレーム番号) */
#define START_INIT     0
#define START_FRAME    1
#define GAME_INIT      10
#define GAME_FRAME     11

// プロトタイプ宣言
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);   // Windows関数
BOOL InitApp(HINSTANCE, int);                           // ユーザー関数
HRESULT InitDX8(void);                                  // DirectX8初期化処理
void ReleaseD3D(void);                                  // DirectX8開放処理
void ResetWindow(void);                                 // ウィンドウ再生成処理
BOOL UpdateFrame(void);                                 // ゲームメイン処理

// グローバル変数
HWND hWnd;                              // ウィンドウハンドル
BOOL g_appActive = FALSE;               // ウィンドウの状態
char szWinName[] = "DirectX8Init";      // ウィンドウクラス用文字列
LPDIRECT3D8 gl_lpD3d = NULL;            // DirectX3Dオブジェク
LPDIRECT3DDEVICE8 gl_lpD3ddev = NULL;   // DirectX3DDeviceオブジェクト
BYTE g_FrameNo = START_INIT;            // フレーム選択用

《解説》

2-2 ゲームメイン処理関数の追加

ゲームメイン処理を行う関数 UpdateFrame関数 を、次のように作成する。プロトタイプ宣言の順番どおり、ResetWindow()関数の下にUpdateFrame関数本体を記述する。

//-----------------------------------------------------------------------------
// 関数名 : UpdateFrame()
// 機能概要: ゲームメイン処理
//-----------------------------------------------------------------------------
BOOL UpdateFrame(void)
{

    /* 現在のキー情報を取得 */

    /* 処理の振り分け */
    switch ( g_FrameNo ) {
        case START_INIT:
            // スタート画面を表示する前に実行する初期化関数を実行
        case START_FRAME:
            // スタート画面表示処理関数を実行
            break;
        case GAME_INIT:
            // ゲーム画面を表示する前に実行する初期化関数を実行
        case GAME_FRAME:
            // ゲーム画面表示処理関数を実行
            break;
        default:
            MessageBox(hWnd, "g_FrameNoの値が例外です。", "ERROR", MB_OK);
            return (FALSE);
    }

    /* フリップ処理 */

    return (TRUE);
}

《解説》

2-3 ゲームメイン処理関数の実行

ゲームループが回るたびにゲームメイン処理関数(UpdateFrame関数)が実行されるよう、WinMain関数を修正する。

//-------------------------------------------------------------------------------------------------
//      メイン関数(エントリーポイント)プログラムはここから始まる
//-------------------------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode)
{
    MSG msg;		// メッセージ構造体変数
    HRESULT hr;

    //表示するウィンドウの定義、登録、表示
    if ( !InitApp(hThisInst, nWinMode) )    // InitApp関数を呼び出し、
        return (FALSE);                     // 正常に終了すれば次にメッセージループへ

    // DirectX8の初期化
    hr = InitDX8();
    if ( FAILED(hr) ) return (FALSE);

    // ゲームループ
    while ( TRUE ) {
    // メッセージがあるかどうか
        if ( PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) {
            // メッセージを取得し、WM_QUITかどうか
            if ( !GetMessage(&msg, NULL, 0, 0) ) break;
            TranslateMessage(&msg);  //キーボード利用を可能にする
            DispatchMessage(&msg);   //制御をWindowsに戻す
        } else if ( g_appActive ) {
            // ゲームメイン処理
            if ( FAILED( UpdateFrame() ) ) break;	←コメントアウトを外した
            Sleep(1);
        } else {
            WaitMessage();
        }
    }

    // DirectX8オブジェクトの削除
    ReleaseD3D();

    return msg.wParam;
}

《解説》

※以上の修正を行ったらビルドを行い、プログラムが正常に動くかどうかを確かめる
(一切の描画を行っていないため、見た目は何も変わらない)。


BACK(一般的なゲームプログラムの構造とプログラム) NEXT(キーボードの状態取得(API))