#include < tchar.h > #include < windows.h > #include < dxerr9.h > #include < d3d9.h > #include < d3dx9.h > #include < vector > #pragma warning( disable : 4996 ) // 無駄な警告を出さなくする #include < strsafe.h > #pragma warning( default : 4996 ) //メモリリークを調べるために必要。 #if _DEBUG #include < crtdbg.h > #define new ::new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #endif #define WINDOW_WIDTH (640) // クライアント領域の幅 #define WINDOW_HEIGHT (480) // クライアント領域の高さ //クライアント領域 + ウィンドウ外枠の幅 #define WINDOW_X ((WINDOW_WIDTH + GetSystemMetrics( SM_CXSIZEFRAME )*2)) //クライアント領域 + ウィンドウ見出し+外枠の幅 #define WINDOW_Y ((WINDOW_HEIGHT + GetSystemMetrics( SM_CYSIZEFRAME )*2 + GetSystemMetrics( SM_CYCAPTION ))) #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } HINSTANCE g_hInstance = NULL; // インスタンス・ハンドル HWND g_hWindow = NULL; // ウインドウ・ハンドル LPDIRECT3D9 g_pD3D = NULL; // Direct3Dインタフェース LPDIRECT3DDEVICE9 g_pD3DDevice = NULL; // Direct3DDeviceインタフェース LPDIRECT3DVERTEXBUFFER9 g_SpriteBuffer = NULL; //スプライト全てを司るバッファ #define MY_VERTEX_FVF3 ( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 ) //スプライトの1頂点の情報 struct SpriteVertexInfo { float m_PosX, m_PosY, m_PosZ, m_rhw; DWORD m_Color; float m_U, m_V; }; //スプライトの4頂点の情報 struct SpriteRectInfo { SpriteVertexInfo m_SpriteInfo[ 4 ]; }; //テクスチャ毎のスプライト群 struct SpriteOfTextureInfo { std::vector< SpriteRectInfo > m_RectVec; DWORD m_NowRectVecNum; SpriteOfTextureInfo() { m_NowRectVecNum = 0; } }; //スプライトの情報 struct SpriteInfo { int m_TextureVecNum; SpriteVertexInfo m_VertexInfo[ 4 ]; SpriteInfo() { m_TextureVecNum = -1; } }; //テクスチャの情報 struct TextureInfo { LPDIRECT3DTEXTURE9 m_pTexture; D3DXIMAGE_INFO m_Info; TextureInfo() { m_pTexture = NULL; } }; //スプライトハンドルに対応する、スプライト情報の配列 const int MAX_SPRITE_NUM = 1024; SpriteInfo g_Sprite[ MAX_SPRITE_NUM ]; //テクスチャの配列 const int MAX_TEXTURE_NUM = 1024; TextureInfo g_Texture[ MAX_TEXTURE_NUM ]; //表示するスプライトの情報を、一時的に書き込む為の配列 SpriteOfTextureInfo g_PreSpriteBuffer[ MAX_TEXTURE_NUM ]; int g_DrawSpriteNum = 0; int g_SpriteBufferNum = 0; int GetSpriteHandle( int t_TextureVecNum ) { int result = -1; if( t_TextureVecNum >= 0 && t_TextureVecNum < MAX_TEXTURE_NUM ){ if( g_Texture[ t_TextureVecNum ].m_pTexture != NULL ){ SpriteInfo t_Info; t_Info.m_TextureVecNum = t_TextureVecNum; float t_U[ 4 ] = { 0.0f, 1.0f, 0.0f, 1.0f }; float t_V[ 4 ] = { 0.0f, 0.0f, 1.0f, 1.0f }; for( int i = 0; i < 4; i++ ){ t_Info.m_VertexInfo[ i ].m_PosX = 0.0f; t_Info.m_VertexInfo[ i ].m_PosY = 0.0f; t_Info.m_VertexInfo[ i ].m_PosZ = 0.0f; t_Info.m_VertexInfo[ i ].m_rhw = 1.0f; t_Info.m_VertexInfo[ i ].m_Color = 0xffffffff; t_Info.m_VertexInfo[ i ].m_U = t_U[ i ]; t_Info.m_VertexInfo[ i ].m_V = t_V[ i ]; } for( int i = 0; i < MAX_SPRITE_NUM; i++ ) { if( g_Sprite[ i ].m_TextureVecNum == -1 ){ g_Sprite[ i ] = t_Info; result = i; break; } } } } return( result ); } int LoadTexture( const char* t_pTextureName, int t_TextureVecNum ) { int result = -1; if( t_TextureVecNum >= 0 && t_TextureVecNum < MAX_TEXTURE_NUM ){ //すでに何らかのテクスチャが読み込まれていたら if( g_Texture[ t_TextureVecNum ].m_pTexture != NULL ){ //読み込まれていたテクスチャを開放 SAFE_RELEASE( g_Texture[ t_TextureVecNum ].m_pTexture ); } HRESULT hr; D3DXCreateTextureFromFileA( g_pD3DDevice, t_pTextureName, &( g_Texture[ t_TextureVecNum ].m_pTexture ) ); hr = D3DXGetImageInfoFromFileA( t_pTextureName, &( g_Texture[ t_TextureVecNum ].m_Info ) ); if( SUCCEEDED( hr ) ){ result = 0; } } return( result ); } int PreDrawSprite(float t_PosX, float t_PosY, float t_PosZ, int t_SpriteHandle) { int result = -1; //スプライトハンドルが正しければ if( t_SpriteHandle >= 0 && t_SpriteHandle < MAX_SPRITE_NUM ){ //スプライト情報が持つテクスチャハンドルが正しければ if( g_Sprite[ t_SpriteHandle ].m_TextureVecNum >= 0 && g_Sprite[ t_SpriteHandle ].m_TextureVecNum < MAX_TEXTURE_NUM ){ //テクスチャハンドルに対応するテクスチャが読み込まれていれば if( g_Texture[ g_Sprite[ t_SpriteHandle ].m_TextureVecNum ].m_pTexture != NULL ){ int t_TextureVecNum = g_Sprite[ t_SpriteHandle ].m_TextureVecNum; int t_RectVecNum = g_PreSpriteBuffer[ t_SpriteHandle ].m_NowRectVecNum; D3DXIMAGE_INFO t_Info = g_Texture[ t_TextureVecNum ].m_Info; //要素数が足りなければ拡張 if( ( int )g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec.size() >= g_PreSpriteBuffer[ t_TextureVecNum ].m_NowRectVecNum ){ g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec.resize( g_PreSpriteBuffer[ t_TextureVecNum ].m_NowRectVecNum + 1 ); } //スプライトハンドルに対応する情報をコピー g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 0 ] = g_Sprite[ t_SpriteHandle ].m_VertexInfo[ 0 ]; g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 1 ] = g_Sprite[ t_SpriteHandle ].m_VertexInfo[ 1 ]; g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 2 ] = g_Sprite[ t_SpriteHandle ].m_VertexInfo[ 2 ]; g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 3 ] = g_Sprite[ t_SpriteHandle ].m_VertexInfo[ 3 ]; //座標だけを上書き g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 0 ].m_PosX = t_PosX; g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 1 ].m_PosX = t_PosX + ( float )t_Info.Width; g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 2 ].m_PosX = t_PosX; g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 3 ].m_PosX = t_PosX + ( float )t_Info.Width; g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 0 ].m_PosY = t_PosY; g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 1 ].m_PosY = t_PosY; g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 2 ].m_PosY = t_PosY + ( float )t_Info.Height; g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 3 ].m_PosY = t_PosY + ( float )t_Info.Height; g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 0 ].m_PosZ = t_PosZ; g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 1 ].m_PosZ = t_PosZ; g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 2 ].m_PosZ = t_PosZ; g_PreSpriteBuffer[ t_TextureVecNum ].m_RectVec[ t_RectVecNum ].m_SpriteInfo[ 3 ].m_PosZ = t_PosZ; g_PreSpriteBuffer[ t_TextureVecNum ].m_NowRectVecNum += 1; g_DrawSpriteNum += 1; result = 0; } } } return( result ); } void DrawAllSprite() { if( g_DrawSpriteNum > 0 ){ if( g_DrawSpriteNum > g_SpriteBufferNum ){ int t_VertexNum = 2 + 1 + ( g_DrawSpriteNum << 2 ) + ( ( g_DrawSpriteNum - 1 ) << 1 ); g_SpriteBufferNum = g_DrawSpriteNum; g_pD3DDevice->CreateVertexBuffer( t_VertexNum * sizeof( SpriteVertexInfo ), D3DUSAGE_WRITEONLY, MY_VERTEX_FVF3, D3DPOOL_MANAGED, &g_SpriteBuffer, NULL); } //全てのスプライトを、一気に書き込む。 SpriteVertexInfo* t_Vertex; DWORD t_NowBufNum = 2; g_SpriteBuffer->Lock( 0, 0, (void**)&t_Vertex, 0); for( int i = 0; i < MAX_TEXTURE_NUM; i++ ) { for( int j = 0, count = g_PreSpriteBuffer[ i ].m_RectVec.size(); j < count; j++ ) { if( g_PreSpriteBuffer[ i ].m_NowRectVecNum > 0 ){ t_Vertex[ t_NowBufNum - 1 ] = g_PreSpriteBuffer[ i ].m_RectVec[ j ].m_SpriteInfo[ 0 ]; t_Vertex[ t_NowBufNum ] = g_PreSpriteBuffer[ i ].m_RectVec[ j ].m_SpriteInfo[ 0 ]; t_Vertex[ t_NowBufNum + 1 ] = g_PreSpriteBuffer[ i ].m_RectVec[ j ].m_SpriteInfo[ 1 ]; t_Vertex[ t_NowBufNum + 2 ] = g_PreSpriteBuffer[ i ].m_RectVec[ j ].m_SpriteInfo[ 2 ]; t_Vertex[ t_NowBufNum + 3 ] = g_PreSpriteBuffer[ i ].m_RectVec[ j ].m_SpriteInfo[ 3 ]; t_Vertex[ t_NowBufNum + 4 ] = g_PreSpriteBuffer[ i ].m_RectVec[ j ].m_SpriteInfo[ 3 ]; t_NowBufNum += 6; } } } g_SpriteBuffer->Unlock(); int t_BufNum = 2; g_pD3DDevice->SetFVF( MY_VERTEX_FVF3 ); for( int i = 0; i < MAX_TEXTURE_NUM; i++ ) { if( g_PreSpriteBuffer[ i ].m_NowRectVecNum > 0 ){ int t_PrimitiveNum = ( g_PreSpriteBuffer[ i ].m_NowRectVecNum << 1) + ( ( g_PreSpriteBuffer[ i ].m_NowRectVecNum - 1 ) << 2); if( g_Texture[ i ].m_pTexture != NULL ){ g_pD3DDevice->SetTexture( 0, g_Texture[ i ].m_pTexture ); }else{ g_pD3DDevice->SetTexture( 0, NULL ); } HRESULT hr; hr = g_pD3DDevice->SetStreamSource( 0, g_SpriteBuffer, 0, sizeof( SpriteVertexInfo ) ); hr = g_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, t_BufNum, t_PrimitiveNum ); t_BufNum += ( g_PreSpriteBuffer[ i ].m_NowRectVecNum << 2 ) + ( g_PreSpriteBuffer[ i ].m_NowRectVecNum << 1 ); g_PreSpriteBuffer[ i ].m_NowRectVecNum = 0; } } } g_DrawSpriteNum = 0; } //----------------------------------------------------------------------------- // Name: MsgProc() // Desc: The window's message handler //----------------------------------------------------------------------------- LRESULT WINAPI MsgProc2( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch( msg ) { case WM_DESTROY: PostQuitMessage( 0 ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam ); } //----------------------------------------------------------------------------- // Name: InitApp() // Desc: Initialize Window //----------------------------------------------------------------------------- HRESULT InitApp(HINSTANCE hInstance) { g_hInstance = hInstance; WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, MsgProc2, 0, 0, g_hInstance, NULL, NULL, (HBRUSH)(COLOR_WINDOW+1), NULL, L"D3D Tutorial", NULL}; if( !RegisterClassEx( &wcex )){ return DXTRACE_ERR(L"InitApp", GetLastError()); } // Create the application's window g_hWindow = CreateWindow( L"D3D Tutorial", L"ゲームプログラミング", WS_OVERLAPPEDWINDOW ^WS_THICKFRAME ^ WS_MAXIMIZEBOX ^ WS_MINIMIZEBOX, 100, 100, WINDOW_X, WINDOW_Y, NULL, NULL, wcex.hInstance, NULL ); if (g_hWindow == NULL) return DXTRACE_ERR(L"InitApp", GetLastError()); return S_OK; } //----------------------------------------------------------------------------- // Name: InitDirectX() // Desc: Initialize DirectX //----------------------------------------------------------------------------- HRESULT InitDirectX(void){ g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); if(g_pD3D == NULL){ DXTRACE_MSG(L"DirectXDeviceの初期化に失敗しました"); return E_FAIL; } D3DDISPLAYMODE d3ddm; if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) { DXTRACE_MSG(L"DirectX3DDeviceの初期化に失敗しました"); return E_FAIL; } D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; HRESULT hr = g_pD3D->CreateDevice( D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,g_hWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp,&g_pD3DDevice); if(FAILED(hr)) { hr = g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,g_hWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp,&g_pD3DDevice); if(FAILED(hr)) { hr = g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_REF,g_hWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp,&g_pD3DDevice); if(FAILED(hr)){ DXTRACE_MSG(L"DirectX3DDeviceの初期化に失敗しました"); return E_FAIL; } } } //セットアップ レンダーステート g_pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); g_pD3DDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE ); g_pD3DDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); g_pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); g_pD3DDevice->SetRenderState( D3DRS_AMBIENT, 0x33333333 ); g_pD3DDevice->SetRenderState( D3DRS_NORMALIZENORMALS, TRUE ); g_pD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); g_pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); g_pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); g_pD3DDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); g_pD3DDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); g_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1 , D3DTA_TEXTURE ); g_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP , D3DTOP_MODULATE ); g_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2 , D3DTA_DIFFUSE ); g_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1 , D3DTA_TEXTURE ); g_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP , D3DTOP_MODULATE ); g_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2 , D3DTA_DIFFUSE ); //ビュー行列作成 D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-4.0f ); D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); D3DXMATRIXA16 matView; D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); g_pD3DDevice->SetTransform( D3DTS_VIEW, &matView ); //射影行列作成 D3DXMATRIXA16 matProj; D3DXMatrixPerspectiveFovLH( &matProj, D3DXToRadian(90.0f), (float)640/480, 1.0f, 100.0f ); g_pD3DDevice->SetTransform( D3DTS_PROJECTION, &matProj ); return S_OK; } //----------------------------------------------------------------------------- // Name: Uninitialize() // Desc: UnInitialize DirectX //----------------------------------------------------------------------------- void Uninitialize(void) { for( int i = 0; i < MAX_TEXTURE_NUM; i++ ) { SAFE_RELEASE( g_Texture[ i ].m_pTexture ); } SAFE_RELEASE( g_SpriteBuffer ); SAFE_RELEASE( g_pD3DDevice ); SAFE_RELEASE( g_pD3D ); } //----------------------------------------------------------------------------- // Name: WinMain() // Desc: The application's entry point //----------------------------------------------------------------------------- int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { #ifdef _DEBUG _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif HRESULT hr; if(FAILED(hr = InitApp(hInstance))) { return(0); } //初期化が成功したら if( SUCCEEDED(hr = InitDirectX()) ) { MSG msg; ZeroMemory( &msg, sizeof(msg) ); ShowWindow(g_hWindow, SW_SHOWDEFAULT); UpdateWindow(g_hWindow); LoadTexture( "test4.png", 0); LoadTexture( "TitleSelect.png", 5); int t_Handle[ 2 ] = { -1, -1 }; t_Handle[ 0 ] = GetSpriteHandle( 0 ); t_Handle[ 1 ] = GetSpriteHandle( 5 ); // Enter the message loop while( msg.message!=WM_QUIT ) { if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); }else{ g_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,60), 1.0f, 0 ); g_pD3DDevice->BeginScene(); PreDrawSprite( 0, 0, 0.5, t_Handle[ 0 ] ); PreDrawSprite( 50, 50, 0.4, t_Handle[ 0 ] ); PreDrawSprite( 100, 100, 0.3, t_Handle[ 0 ] ); PreDrawSprite( 150, 150, 0.2, t_Handle[ 0 ] ); PreDrawSprite( 150, 100, 0.25, t_Handle[ 1 ] ); DrawAllSprite(); g_pD3DDevice->EndScene(); g_pD3DDevice->Present( NULL, NULL, NULL, NULL ); Sleep(1); } } } Uninitialize(); UnregisterClass( L"D3D Tutorial", g_hInstance ); return 0; }