DirectX Graphics処理分割

WinMain.cppからDirectX Graphics関係の関数を抜き出し、NKC_DGraphics.cppというファイルに作成する方法を解説する。(1)でダウンロードしたファイルでプロジェクトを作成し、正しく実行されることを確認しておくこと。

ソースファイルの追加

DirectX Graphics系の関数を配置するためのソースファイルとして、NKC_DGraphics.cppという名前のファイルを作成する。手順は次のとおり。

  1. メニューの「プロジェクト」から「プロジェクトへ追加」、「新規作成」を選択。
  2. 新規作成ウィンドウから「C++ ソースファイル」を選択し、ファイル名を「NKC_DGraphics.cpp」と入力後、「OK」ボタンをクリックする。

これにより、中身のないファイルがプロジェクトに追加される。ここに、DirectX Graphics系の関数を配置していく。

myDGraphics.cppへプログラムを記述

作成したNKC_DGraphics.cppファイルに、プログラムを記述していく。C言語(C++)はソース・ファイルごとにコンパイルされるため、同じプロジェクト内のソースファイルでも、それぞれのソースファイルに対してインクルード処理、グローバル変数の宣言などを行わなければならない。(この辺りがVisual Basicなどと違って非常に面倒なところである・・・)

1.インクルード・ファイルの宣言

DirectX Graphics関係の関数(InitDX8、InitRender、ReleaseD3D、CreateStartTexture、ReleaseStartTexture、CreateGameTexture、ReleaseGameTexture)に必要なヘッダ・ファイルをインクルードする。ウィンドウを生成するわけではないので、windows.hやwindowsx.hは必要ない。

//=============================================================================
//  DirectX Graphics関係の自作関数群
//  Copyright NKC Game Staff(←自分の名前) 
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <d3d8.h>       // DirectX8ヘッダファイル
#include <d3dx8.h>      // D3DXヘッダファイル

2.マクロの宣言

WinMain.cppに宣言済みのマクロのうち、DirectX Graphics関係の関数に必要なものを宣言する。

// マクロ
#define WINMODE FALSE // ウィンドウモードの指定(TRUE:ウィンドウモード/FALSE:フルスクリーン)
#define SCREEN_WIDTH	640	// ウィンドウの幅
#define SCREEN_HEIGHT	480	// ウィンドウの高さ

3.グローバル変数の宣言

WinMain.cppに宣言済みのグローバル変数のうち、DirectX Graphics関係の関数に必要なものを宣言する。

// グローバル変数
/* 他のソースで宣言されているもの */
extern HWND hWnd;                       // ウィンドウハンドル
/* 他のソースからも利用されるもの */
LPDIRECT3DDEVICE8 gl_lpD3ddev = NULL;   // Direct3DDevice8インターフェイス
LPDIRECT3DTEXTURE8 gl_TXBack = NULL;    // 背景用テクスチャ
LPDIRECT3DTEXTURE8 gl_TXMyChara = NULL; // 自機用テクスチャ
LPDIRECT3DTEXTURE8 gl_TXEnemy = NULL;   // 敵用テクスチャ
/* 自ソースでのみ利用するもの */
static LPDIRECT3D8 gl_lpD3d = NULL;     // Direct3D8インターフェイス
static D3DPRESENT_PARAMETERS gl_d3dpp;  // ディスプレイパラメータ

《POINT》

4.プロトタイプ宣言

このソースに配置する関数のプロトタイプ宣言を行う。

// プロトタイプ宣言
/* 他のソースから呼び出されるもの */
HRESULT InitDX8(void);                  // DirectX8初期化処理
void InitRender(void);                  // 描画の設定
void ReleaseD3D(void);                  // DirectX8開放処理
void ResetWindow(void);                 // ウィンドウ再生成処理
void CreateStartTexture(void);          // スタート画面用テクスチャ作成処理
void ReleaseStartTexture(void);         // スタート画面用テクスチャ開放処理
void CreateGameTexture(void);           // ゲーム画面用テクスチャ作成処理
void ReleaseGameTexture(void);          // ゲーム画面用テクスチャ開放処理
/* 自ソースでのみ使用するもの */

《POINT》

5.関数の配置

8つの関数をこのソースに配置する(WinMain.cppからコピー)。配置後、WinMain.cppからは削除する。

//-----------------------------------------------------------------------------
// 関数名 : InitDX8() 
// 機能概要: Direct Draw オブジェクトの生成
// 戻り値 : 正常終了のとき:DD_OK、異常終了のとき:エラーコード
//-----------------------------------------------------------------------------
HRESULT InitDX8(void)
{
    ・
    ・
    ・
}

//-----------------------------------------------------------------------------
// 関数名 : InitRender()
// 機能概要: 描画の設定など
//-----------------------------------------------------------------------------
void InitRender(void)
{
    ・
    ・
    ・
}

