9:共通クラスを作る
テクスチャ、プレイヤー、敵、背景、BGM、etc...。とにかくゲームには様々な要素が詰まっていますが、これらをまとめて一元管理できるクラスを作ると、以下のようなメリットを得ることができます。
[DirectXデバイスを共有できる] 基本クラスの中にstatic宣言で、ウィンドウハンドラ(HWND)やDirectX関連のオブジェクトを格納しておけば、externを使うことなく、これらの値を共有することができ、プログラム的にもスッキリします。
[オブジェクト管理が簡単になる] すべての派生クラスは基本クラスのポインタ型に代入が可能です。つまり、派生クラスをすべて基本クラスとしても処理できるので、基本クラスリストにすべて詰め込んでおけば、プログラムの管理が簡単になります。
[ゲーム処理に柔軟に対応できる] 仮想関数の概念を使えば、リスト内容をループで回してやるだけで、登録したすべてのオブジェクトを実行させることができ、ひとつひとつのオブジェクトに対して固有の命令を与える必要がありません。仮想関数については後述。

(ゲームクラスのイメージ)
#pragma once
class CGameObject
{
public:
void Initialize(); // 初期化時に呼び出す
void Uninitialize(); // 終了時に呼び出す
};
#include "GameObject.h"
void CGameObject::Initialize()
{
}
void CGameObject::Uninitialize()
{
}
once
」はそのコードが記述されているファイルを2回以上読み込むのを禁止するためのプリプロセッサです。Microsoft社のCコンパイラ以外では無効となりますが、代わりに以下のように記述することで、他社のコンパイラでも二重読み込みを防止することができます。
#ifndef CGAMEOBJECT
// ↑↓宣言名は、このファイル以外で使われる可能性がないのであれば何でもよい
#define CGAMEOBJECT
class CGameObject
{
public:
void Initialize(); // 初期化時に呼び出す
void Uninitialize(); // 終了時に呼び出す
};
#endif
これらをふまえて修正したコード例は次の通りです。
#pragma once
#include <tchar.h>
#include <windows.h>
#include <dxerr9.h>
#include <d3d9.h>
#include <d3dx9.h>
#define RELEASE(x) {if(x) x->Release();}
class CGameObject
{
private:
static HWND hWnd;
static HINSTANCE hInstance;
public:
static const HWND GetHWnd(){ return hWnd; }
static const HINSTANCE GetHInstance(){ return hInstance; }
BOOL Initialize(HWND hWnd, HINSTANCE hInstance);
void Uninitialize();
protected:
static LPDIRECT3D9 pD3D;
static LPDIRECT3DDEVICE9 pD3Ddevice;
static LPD3DXSPRITE pSprite;
};
#include "GameObject.h"
HWND CGameObject::hWnd = NULL;
HINSTANCE CGameObject::hInstance = NULL;
LPDIRECT3D9 CGameObject::pD3D = NULL;
LPDIRECT3DDEVICE9 CGameObject::pD3Ddevice = NULL;
LPD3DXSPRITE CGameObject::pSprite = NULL;
BOOL CGameObject::Initialize(HWND hWnd, HINSTANCE hInstance)
{
this->hWnd = hWnd;
this->hInstance = hInstance;
pD3D = Direct3DCreate9(D3D_SDK_VERSION);
if(pD3D == NULL){
DXTRACE_MSG(_T("DirectXDeviceの初期化に失敗しました"));
return FALSE;
}
D3DDISPLAYMODE d3ddm;
if(FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
{
DXTRACE_MSG(_T("DirectX3DDeviceの初期化に失敗しました"));
return FALSE;
}
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
if(FAILED(pD3D->CreateDevice(
D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,&pD3Ddevice)))
{
DXTRACE_MSG(_T("3DDeviceObjectの初期化に失敗しました"));
return FALSE;
}
pD3Ddevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
pD3Ddevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
pD3Ddevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
if(FAILED(D3DXCreateSprite(pD3Ddevice, &pSprite)))
{
DXTRACE_MSG(_T("SpriteObjectの作成に失敗しました"));
return FALSE;
}
return TRUE;
}
void CGameObject::Uninitialize()
{
RELEASE(pSprite);
RELEASE(pD3Ddevice);
RELEASE(pD3D);
}