スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

ウィンドウ生成部分とDirectXの部分を分けてみた

今日はプログラミングのお話。
現在、自作ゲームにおける根幹の部分を改修しております。

何をやったかと言うと、
-----------------------------------
・ウィンドウクラスの登録
・ウィンドウの生成
・DirectXの処理

-----------------------------------
これを複数のクラスに分割しなおしました。

以前はDirextXBaseというクラスを作成し、
そのクラスがウィンドウの生成からDirectXの初期化やら全部担当する設計だったので、
正直 柔軟性も何もあったもんじゃなかったです。
(我ながらひどい設計だったと思う)

今回はインターネット上のサイトや参考書を見ながら
もう一度作り直してみました。

で、どういう風にしたかと言うと、
まずアプリケーションの大まかな流れを決めるクラスを作成しました。

===================================================
【1】ApplicationBaseクラスの作成
===================================================

class ApplicationBase{
public:
HRESULT Run(HINSTANCE hinstance);
protected:
virtual HRESULT RegistWndClass(); //ウィンドウクラスを登録する関数
virtual HRESULT CreateMainWnd(); //ウィンドウを作成する関数
virtual HRESULT Initialize(); //初期化する関数
virtual HRESULT Loop(); //ゲームループを実行する関数
virtual HRESULT ReleaseApp(); //後処理をする関数
protected:
std::vector<Dix::sp<WindowBase>> m_WndBaseAry; //ウィンドウ作成担当のクラスのvector配列
HINSTANCE m_hInst; // アプリケーションハンドル
WNDCLASSEX m_WndClassEx; // ウィンドウクラス構造体
};


Run関数だけ公開しておき、他の関数はvirtualで 外部には非公開です。
で、Run関数の中身はこんな感じです。

HRESULT ApplicationBase::Run(HINSTANCE hinstance)
{
m_hInst = hinstance; // インスタンスハンドルの保持

if(RegistWndClass() != S_OK) // ウィンドウクラスの登録
return E_FAIL;

if(CreateMainWnd() != S_OK) // メインウィンドウの作成
return E_FAIL;

if(Initialize() != S_OK) // アプリケーションの初期化
return E_FAIL;

Loop(); //ゲームループ
ReleaseApp(); //開放処理

return(S_OK);
}


で、次にApplicationBaseクラスの派生クラスを作成します。

class DirectXAppBase : public ApplicationBase {
public:
DirectXAppBase();
~DirectXAppBase();
private:
HRESULT RegistWndClass();
HRESULT CreateMainWnd();
HRESULT Initialize();
HRESULT Loop();
HRESULT ReleaseApp();
private:
DirectXMainBase* m_DXObj; //DirectX独自の初期化処理とかを担当するクラス (後で解説)
};


派生クラスでは、基底クラス(ApplicationBase)の
virtualな関数をオーバーライドします。

こうしておけば、下記の様に呼び出すと、
------------------------
DirectXAppBase DBase;
DBase.Run(hInstance);

------------------------
オーバーライドで独自に定義した処理が実行されます。

基底クラスで 関数の呼び出し順を決めておき、
派生クラスで 呼び出す関数の処理内容を定義する
 といった感じです。

で、オーバーライドしたモノの中に、ウィンドウを作成する
CreateMainWnd関数があるのですが、

ここでは、ウィンドウの作成を担当するクラスを作り、
ウィンドウ作成は そのクラスに任せます。

HRESULT DirectXAppBase::CreateMainWnd()
{
Dix::sp wb(new DirectXWndBase());

if (wb->Create( m_hInst, m_WndClassEx.lpszClassName ) != S_OK){
return(E_FAIL);
}
m_WndBaseAry.push_back(wb);
}

※確認※
m_WndClassExというのは、ApplicationBaseクラスのメンバ。

DirectXAppBaseは派生クラスなので、ApplicationBaseクラスのメンバである
m_WndClassEx(WNDCLASSEX型の変数)を利用できる。

===================================================
【2】WindowBaseクラスの作成
===================================================
で、ウィンドウ作成を担当するWindowBaseクラスの内容は以下の通り。

class WindowBase
{
public:
WindowBase();
virtual ~WindowBase();
virtual LRESULT LocalWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); //ローカルなウィンドウプロシージャ
int Create(HINSTANCE hInstance, LPCWSTR classname); //2つの引数をとり、ウィンドウを作成する関数
HWND GetHandle(); //m_hWndを返す関数
private:
HWND m_hWnd; //後処理をする関数
};


ここで、注意点。
ウィンドウにはウィンドウプロシージャというものが必要なのですが、
ウィンドウプロシージャはグローバルな関数でなければならない
という面倒な制約があります。
--------------------------------------------------------------------
※ウィンドウプロシージャとは、「クリックされた」「右上の×が押された」などの
ウィンドウに関するメッセージを受け取って何らかの処理を実行する関数です。
--------------------------------------------------------------------

つまり、WindowBaseクラスでローカルなウィンドウプロシージャを定義しても、
グローバルじゃないから無効(エラー)、となってしまうのです。

これを解決するために、
ApplicationBaseクラスにグローバルなウィンドウプロシージャを持たせます。



<追記予定!>
スポンサーサイト

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

コメント

ApplicationBaseクラスの作成について

ApplicationBasicのstd::vector<Dix::sp<WindowBase>>m_WndBaseAry;
にある「Dix」はどうやって使っているんですか?
使い方を教えてください。

No title

>アチョビヤさん
あ、これは個人的に定義されたスマートポインタになります。
「ゲームつくろー」さんのHPで公開されているものを使用致しました。

http://marupeke296.com/TOOL_No12_LinkListSmartPtr.html

使い方についてですが、上記のスマートポインタは
「Dix」という名前空間が定められているので、

下記の様に、Dixという名前空間の中にある、
「sp」というクラスを使用しますよ、という記載をしています(_ _)
Dix::sp< //略

STLを使用された事があれば、
下記の様に「std」と指定するのと同じ理屈になりますv-411

std::vector< //略
コメントの投稿
管理者にだけ表示を許可する



上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。