2Dゲームの最低必要要素である
SIZE(20){ COLOR(#ffaa00){・入力}}
SIZE(20){ COLOR(#ffaa00){・画像表示}}
SIZE(20){ COLOR(#ffaa00){・サウンド再生}}
をやってきました
今回はそれをまとめます

入力は、DirectX講座2回 
画像描画は、DirectX講座10回 
サウンド再生は、DirectX講座12回 
で、すでにやりました
この3つを合体させます

具体的には12回のプログラムに10回のプログラムを合体します
クラスに関しては変更はありません

今回使うファイルは次のようになってます。どぞー(-ω-)つ旦
・&ref(framework.cpp);
・&ref(car.bmp);
・&ref(katana.wav);
・&ref(bomb.wav);
zipでほしい人はこちら
・&ref(framework.zip);

 // Direct3Dに必要なヘッダーとライブラリ
 #define _CRT_SECURE_NO_WARNINGS
 
 //////////////////////////////////////////////////////////////////////
 #define D3D_DEBUG_INFO	// Direct3Dデバックフラグ
 
 #pragma comment(lib, "d3d9.lib")
 #pragma comment(lib, "d3dx9.lib")
 #pragma comment(lib, "d3dxof.lib")
 #pragma comment(lib, "dxguid.lib")
 #pragma comment(lib, "winmm.lib")
 #include <comdef.h>
 #include <d3d9.h>
 #include <d3dx9.h>
 #include <mmsystem.h>
 
 //////////////////////////////////////////////////////////////////////
 // DirectSoundに必要なヘッダーとライブラリ
  
 #define DIRECTSOUND_VERSION 0x800	// DirectSoundのバージョン
 
 #pragma comment(lib, "dsound.lib")
 #pragma comment(lib, "d3dxof.lib")
 #pragma comment(lib, "dxguid.lib")
 
 #include <comdef.h>
 #include <dsound.h>
 
 //////////////////////////////////////////////////////////////////////
 
 #include <Windows.h>
 #include <tchar.h>
 
 
 //////////////////////////////////////////////////////////////////////
 
 // Direct3Dクラス
 class Direct3D
 {
 public:
	IDirect3D9*			pD3D9;			// Direct3Dデバイス生成用オブジェクト
	IDirect3DDevice9*		pDevice3D;		// Direct3Dのデバイス
 
	// コンストラクタ
	Direct3D();
	// デストラクタ
	~Direct3D();
 
	// デバイス作成
	bool Create(HWND hWnd,int Width,int Height);
 };
 
 // コンストラクタ
 Direct3D::Direct3D(){
	pD3D9 = NULL;			// Direct3Dデバイス生成用オブジェクト
	pDevice3D = NULL;		// Direct3Dのデバイス
 }
 // デストラクタ
 Direct3D::~Direct3D(){
	// DirectXの変数は必ず後処理をすること
	if(pDevice3D != NULL)
		pDevice3D->Release();
	if(pD3D9 != NULL)
		pD3D9->Release();
 }
 
 // デバイス作成
 bool Direct3D::Create(HWND hWnd,int Width,int Height){
 	
	// Direct3D9オブジェクトの作成	
	pD3D9 = Direct3DCreate9(D3D_SDK_VERSION);	
	// ディスプレイ情報取得
	D3DDISPLAYMODE Display;
	pD3D9->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &Display);
 
	D3DPRESENT_PARAMETERS	D3DParam = {			// スワップチェイン設定
		Width,Height,Display.Format,1,D3DMULTISAMPLE_NONE,0,
		D3DSWAPEFFECT_DISCARD,hWnd,TRUE,TRUE,D3DFMT_D24S8,0,0,D3DPRESENT_INTERVAL_DEFAULT
	};			
 	
	// HALモードで3Dデバイス作成
	if (FAILED(pD3D9->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, D3DParam.hDeviceWindow,
		D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &D3DParam, &pDevice3D)))
	if (FAILED(pD3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DParam.hDeviceWindow, 
		D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &D3DParam, &pDevice3D)))
	// REFモードで3Dデバイス作成
	if (FAILED(pD3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, D3DParam.hDeviceWindow, 
		D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &D3DParam, &pDevice3D)))
	if (FAILED(pD3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, D3DParam.hDeviceWindow, 
		D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &D3DParam, &pDevice3D)))
	{
		// 3Dデバイス作成失敗(このグラフィックボードではDirectXが使えない)
		pD3D9->Release();
		return false;
	}
 
	return true;
 }
 
 ///////////////////////////////////////////////////////////////////
 
 // テクスチャクラス
 class Texture
 {
 public:
	IDirect3DTexture9* pTexture;
	// コンストラクタ
	Texture();
	// デストラクタ
	~Texture();
	// 画像データ読み込み
	bool Load(IDirect3DDevice9* pDevice3D,TCHAR* FileName);
 };
 
 Texture::Texture(){
	pTexture = NULL;
 }
 Texture::~Texture()
 {
	// 読み込まれていたら破棄
	if(pTexture != NULL)
		pTexture->Release();
 }
 bool Texture::Load(IDirect3DDevice9* pDevice3D,TCHAR* FileName)
 {
	// 画像読み込み
	// DirextXやWindowsAPIの関数はHRESULTを結果に返す関数が多い
	// FAILEDマクロで関数が失敗したかわかる
	// SUCEEDEDマクロで関数が成功したかわかる
	if(FAILED(D3DXCreateTextureFromFile(pDevice3D,FileName,&pTexture)))
		return false;	// 画像読み込み失敗(ファイルがない可能性あり)
 
	// 画像読み込み成功
	return true;
 }
 
 //////////////////////////////////////////////////////////////////////
 
 // スプライトクラス(2D板ポリゴン)
 class Sprite
 {
 public:
	// 板ポリゴン頂点情報
	struct Vertex{
		float x,y,z;// 3次元座標
		float rhw;	// 2D変換済みフラグ
		float u,v;	// UV座標
	};
	// FVF(柔軟な頂点構造体宣言)フラグ
	static const DWORD SPRITE_FVF = D3DFVF_XYZRHW | D3DFVF_TEX1;
 	
	// スプライト位置
	D3DXVECTOR2 pos;
	// スプライトサイズ
	int width;
	int height;
 
	// コンストラクタ
	Sprite();
	// デストラクタ
	~Sprite();
 
	void SetPos(float x,float y);
	void SetWidth(int Width,int Height);
	void Draw(IDirect3DDevice9* pDevice3D,IDirect3DTexture9* pTexture);
 
 };
 
 // コンストラクタ
 Sprite::Sprite()
 {
	pos.x = pos.y = 0.0f;
	width = 0;
	height = 0;
 }
 // デストラクタ
 Sprite::~Sprite(){}
 
 void Sprite::SetPos(float x,float y)
 {
	pos.x = x;
	pos.y = y;
 }
 void Sprite::SetWidth(int Width,int Height)
 {
	width = Width;
	height = Height;
 }
 
 void Sprite::Draw(IDirect3DDevice9* pDevice3D,IDirect3DTexture9* pTexture)
 {
	// 頂点情報セット
	Vertex vtx[4]={
		{ pos.x + width/2, pos.y - height/2, 0.0f, 1.0f, 1.0f, 0.0f},
		{ pos.x + width/2, pos.y + height/2, 0.0f, 1.0f, 1.0f, 1.0f}, 
		{ pos.x - width/2, pos.y - height/2, 0.0f, 1.0f, 0.0f, 0.0f}, 
		{ pos.x - width/2, pos.y + height/2, 0.0f, 1.0f, 0.0f, 1.0f} 
	};
 
	// テクスチャセット
	pDevice3D->SetTexture(0,pTexture);
	// 頂点構造体宣言セット
	pDevice3D->SetFVF(SPRITE_FVF);
	// スプライト描画
	pDevice3D->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,vtx,sizeof(Vertex));
 }
 
 ///////////////////////////////////////////
 
 // DirectSoundクラス
 class DirectSound
 {
 public:
	IDirectSound8*	pDirectSound8; // DirectSoundデバイス
 	
	// コンストラクタ
	DirectSound();
	// デストラクタ
	~DirectSound();
 
	bool Create(HWND hWnd);
 };
 
 // コンストラクタ
 DirectSound::DirectSound()
 {
	pDirectSound8 = NULL;	// DirectSoundデバイス
 }
 // デストラクタ
 DirectSound::~DirectSound()
 {
	if(pDirectSound8 != NULL)
		pDirectSound8->Release();
 }
 
 bool DirectSound::Create(HWND hWnd)
 {
	// サウンドデバイス作成
	DirectSoundCreate8(NULL, &pDirectSound8, NULL);	
	// 協調レベルのセット(ここで音を鳴らすウィンドウを指定する必要がある)
	if (FAILED(pDirectSound8->SetCooperativeLevel(hWnd, DSSCL_PRIORITY)))
	{
		// 失敗
		return false;
	}
 
	return true;
 }
 
 ////////////////////////////////////////////
 
 class Wave{
 public:
	WAVEFORMATEX		WaveFormat;	// Waveフォーマット
	byte*			WaveData;	// 音の生データ
	int			DataSize;	// データサイズ
 
	// コンストラクタ
	Wave();
	// デストラクタ
	~Wave();
 
	// Wavファイル読み込み
	bool Load(TCHAR* FileName);
 };
 
 // コンストラクタ
 Wave::Wave()
 {
	memset(&WaveFormat,0,sizeof(WAVEFORMATEX));
	WaveData = NULL;
	DataSize = 0;
 }
 // デストラクタ
 Wave::~Wave()
 {
	if(WaveData != NULL)
		delete[] WaveData;
 }
 
 // Wavファイル読み込み
 bool Wave::Load(TCHAR* FileName)
 {
 
	// バイナリ読み込みモードで開く
	FILE* fp;
	if (!(fp = ::_tfopen(FileName, _T("rb") )))
		return false;
 
	char chunkId[5] = {};
	char tmp[5] = {};
	unsigned int chunkSize = 0;
 
	// RIFFチャンク読み込み
	fread(chunkId, sizeof(char) * 4, 1, fp);
	fread(&chunkSize, sizeof(unsigned int), 1, fp);
	fread(tmp, sizeof(char) * 4, 1, fp);
	if (strcmp(chunkId, "RIFF") || strcmp(tmp, "WAVE")){
		return false;	// Waveファイルじゃない
	}
 
	// 子チャンク読み込み
	bool fmtchunk	= false;
	bool datachunk	= false;
	while (true)
	{
		fread(chunkId, sizeof(char) * 4, 1, fp);
		fread(&chunkSize, sizeof(unsigned int), 1, fp);
		if (!strcmp(chunkId, "fmt "))
		{
			if (chunkSize >= sizeof(WAVEFORMATEX))
			{
				fread(&WaveFormat, sizeof(WAVEFORMATEX), 1, fp);
				int diff = chunkSize - sizeof(WAVEFORMATEX);
				fseek(fp, diff, SEEK_CUR);
			}
			else
			{
				memset(&WaveFormat, 0, sizeof(WAVEFORMATEX));
				fread(&WaveFormat, chunkSize, 1, fp);
			}
			fmtchunk = true;
		}
		else if (!strcmp(chunkId, "data"))
		{
			// データサイズ確保
			DataSize = chunkSize;
			WaveData = new byte[chunkSize];
			// データ読み込み
			if (fread(WaveData, sizeof(byte), chunkSize, fp) != chunkSize)
			{
				fclose(fp);
				return false;	// ファイルが壊れている
			}
			datachunk = true;
		}
		else
		{
			fseek(fp, chunkSize, SEEK_CUR);
		}
 
		if (fmtchunk && datachunk)
			break;
 
		// ファイルサイズチェックも行なった方がいいかも
	}
 
	fclose(fp);
	return true;
 }
 
 ////////////////////////////////////////////////
 
 class SoundBuffer
 {
 public:
	IDirectSoundBuffer8*	pSecondaryBuffer;	// セカンダリバッファ
 	
	// コンストラクタ
	SoundBuffer();
	// デストラクタ
	~SoundBuffer();
 
	bool Create(IDirectSound8*	pDirectSound8,WAVEFORMATEX& WaveFormat,byte* WaveData,int DataSize);
 
	void Play(bool isLoop);
	void Stop();
 };
 
 // コンストラクタ
 SoundBuffer::SoundBuffer()
 {
	pSecondaryBuffer = NULL;
 }
 // デストラクタ
 SoundBuffer::~SoundBuffer()
 {
	Stop();	// セカンダリバッファは破棄する前に再生停止すること
 
	if(pSecondaryBuffer != NULL)
		pSecondaryBuffer->Release();
 }
 
 bool SoundBuffer::Create(IDirectSound8*	pDirectSound8,WAVEFORMATEX& WaveFormat,byte* WaveData,int DataSize)
 {
 	
	DSBUFFERDESC	desc = {};			// セカンダリバッファ作成用設定
	// チャンネル数での分岐、モノラルは1チャンネル、ステレオは2チャンネル
	if(WaveFormat.nChannels == 1){
		desc.dwFlags =  DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY |
			DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_STATIC;	
		desc.guid3DAlgorithm = DS3DALG_NO_VIRTUALIZATION;
	}
	else{
		desc.dwFlags =  DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY | 
			DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_CTRLPAN | DSBCAPS_STATIC;   
		// | DSBCAPS_CTRLFX;	エフェクトを追加すると Duplicate できない
		desc.guid3DAlgorithm = GUID_NULL;	
	}
	desc.dwSize	= sizeof(DSBUFFERDESC);
	desc.dwBufferBytes		= DataSize;			// 音データサイズ指定
	desc.lpwfxFormat		= &WaveFormat;		// フォーマット指定
 
	IDirectSoundBuffer*	pPrimaryBuffer = NULL;	// プライマリバッファ
	// プライマリバッファ作成
	pDirectSound8->CreateSoundBuffer(&desc,&pPrimaryBuffer,NULL);
	// プライマリバッファからセカンダリバッファ作成
	pPrimaryBuffer->QueryInterface(IID_IDirectSoundBuffer8, (void**)&pSecondaryBuffer);
	pPrimaryBuffer->Release();	// セカンダリバッファが作成できれば、プライマリバッファは破棄してかまわない
 
	unsigned char* block1		= NULL;
	unsigned char* block2		= NULL;
	unsigned long blockSize1	= 0;
	unsigned long blockSize2	= 0;
	// セカンダリバッファをロックしてデータ書き込み
	pSecondaryBuffer->Lock(0, DataSize, 
		(void**)&block1, &blockSize1, (void**)&block2, &blockSize2, DSBLOCK_ENTIREBUFFER); 
	// セカンダリバッファに音データコピー
	memcpy(block1, WaveData, DataSize);
	// セカンダリバッファロック解除
	pSecondaryBuffer->Unlock(block1, blockSize1, block2, 0);
 
	return true;
 }
 
 void SoundBuffer::Play(bool isLoop)
 {
	// サウンド再生
	if(pSecondaryBuffer != NULL){
		DWORD LoopFlag = (isLoop ? DSBPLAY_LOOPING : 0);
		pSecondaryBuffer->Play(0,0,LoopFlag);
	}
 }
 void SoundBuffer::Stop()
 {
	if(pSecondaryBuffer != NULL)
		pSecondaryBuffer->Stop();
 }
 
 //////////////////////////////////////////////////////////////////////
 
 // ウィンドウプロシージャ、ウィンドウに対するメッセージ処理を行う
 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
 	
	switch(msg){
		// ウィンドウが破棄されたとき
	case WM_DESTROY:
		PostQuitMessage(0);	// WM_QUITメッセージをメッセージキューに送る
		return 0;
	}
	// デフォルトのメッセージ処理を行う
	return DefWindowProc(hWnd, msg, wParam, lParam);
 }
 
 // WinMain関数(アプリケーションの開始関数)
 // コンソールアプリケーションと違い、コンソールを開かない
 int _stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
 {
	const TCHAR* WC_BASIC = _T("BASIC_WINDOW");
	// シンプルウィンドウクラス設定
	WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,WndProc, 0,0,hInstance,
		(HICON)LoadImage(NULL,MAKEINTRESOURCE(IDI_APPLICATION),IMAGE_ICON,0,0,LR_DEFAULTSIZE | LR_SHARED),
		(HCURSOR)LoadImage(NULL,MAKEINTRESOURCE(IDC_ARROW),IMAGE_CURSOR,0,0,LR_DEFAULTSIZE | LR_SHARED), 
		(HBRUSH)GetStockObject(WHITE_BRUSH), NULL, WC_BASIC , NULL};
 
	// シンプルウィンドウクラス作成
	if(!RegisterClassEx(&wcex)) 
		return false;
 
	// ウィンドウ幅、高さはディスプレイに依存する。普通は4:3
	const int WINDOW_WIDTH = 640;
	const int WINDOW_HEIGHT = 480;
	// ウィンドウの作成
	HWND hWnd = CreateWindowEx(0,WC_BASIC,
		_T("Application"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_VISIBLE,
		CW_USEDEFAULT,CW_USEDEFAULT,WINDOW_WIDTH,WINDOW_HEIGHT,NULL,NULL,hInstance,NULL);
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
	////////////////////////////////////
	//	Direct3Dの初期化
	////////////////////////////////////
	Direct3D direct3d;
	direct3d.Create(hWnd,WINDOW_WIDTH,WINDOW_HEIGHT);
 
	////////////////////////////////
	// テクスチャ作成
	////////////////////////////////
	Texture cartex;
	cartex.Load(direct3d.pDevice3D,_T("car.bmp"));
 
	////////////////////////////////
	// スプライト作成
	////////////////////////////////
	Sprite sprite[2];
 
	sprite[0].SetPos(100,100);
	sprite[0].SetWidth(128,128);
	sprite[1].SetPos(300,300);
	sprite[1].SetWidth(128,128);
 	
 ///////////////////////////////////////////////////////////////////////////////////////////////
 	
	////////////////////////////////
	// DirectSoundデバイス作成
	////////////////////////////////
	DirectSound directsound;
	directsound.Create(hWnd);
 
	///////////////////////////////////////////////
	//	Waveファイル読込み
	///////////////////////////////////////////////
	Wave wave[2];
	wave[0].Load(_T("katana.wav"));
	wave[1].Load(_T("bomb.wav"));
 	
 
	///////////////////ファイル読込みはここまで
 
	/////////////////////////////////
	//	セカンダリバッファの作成
	//	(読み込んだ音データをコピー)
	/////////////////////////////////
	SoundBuffer sb[2];
	for(int i = 0;i < 2;++i)
		sb[i].Create(directsound.pDirectSound8,wave[i].WaveFormat,wave[i].WaveData,wave[i].DataSize);
 
 
	// ループ再生
	sb[0].Play(true);
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
	// メッセージループ
	MSG msg = {}; 
	while(msg.message != WM_QUIT) {
		// アプリケーションに送られてくるメッセージをメッセージキューから取得する
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
			DispatchMessage(&msg);	// アプリケーションの各ウィンドウプロシージャにメッセージを転送する
		}
		// メッセージ処理をしていないとき
		else{
			//(ここにDirectXの処理を書く)
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
			// 描画開始
			if(SUCCEEDED(direct3d.pDevice3D->BeginScene()))
			{
				DWORD ClearColor = 0xff808080;	// 背景クリア色
				// 背景クリア
				direct3d.pDevice3D->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER, ClearColor, 1.0f, 0 );
 
				// 再生
				if(GetAsyncKeyState('A'))
					sb[1].Play(false);
 				
				// スプライト描画
				for(int i = 0;i < 2;++i){
					sprite[i].Draw(direct3d.pDevice3D,cartex.pTexture);
				}
 
				// 描画終了
				direct3d.pDevice3D->EndScene();
			}
			// 描画反映
			direct3d.pDevice3D->Present( NULL, NULL, NULL, NULL );
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
		}
	}
 
 	
	return 0;
 }

描画は講座10回と変わりません
そこにサウンド再生が加わります
さらにAキーで追加のサウンドを再生します
&ref("framework.jpg");

今回で2Dゲームに最低限必要なものがそろったので
簡単なゲームくらい作れるようになるはずです

そろそろプログラムが長くなってきました(500行越え)
プログラムが長くなってきたら1つのファイルで管理をすることが困難になってきます(見づらい+追加が大変+バグなどが発見しにくい)
なので、次回はC/C++で別ファイルにプログラムを分割する方法を説明します

前:DirectX講座12回
次:DirectX講座14回

#vote( (^σ^)ウマー[2],動けぇぇぇえええ[1],おまえはもう死んでいる[2])
#vote( (^σ^)ウマー[2],動けぇぇぇえええ[2],おまえはもう死んでいる[2])



トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS