ホーム < ゲームつくろー! < DirectX技術編 < Xファイルのカスタムテンプレートを使ってみよう:サンプルプログラム


その32 Xファイルのカスタムテンプレートを使ってみよう:サンプルプログラム


 DirectX技術編その32「Xファイルのカスタムテンプレートを使ってみよう」で説明した内容を踏まえたサンプルプログラムです。実行すると、PersonID.xというテンプレートを定義したファイルからテンプレート定義を読み込み、それを登録した後に、TestID.xという名前とID番号が入ったデータを読みに行き、Xファイルの仕様に従ってデータを格納して、画面に表示します。


サンプルスクリーンショット

 以下のプログラムは指定のカスタムテンプレート(PersonID.x)及びデータファイル(TestID.x)をパスの通った場所に置き、空のプロジェクトにコピペすることで完全に動きます。PersonIDテンプレートは世界に一つしかない番号が振られておりますので、こちらからファイルをダウンロードしてください。上からデバッグしていくと、何をしているか良くわかるように1つのソースで完結させています。今回のポイントになりそうなところは太文字で示されています。

(もしうまく動かないようでしたら掲示板にてご連絡下さい)

/// XFileカスタムテンプレート読み込みテスト

#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "d3dxof.lib")

#include <windows.h>
#include <tchar.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <dxfile.h>   // Xファイル関連を使用するのに必要
#include <fstream>
#include <vector>
#include <string>

using namespace std;

#if _UNICODE
   typedef wstring gstring;
#else
   typedef string gstring;
#endif

TCHAR gName[] = _T("XFileカスタムテンプレート読み込みテスト");


// 文字コード対応文字列代入関数
void COPYSTR_To_STL( gstring &stl, const char *str )
{
#if _UNICODE
   TCHAR *Buf = _T("");
   int num = MultiByteToWideChar(CP_ACP, 0, str, -1, Buf, 0);
   Buf = new TCHAR[num];
   MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, Buf, num);
   stl = Buf;
   delete Buf;
#else
   stl = str;
#endif
}


// テキストファイルをメモリにコピーする関数
char* GetFileText( char* filename ){
   ifstream ifs;
   ifs.open( filename );
   if( !ifs.is_open() )
      return NULL;
   DWORD FileSize=0;
   while(!ifs.eof()){ ifs.ignore(); FileSize++;}  // サイズ取得
   ifs.clear(); ifs.seekg(0, ios_base::beg);      // ファイルポインタを初期位置へ
   char* tmp = new char[FileSize];
   ZeroMemory( tmp, FileSize );
   ifs.read( tmp, FileSize-1);
   return tmp;
}


LRESULT CALLBACK WndProc(HWND hWnd, UINT mes, WPARAM wParam, LPARAM lParam){
   if(mes == WM_DESTROY) {PostQuitMessage(0); return 0;}
   return DefWindowProc(hWnd, mes, wParam, lParam);
}

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
   // アプリケーションの初期化
   MSG msg; HWND hWnd;
   WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInstance, NULL, NULL,
                                    (HBRUSH)(COLOR_WINDOW+1), NULL, (TCHAR*)gName, NULL};
   if(!RegisterClassEx(&wcex))
      return 0;

   if(!(hWnd = CreateWindow(gName, gName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
                                    NULL, NULL, hInstance, NULL)))
      return 0;

   // Direct3Dの初期化
   LPDIRECT3D9 g_pD3D;
   LPDIRECT3DDEVICE9 g_pD3DDev;
   if( !(g_pD3D = Direct3DCreate9( D3D_SDK_VERSION )) ) return 0;

   D3DPRESENT_PARAMETERS d3dpp = {0,0,D3DFMT_UNKNOWN,0,D3DMULTISAMPLE_NONE,0,
                                                      D3DSWAPEFFECT_DISCARD,NULL,TRUE,0,D3DFMT_UNKNOWN,0,0}; 

   if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDev ) ) )
   if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDev ) ) )
   {
      g_pD3D->Release();
      return 0;
   }

   // カスタムテンプレートファイルからテンプレート定義を抽出
   char* g_pTEMPLATE_PERSONID = GetFileText( "PersonID.x" );
   if( !g_pTEMPLATE_PERSONID ){
      g_pD3DDev->Release(); g_pD3D->Release(); return 0;
   }

   // テンプレートを登録
   IDirectXFile *pDXFile;
   DirectXFileCreate( &pDXFile );
   if(FAILED(pDXFile->RegisterTemplates( g_pTEMPLATE_PERSONID, strlen( g_pTEMPLATE_PERSONID ) ))){
      g_pD3DDev->Release(); g_pD3D->Release(); return 0;
   }

   // ファイルからテンプレートデータを列挙するインターフェイスを取得
   IDirectXFileEnumObject *pEnumObj;
   if(FAILED(pDXFile->CreateEnumObject( "TestID.x", DXFILELOAD_FROMFILE, &pEnumObj ))){
      pDXFile->Release(); g_pD3DDev->Release(); g_pD3D->Release(); return 0;
   }

   // テンプレート内のデータを取得
   IDirectXFileData *pDXData;
   DWORD Size;     // 取得したデータサイズ
   char **pName;   // 名前
   DWORD *pIDCode; // ID
   vector< gstring > VctName;   // 名前格納配列
   vector< DWORD > VctID;       // ID格納配列
   const GUID PersonID_GUID ={ 0xB2B63407,0x6AA9,0x4618, 0x95, 0x63, 0x63, 0x1E, 0xDC, 0x20, 0x4C, 0xDE};
   while( SUCCEEDED(pEnumObj->GetNextDataObject( &pDXData )) ){
      const GUID *guid;
      pDXData->GetType( &guid );
      if(*guid == PersonID_GUID)
      {
         // PersonIDテンプレートのデータなので、NameとIDCodeを取得
         HRESULT hr;
         hr = pDXData->GetData("Name", &Size, (void**)&pName );
         hr = pDXData->GetData("IDCode", &Size, (void**)&pIDCode );
         //取得したデータをコピー
         gstring str;
         COPYSTR_To_STL( str, *pName );
         VctName.push_back( str );
         VctID.push_back( *pIDCode );
      }
      pDXData->Release();   // データを取得したら解放が必要
   }

   // Xファイル関連のインターフェイスを解放
   pEnumObj->Release();
   pDXFile->Release();

   // フォントの生成
   int fontsize = 24;
   D3DXFONT_DESC lf = {fontsize, 0, 500, 1, 0, SHIFTJIS_CHARSET, OUT_TT_ONLY_PRECIS,
                        PROOF_QUALITY, DEFAULT_PITCH | FF_DONTCARE, _T("HG丸ゴシックM-PRO")};

   // ID3DXFontコンポーネント生成
   LPD3DXFONT pD3DFont;
   if(FAILED(D3DXCreateFontIndirect(g_pD3DDev, &lf, &pD3DFont))){
      g_pD3DDev->Release();  g_pD3D->Release();
      return 0;
   }

   ShowWindow(hWnd, nCmdShow);

   // メッセージ ループ
   DWORD DataNum = VctName.size();
   DWORD i;
   RECT r = {0,0,0,0};
   do{
      Sleep(1);
      if( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ){ DispatchMessage(&msg);}
         // Direct3Dの処理
         g_pD3DDev->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
         g_pD3DDev->BeginScene();

         for(i=0; i<DataNum; i++)
         {
             SetRect( &r, 0,0,0,0);
             // テキスト描画
               // Name
               pD3DFont->DrawText(NULL, VctName[i].c_str(), -1, &r, DT_CALCRECT | DT_LEFT | DT_SINGLELINE, 0xffffffff);
               r.top = i*fontsize; r.bottom = (i+1)*fontsize;
               pD3DFont->DrawText(NULL, VctName[i].c_str(), -1, &r, DT_LEFT | DT_SINGLELINE, 0xffffff00);
               
               // ID
               _TCHAR localstr[10];
               int a = _stprintf_s( localstr, 10, _T("%d"), VctID[i]);
               pD3DFont->DrawText(NULL, localstr, -1, &r, DT_CALCRECT | DT_LEFT | DT_SINGLELINE, 0xffffffff);
               r.left += fontsize*10; r.top = i*fontsize; r.right += fontsize*10; r.bottom = (i+1)*fontsize;
               pD3DFont->DrawText(NULL, localstr, -1, &r, DT_LEFT | DT_SINGLELINE, 0xffffff00);
         }

         g_pD3DDev->EndScene();
         g_pD3DDev->Present( NULL, NULL, NULL, NULL );
   }while(msg.message != WM_QUIT);

   pD3DFont->Release();
   g_pD3DDev->Release();
   g_pD3D->Release();

   return 0;
}