Direct3D learning (4)
学习D3d的教程,里面第6章以后就不提供代码了,自己按照他说的,进行了一些封装。还是比较肤浅的。目前至少能运行了。
使用异常处理,纯虚类接口,继承,模板template等C++方法。
GameObjectAction是接口类,主要定义了一些基本的虚函数接口。
GameObject是基本类,包含了Direct3DDevice的指针,一个世界矩阵用于表示物体的移动和翻转,angleX表示相对于x轴的角度,x表示中心相对于x的偏移,其他类似。继承了GameObjectAction。
class GameApp是运行游戏的一个类。它里面定义了一个vector的GameObject,表示画面中所有物体的集合。
class D3dCube是一个立方体类,(事实上也可以处理长方体),支持基本的移动旋转等操作。
目前的实现很是简单。但这毕竟是一个开始。以后一点点修改。
下载地址http://blog.blogchina.com/upload/2005-04-08/20050408152549160215.rar, 解压后,记得修改工程的directX9的路径。
下面是源代码:
/* 用于异常处理。 暂时简单处理了一下。 * filename: gy_exception.h */ #ifndef _GY_EXCEPTION_H #define _GY_EXCEPTION_H namespace gy { const int ER_CODE = 2000; class Exception { public: Exception(int code = 0) : errno(code) { } ~Exception() { } int errno; }; } #endif /* * filename: GameObject.h */ #ifndef _GY_GAMEOBJECT_H #define _GY_GAMEOBJECT_H #include < d3dx9math.h > #include < d3d9.h > namespace gy { #define SafeRelease(pObject) / if (pObject != NULL) {/ pObject->Release(); / pObject = NULL; / } inline void Matrix_Initialize(D3DXMATRIX& mat) { mat = D3DXMATRIX( 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); } class GameObjectAction { public: virtual void Render() = 0; virtual void MoveTo(float _x, float _y, float _z) = 0; virtual void RotateTo(float _anglex, float _angley, float _anglez) = 0; virtual void Translate(float _x, float _y, float _z) = 0; virtual void Rotate(float _anglex, float _angley, float _anglez) = 0; }; class GameObject : public GameObjectAction { public: GameObject(LPDIRECT3DDEVICE9 p) { pD9 = p; //position = D3DXVECTOR3(0, 0, 0); Matrix_Initialize(worldmatrix); x = y = z = anglex = angley = anglez = 0; } virtual ~GameObject() {} // data protected: LPDIRECT3DDEVICE9 pD9; //D3DXVECTOR3 position; D3DXMATRIX worldmatrix; float anglex, angley, anglez; float x, y, z; }; } #endif /* * filename: D3dCube.h */ #ifndef _GY_D3DCUBE_H #define _GY_D3DCUBE_H #include "GameObject.h" #include "gy_exception.h" namespace gy { template < class CustomVertex > class D3dCube : public GameObject { public: D3dCube(LPDIRECT3DDEVICE9 pD3dDevice9, CustomVertex *array, size_t count, DWORD fvfflag); ~D3dCube(); void Render(); void MoveTo(float _x, float _y, float _z); void Translate(float _x, float _y, float _z); void Rotate(float _anglex, float _angley, float _anglez); void RotateTo(float _anglex, float _angley, float _anglez); private: void DoTranslate(); void DoRotate(); LPDIRECT3DVERTEXBUFFER9 vertex; DWORD fvf; }; template < class CustomVertex > D3dCube< CustomVertex >::D3dCube(LPDIRECT3DDEVICE9 p, CustomVertex* array, size_t count, DWORD fvfflag) : GameObject(p) { void *pVertex; size_t length; vertex = NULL; length = sizeof(CustomVertex) * count; if (FAILED(pD9->CreateVertexBuffer(length, 0, fvfflag,D3DPOOL_DEFAULT, &vertex, NULL))) { throw(Exception(ER_CODE)); return; } if (FAILED(vertex->Lock(0, length, (void**)&pVertex, 0))) { throw(Exception(ER_CODE)); return; } memcpy(pVertex, array, length); vertex->Unlock(); fvf = fvfflag; } template < class CustomVertex > D3dCube< CustomVertex >::~D3dCube() { SafeRelease(vertex); } template < class CustomVertex > void D3dCube< CustomVertex > :: DoRotate() { D3DXMATRIX mat, matX, matY, matZ; D3DXMatrixRotationX(&matX, anglex); D3DXMatrixRotationX(&matY, angley); D3DXMatrixRotationX(&matZ, anglez); D3DXMatrixMultiply(&mat, &matX, &matY); D3DXMatrixMultiply(&mat, &mat, &matZ); D3DXMatrixMultiply(&worldmatrix, &worldmatrix, &mat); } template < class CustomVertex > void D3dCube< CustomVertex >::DoTranslate() { D3DXMATRIX mat; D3DXMatrixTranslation(&mat, x, y, z); D3DXMatrixMultiply(&worldmatrix, &worldmatrix, &mat); } template < class CustomVertex > void D3dCube< CustomVertex >::Render() { DoTranslate(); DoRotate(); pD9->SetTransform(D3DTS_WORLD, &worldmatrix); pD9->SetStreamSource(0, vertex, 0, sizeof(CustomVertex)); pD9->SetFVF(fvf); pD9->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); pD9->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 8); pD9->DrawPrimitive(D3DPT_TRIANGLESTRIP, 14, 2); Matrix_Initialize(worldmatrix); } template < class CustomVertex > void D3dCube< CustomVertex >::MoveTo(float _x, float _y, float _z) { x = _x; y = _y; z = _z; } template < class CustomVertex > void D3dCube< CustomVertex >::Translate(float _x, float _y, float _z) { x += _x; y += _y; z += _z; } template < class CustomVertex > void D3dCube< CustomVertex >::Rotate(float _anglex, float _angley, float _anglez) { anglex += _anglex; angley += _angley; anglez += _anglez; } template < class CustomVertex > void D3dCube< CustomVertex >::RotateTo(float _anglex, float _angley, float _anglez) { anglex = _anglex; angley = _angley; anglez = _anglez; } } #endif /* * filename: GameApp.h */ #ifndef _GY_GAMEAPP_H #define _GY_GAMEAPP_H #include "GameObject.h" #include "gy_exception.h" #include < vector > using namespace std; namespace gy { class GameApp { public: GameApp(HWND hWnd); ~GameApp(); void Loop(); void AddObject(GameObject* pObject) { objects.push_back(pObject); } LPDIRECT3DDEVICE9 GetDevice() { return pD9; } LPDIRECT3D9 GetD3D() { return pD3D; } private: void Render(); void SetupCamera(); void SetupPerspective(); void Init(HWND hWnd); void End(); // data public: LPDIRECT3D9 pD3D; LPDIRECT3DDEVICE9 pD9; vector< GameObject* > objects; }; } #endif /* * filename: GameApp.cpp */ #include "stdafx.h" #include "GameApp.h" #include < Mmsystem.h > namespace gy { GameApp::GameApp(HWND hWnd) { Init(hWnd); } GameApp::~GameApp() { End(); } void GameApp::Init(HWND hWnd) { pD3D = Direct3DCreate9(D3D_SDK_VERSION); if (pD3D == NULL) { throw(Exception(ER_CODE)); return; // use throw in future } D3DDISPLAYMODE d3ddm; if (FAILED( pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) { throw(Exception(ER_CODE)); return; } D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_COPY; d3dpp.BackBufferFormat = d3ddm.Format; if (FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pD9))) { throw(Exception(ER_CODE)); return; } // remove in future // set cullmode use anti-circle-way pD9->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); pD9->SetRenderState(D3DRS_LIGHTING, FALSE); return; } void GameApp::End() { for (size_t i = 0; i < objects.size(); ++i) { if (objects[i] != NULL) { delete objects[i]; objects[i] = NULL; } } SafeRelease(pD9); SafeRelease(pD3D); } void GameApp::SetupCamera() { //Here we will setup the camera. //The camera has three settings: "Camera Position", "Look at Position" and //"Up Direction" //We have set the following: //Camera Position: (0, 0, -30) //Look at Position: (0, 0, 0) //Up direction: Y-Axis. D3DXMATRIX matView; D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0.0f, 0.0f,-100.0f), //Camera Position &D3DXVECTOR3(0.0f, 0.0f, 0.0f), //Look At Position &D3DXVECTOR3(0.0f, 1.0f, 0.0f)); //Up Direction pD9->SetTransform(D3DTS_VIEW, &matView); } void GameApp::SetupPerspective() { //Here we specify the field of view, aspect ration and near and //far clipping planes. D3DXMATRIX matProj; D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 1.0f, 500.0f); pD9->SetTransform(D3DTS_PROJECTION, &matProj); } void GameApp::Render() { if (pD9 == NULL) { return; } pD9->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); pD9->BeginScene(); SetupCamera(); SetupPerspective(); for (size_t i = 0; i < objects.size(); ++i) { if (objects[i] != NULL) { objects[i]->RotateTo(timeGetTime()/400.0f, 0.0f, 0.0f); objects[i]->Render(); } } pD9->EndScene(); pD9->Present(NULL, NULL, NULL, NULL); } void GameApp::Loop() { MSG msg; BOOL fMessage; PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE); while(msg.message != WM_QUIT) { fMessage = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE); if (fMessage) { TranslateMessage(&msg); DispatchMessage(&msg); }else { Render(); } //Sleep(33); // 30fps = 1000/33 fps } } } /* * filename: d3d.cpp */ #include "stdafx.h" #include "GameApp.h" #include "D3dCube.h" using namespace gy; struct CUSTOMVERTEX { FLOAT x, y, z; DWORD color; }; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE) CUSTOMVERTEX cvVertex[] = { //Top Face {-5.0f, 5.0f, -5.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 0 - Blue {-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 1 - Red {5.0f, 5.0f, -5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 2 - Red {5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 3 - Green //Face 1 {-5.0f, -5.0f, -5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 4 - Red {-5.0f, 5.0f, -5.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 5 - Blue {5.0f, -5.0f, -5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 6 - Green {5.0f, 5.0f, -5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 7 - Red //Face 2 {5.0f, -5.0f, 5.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 8 - Blue {5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 9 - Green //Face 3 {-5.0f, -5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 10 - Green {-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 11 - Red //Face 4 {-5.0f, -5.0f, -5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 12 - Red {-5.0f, 5.0f, -5.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 13 - Blue //Bottom Face {5.0f, -5.0f, -5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 14 - Green {5.0f, -5.0f, 5.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 15 - Blue {-5.0f, -5.0f, -5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 16 - Red {-5.0f, -5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 17 - Green }; LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_DESTROY: PostQuitMessage(0); return 0; break; case WM_KEYUP: switch(wParam) { case VK_ESCAPE: DestroyWindow(hWnd); return 0; break; } break; default: break; } return DefWindowProc(hWnd, msg, wParam, lParam); } INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE , LPSTR , int ) { WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, WinProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, "DX Project 1", NULL}; RegisterClassEx(&wc); HWND hWnd = CreateWindow("DX Project 1", "www.andypike.com: Tutorial 1", WS_OVERLAPPEDWINDOW, 50, 50, 500, 500, GetDesktopWindow(), NULL, wc.hInstance, NULL); try { GameApp theGameApp(hWnd); ShowWindow(hWnd, SW_SHOWDEFAULT); UpdateWindow(hWnd); D3dCube< CUSTOMVERTEX > *cube = new D3dCube< CUSTOMVERTEX >(theGameApp.GetDevice(), cvVertex, sizeof(cvVertex)/sizeof(CUSTOMVERTEX), D3DFVF_CUSTOMVERTEX); theGameApp.AddObject(cube); cube = new D3dCube< CUSTOMVERTEX >(theGameApp.GetDevice(), cvVertex, sizeof(cvVertex)/sizeof(CUSTOMVERTEX), D3DFVF_CUSTOMVERTEX); cube->MoveTo(20.0f, 0.0f, 0.0f); theGameApp.AddObject(cube); theGameApp.Loop(); }catch(Exception e) { cout << "Catch Error: " << e.errno << endl; } UnregisterClass("DX Project 1", wc.hInstance); return 0; }