//-----------------------------------------------------------------------------
// 関数名 : ReleaseD3D()
// 機能概要: DirectX8オブジェクトの開放
//-----------------------------------------------------------------------------
void ReleaseD3D(void)
{
    ・
    ・
    ・
}

//-----------------------------------------------------------------------------
// 関数名 : ResetWindow()
// 機能概要: ウィンドウの再設定
//-----------------------------------------------------------------------------
void ResetWindow(void)
{
    ・
    ・
    ・
}

//-----------------------------------------------------------------------------
// 関数名 : CreateStartTexture()
// 機能概要: スタート画面用テクスチャの作成・再生成
//-----------------------------------------------------------------------------
void CreateStartTexture(void)
{
    ・
    ・
    ・
}

//-----------------------------------------------------------------------------
// 関数名 : ReleaseStartTexture()
// 機能概要: スタート画面用テクスチャ開放処理
//-----------------------------------------------------------------------------
void ReleaseStartTexture(void)
{
    ・
    ・
    ・
}

//-----------------------------------------------------------------------------
// 関数名 : CreateGameTexture()
// 機能概要: ゲーム画面用テクスチャの作成・再生成
//-----------------------------------------------------------------------------
void CreateGameTexture(void)
{
    ・
    ・
    ・
}

//-----------------------------------------------------------------------------
// 関数名 : ReleaseGameTexture()
// 機能概要: ゲーム画面用テクスチャ開放処理
//-----------------------------------------------------------------------------
void ReleaseGameTexture(void)
{
    ・
    ・
    ・
}

《POINT》

WinMain.cppを修正

WinMain.cppを次のように修正する。

1.グローバル変数の修正

グローバル変数のうち、NKC_DGraphics.cppに本体があるものに対してextern宣言を行う。

// グローバル変数
/* 他ソースも利用するもの */
HWND hWnd;                              // ウィンドウハンドル
BOOL g_appActive = FALSE;               // ウィンドウの状態
/* NKC_DGraphics.cppに本体があるもの */
extern LPDIRECT3DDEVICE8 gl_lpD3ddev;   // Direct3DDevice8インターフェイス
extern LPDIRECT3DTEXTURE8 gl_TXBack;    // 背景用テクスチャ
extern LPDIRECT3DTEXTURE8 gl_TXMyChara; // 自機用テクスチャ
extern LPDIRECT3DTEXTURE8 gl_TXEnemy;   // 敵用テクスチャ
/* 自ソースでのみ利用するもの */
static char szWinName[] = "Exer007";        // ウィンドウクラス用文字列
static char szWinTitle[] = "ゲームを作りやすいプログラム"; // ウィンドウクラス用文字列
static BYTE g_FrameNo = START_INIT;         // フレーム選択用
static BYTE gl_KeyTbl[256];                 // キーボードの状態を格納
static RECT gl_rcScreen = {0, 0, 640, 480}; // ウィンドウ領域
static TLVERTX BackVertex[4];               // 背景用頂点情報配列
static TLVERTX MyCharaVertex[4];            // 自機用頂点情報配列
static RECT MyCharaHitRect;                 // 自機用当たり判定矩形
static TLVERTX EnemyVertex[4];              // 敵用頂点情報配列
static RECT EnemyHitRect;                   // 敵機用当たり判定矩形

2.DirectX Graphics系の関数を削除

DirectX Graphics系の処理を行う関数(InitDX8、InitRender、ReleaseD3D、CreateStartTexture、ReleaseStartTexture、CreateGameTexture、ReleaseGameTexture)はNKC_DGraphics.cppに配置したので、WinMain.cppからは削除する(NKC_DGraphics.cpp作成時、削除しているはず)。ただし、それらの関数はWinMain関数から呼び出すため、プロトタイプ宣言は残しておかなければならない
よって、WinMain.cppのプロトタイプ宣言は次のようになる。

// プロトタイプ宣言
/* NKC_DGraphics.cppで宣言されているもの */
HRESULT InitDX8(void);                                  // DirectX8初期化処理
void InitRender(void);                                  // 描画の設定
void ReleaseD3D(void);                                  // DirectX8開放処理
void ResetWindow(void);                                 // ウィンドウ再生成処理
void CreateStartTexture(void);                          // スタート画面用テクスチャ作成処理
void ReleaseStartTexture(void);                         // スタート画面用テクスチャ開放処理
void CreateGameTexture(void);                           // ゲーム画面用テクスチャ作成処理
void ReleaseGameTexture(void);                          // ゲーム画面用テクスチャ開放処理
/* 自ソースで宣言されているもの */
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM); 	// Windows関数
BOOL InitApp(HINSTANCE, int);                           // ユーザー関数
BOOL UpdateFrame(void);                                 // ゲームメイン処理
void StartInit(void);                                   // スタート画面初期化処理
void StartFrame(void);                                  // スタート画面処理
void GameInit(void);                                    // ゲーム画面初期化処理
void GameFrame(void);                                   // ゲーム画面処理
void InitVertex(LPTLVERTEX, float, float, float, float, int); // 頂点情報格納
void Move(LPTLVERTEX, float, float);                    // 移動処理
void MoveCheck(RECT, LPTLVERTEX);                       // 移動範囲の制限
bool HitCheck(LPTLVERTEX, LPTLVERTEX);                  // 当たり判定処理
bool HitCheck2(LPTLVERTEX, RECT, LPTLVERTEX, RECT);     // 当たり判定用矩形を用いた当たり判定処理

