#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>
#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>
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;
}
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));
}
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;
}
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);
}
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(FAILED(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;
}