製作開始

3Dブロック崩しの製作開始。の前に昨日描こうと思ってたラフ画を描いた。

ラフすぎるけど、この程度のゲームなら十分だろう。トラックボールだとペイントソフトがすごく描きにくい。ペンタブがほしいところだ。

さて、まずはウィンドウだけを出すプログラムを書く。すっかり言い忘れていたけど、開発はC++/DirectX9でやります。
WinMain関数はこんな感じ。

#include "stdafx.h"
#include "Game.h"

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){
	return CGame::Get()->Run(hInstance, lpCmdLine, nCmdShow);
}

CGameというゲームクラスオブジェクトのRunメソッドを呼ぶだけ。
そのRunメソッドの中で何をやるかというと、以下の通り。

  1. 多重起動防止処理
  2. コマンドラインの読み込み
  3. 環境設定の読み込み
  4. ウィンドウの生成
  5. DirectXの初期化
  6. ゲームデータのロード
  7. ゲームの初期化
  8. メインループ
  9. 各種終了処理

2,6,7は今のところやることがないのでカラ。
1はMutexオブジェクトで排他処理をしている。
3は後々環境設定ダイアログなんかで設定できるようしてそれを読み込む予定。今はメッセージボックスを出してフルスクリーンかウィンドウかを選ばせるだけ。
4はWindowsプログラミング入門でやるようなウィンドウの生成をする。ここでインスタンスハンドルhInstanceと表示方法を指定するnCmdShowを使う。
5がまあある意味今回のメイン。最初はサウンドや入力はおいといて、Direct3Dの初期化だけをやる。これもDirectXの入門サイトにあるような初期化コードほぼそのまま。

bool CDirect3D::Init(HWND hWnd, BOOL bFullScreen, int screenWidth, int screenHeight){
	if((pD3D_ = Direct3DCreate9(D3D_SDK_VERSION)) == NULL){
		return false;
	}

	D3DDISPLAYMODE d3ddm;
	if(FAILED(pD3D_->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))){
		return false;
	}

	ZeroMemory(&D3DPP_, sizeof(D3DPRESENT_PARAMETERS));

	D3DPP_.BackBufferCount = 1;
	D3DPP_.Windowed = !bFullScreen;
	if(bFullScreen){
		D3DPP_.BackBufferWidth = screenWidth;
		D3DPP_.BackBufferHeight = screenHeight;
	}else{
		D3DPP_.BackBufferWidth = 0;
		D3DPP_.BackBufferHeight = 0;
	}
	D3DPP_.BackBufferFormat = d3ddm.Format;
	//D3DPP_.MultiSampleType = D3DMULTISAMPLE_NONE;
	D3DPP_.hDeviceWindow = hWnd;
	D3DPP_.SwapEffect = D3DSWAPEFFECT_DISCARD;
	//D3DPP_.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
	D3DPP_.PresentationInterval = D3DPRESENT_INTERVAL_ONE;    // VSYNCを待つ
	D3DPP_.EnableAutoDepthStencil = TRUE;
	D3DPP_.AutoDepthStencilFormat = D3DFMT_D16;
	//D3DPP_.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;

	if(FAILED(pD3D_->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &D3DPP_, &pD3DDevice_))){
		if(FAILED(pD3D_->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &D3DPP_, &pD3DDevice_))){
			if(FAILED(pD3D_->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &D3DPP_, &pD3DDevice_))){
				return false;
			}
		}
	}
	return true;
}

プレゼンテーションパラメータでコメントアウトしてある部分はデフォルト設定だから。
で、初期化したら8でメインループをまわす。

//DirectXの初期化
CDirect3D* pDirect3D = new CDirect3D;
if(!pDirect3D->Init(hWnd, bFullScreen, width, height)){
	MessageBox(NULL, _T("Direct3Dの初期化に失敗しました"), _T("起動失敗"), MB_OK);
	return 0;
}
	
//メインループ
MSG msg;
while(true){
	if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
		if(msg.message == WM_QUIT) break;
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}else{
		//1フレームの移動・判定処理はここ
		if(pDirect3D->BeginRender()){
			//1フレームの描画処理はここ
			if(!pDirect3D->EndRender()) break;
		}
		Sleep(1);
	}
}

Sleep(1)を噛ませているのは、非アクティブにするとビジーループになるゲームがたまにあって、それが気持ち悪いので対処。これが正しいやり方なのかどうかはわからない。


ふう。コードを載せると間延びする。
次にオブジェクトのモデルを作る・・・というところでいい時間なので明日にしよう。
この記録を書くのに結構時間を使ってしまうなあ。