※ここまでの修正を行ったらビルドを行い、エラーが出ることなくプログラムが動作するかを確認する。

NKC_DGraphics.cpp用のヘッダ・ファイルを用意する

通常、他のソースにある関数を使う場合、使いたい関数をプロトタイプ宣言して使うのではなく、そのソースに存在する関数のプロトタイプ宣言がしてあるヘッダ・ファイルをインクルードして利用する。
現在のプログラムはNKC_DGraphics.cppにDirectX Graphics系の関数を作成し、WinMain.cppでプロトタイプ宣言をすることによりInitD3DやReleaseD3D関数などを利用しているが、これらをヘッダ・ファイルから利用するようにプログラムを修正する。

1.NKC_DGraphics.hの新規作成

NKC_DGraphics.cpp用のヘッダ・ファイルを「NKC_DGraphics.h」というファイル名で新規作成する。

  1. 「プロジェクト」→「プロジェクトへ追加」→「新規作成」を選択。
  2. 新規作成ウィンドウから「C/C++ヘッダーファイル」を選択し、ファイル名に「NKC_DGraphics.h」と入力し、位置がプロジェクトのフォルダになっていることを確認して、OKボタンをクリック。

2.NKC_DGraphics.hを編集

NKC_DGraphics.hに、NKC_DGraphics.cppで作成した関数のうち、他のソースから利用されるグローバル変数の宣言や、関数のプロトタイプ宣言を行う。

//-----------------------------------------------------------------------------
// File: NKC_DGraphics.h
// Desc: NKC_DGraphics.cppで使用するもののうち、他のソースでも使うものを宣言
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// マクロ
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// 構造体
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// グローバル変数
//-----------------------------------------------------------------------------
extern LPDIRECT3DDEVICE8 gl_lpD3ddev;   // Direct3DDevice8インターフェイス
extern LPDIRECT3DTEXTURE8 gl_TXBack;    // 背景用テクスチャ
extern LPDIRECT3DTEXTURE8 gl_TXMyChara; // 自機用テクスチャ
extern LPDIRECT3DTEXTURE8 gl_TXEnemy;   // 敵用テクスチャ

//-----------------------------------------------------------------------------
// プロトタイプ宣言
//-----------------------------------------------------------------------------
HRESULT InitDX8(void);                  // DirectX8初期化処理
void InitRender(void);                  // 描画の設定
void ReleaseD3D(void);                  // DirectX8開放処理
void ResetWindow(void);                 // ウィンドウ再生成処理
void CreateStartTexture(void);          // スタート画面用テクスチャ作成処理
void ReleaseStartTexture(void);         // スタート画面用テクスチャ開放処理
void CreateGameTexture(void);           // ゲーム画面用テクスチャ作成処理
void ReleaseGameTexture(void);          // ゲーム画面用テクスチャ開放処理

3.WinMain.cpp、NKC_DGraphics.cppファイルの編集

それぞれのソースファイルで宣言していたグローバル変数やプロトタイプ宣言は、NKC_DGraphics.hをインクルードすることで省略できる。次のように修正する。

  1. WinMain.cppからNKC_DGraphics.cppに関係するグローバル変数を削除する。
  2. WinMain.cppとNKC_DGraphics.cppから、NKC_DGraphics.hに宣言した8つのプロトタイプ宣言を削除する。
  3. WinMain.cppとNKC_DGraphics.cppでmyDGraphics.hをインクルードする。
    #include "NKC_DGraphics.h"

確認

上記1から3までの修正を行うと、WinMain.cpp、NKC_DGraphics.cppのヘッダ部分は次のようになる。

《WinMain.cpp》

//-------------------------------------------------------------------------------------------------
// 問題番号:Exer007
//  問題内容:ゲームを作りやすいプログラム
//  Copyright NKC Game Staff(←自分の名前) 
//-------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <windows.h>	// WindowsAPIを使用可能にする
#include <windowsx.h>
#include <d3d8.h>       // DirectX8ヘッダファイル
#include <d3dx8.h>      // D3DXヘッダファイル
#include "NKC_DGraphics.h"

// マクロ
#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
/* 頂点フォーマット(基本形)*/
#define FVF_TLVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)

// 構造体の宣言
/* 頂点構造体 */
typedef struct _TLVERTEX {
    float           x, y, z;                //位置情報
    float           rhw;                    //頂点変換値
    D3DCOLOR        color;                  //頂点カラー
    float           tu, tv;                 //テクスチャ座標
} TLVERTX, *LPTLVERTEX;

// グローバル変数
/* 他ソースも利用するもの */
HWND hWnd;                              // ウィンドウハンドル
BOOL g_appActive = FALSE;               // ウィンドウの状態
/* 自ソースでのみ利用するもの */
static char szWinName[] = "Exer007";        // ウィンドウクラス用文字列
static char szWinTitle[] = "ゲームを作りやすいプログラム"; // ウィンドウクラス用文字列
static BYTE g_FrameNo = START_INIT;         // フレーム選択用
static BYTE gl_KeyTbl[256];                 // キーボードの状態を格納
static RECT gl_rcScreen = {0, 0, 640, 480}; // ウィンドウ領域
static TLVERTX BackVertex[4];               // 背景用頂点情報配列
static TLVERTX MyCharaVertex[4];            // 自機用頂点情報配列
static TLVERTX EnemyVertex[4];              // 敵用頂点情報配列
static RECT MyCharaHitRect;                 // 自機用当たり判定矩形
static RECT EnemyHitRect;                   // 敵機用当たり判定矩形

// プロトタイプ宣言
/* 自ソースでのみ利用するもの */
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM); 	// Windows関数
BOOL InitApp(HINSTANCE, int);                           // ユーザー関数
BOOL UpdateFrame(void);                                 // ゲームメイン処理
void StartInit(void);                                   // スタート画面初期化処理
void StartFrame(void);                                  // スタート画面処理
void GameInit(void);                                    // ゲーム画面初期化処理
void GameFrame(void);                                   // ゲーム画面処理
void InitVertex(LPTLVERTEX, float, float, float, float, int); // 頂点情報格納
void Move(LPTLVERTEX, float, float);                    // 移動処理
void MoveCheck(RECT, LPTLVERTEX);                       // 移動範囲の制限
bool HitCheck(LPTLVERTEX, LPTLVERTEX);                  // 当たり判定処理
bool HitCheck2(LPTLVERTEX, RECT, LPTLVERTEX, RECT);     // 当たり判定用矩形を用いた当たり判定処理

《NKC_DGraphics.cpp》

//=============================================================================
//  DirectX Graphics関係の自作関数群
//  Copyright NKC Game Staff(←自分の名前) 
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <d3d8.h>       // DirectX8ヘッダファイル
#include <d3dx8.h>      // D3DXヘッダファイル
#include "NKC_DGraphics.h"

// マクロ
#define WINMODE FALSE // ウィンドウモードの指定(TRUE:ウィンドウモード/FALSE:フルスクリーン)
#define SCREEN_WIDTH	640	// ウィンドウの幅
#define SCREEN_HEIGHT	480	// ウィンドウの高さ

// グローバル変数
/* 他のソースで宣言されているもの */
extern HWND hWnd;                       // ウィンドウハンドル
/* 他のソースからも利用されるもの */
LPDIRECT3DDEVICE8 gl_lpD3ddev = NULL;   // Direct3DDevice8インターフェイス
LPDIRECT3DTEXTURE8 gl_TXBack = NULL;    // 背景用テクスチャ
LPDIRECT3DTEXTURE8 gl_TXMyChara = NULL; // 自機用テクスチャ
LPDIRECT3DTEXTURE8 gl_TXEnemy = NULL;   // 敵用テクスチャ
/* 自ソースでのみ利用するもの */
static LPDIRECT3D8 gl_lpD3d = NULL;     // Direct3D8インターフェイス
static D3DPRESENT_PARAMETERS gl_d3dpp;  // ディスプレイパラメータ

// プロトタイプ宣言
/* 自ソースでのみ使用するもの */

※ここまでの修正を行ったらビルドを行い、エラーが出ることなくプログラムが動作するかを確認する。

補足

今まですべてのプログラムを1本のソースファイルで作成していたため、ソースを分割するという作業は非常に面倒に感じるかもしれない。しかし、しっかりとしたルールを持って分割しておけば、ゲームの仕様変更に柔軟に対応できるプログラムを作ることができるはずである。
今はまだ難しく感じるだろうが、プログラムはひたすら数をこなし、慣れるしかない。コンテストに出品するゲームを製作するため、是非この技術を身につけましょう。


NEXT(ソース分割の考え方) NEXT(スタート処理分割)