1.1 Surfaces之封裝CXSurface

1、Surfaces是什么:
  通俗的講surfaces就是一個(gè)二維的矩形平面。在DX9中,與其對(duì)應(yīng)的com接口為IDirect3DSurface9,LPDIRECT3DSURFACE9。

2、Surfaces的作用:
  作為一個(gè)矩形平面,surfaces用來(lái)在屏幕上顯示平面圖象,即從文件中讀取圖象數(shù)據(jù)呈現(xiàn)給用戶。

3、IDirect3DSurface9的使用一般過程:
  聲明: LPDIRECT3DSURFACE9
  創(chuàng)建: CreateOffscreenPlainSurface(…)
  獲取圖象信息: D3DXGetImageInfoFromFile(…)
  裝載到surfaces中: D3DXLoadSurfaceFromFile(…)
  獲取back buffer地址: GetBackBuffer(…)
  顯示: UpdateSurface(…)
  釋放內(nèi)存 Release()

代碼段如下:

LPDIRECT3DSURFACE9 g_Surface =NULL;
D3DXIMAGE_INFO Info;
D3DXGetImageInfoFromFile("D:\image.jpg", &Info);
g_pd3dDevice->CreateOffscreenPlainSurface(Info.Width, Info.Height, Info.Format, &g_Surface, NULL);
D3DXLoadSurfaceFromFile(g_Surface, NULL, NULL, "D:\image.jpg", NULL, D3DX_FILTER_NONE, 0xFF000000, NULL);

//--------------------------------------------------------------------------------------------------
LPDIRECT3DSURFACE9 BackBuffer = NULL;
g_pd3dDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO, &BackBuffer);
g_pd3dDevice->UpdateSurface(g_Surface, NULL, BackBuffer, NULL);
if(BackBuffer != NULL)
??? BackBuffer->Release();

//---------------------------------------------------------------------------------------------------
if(g_Surface!= NULL)
??? g_Surface ->Release();

  由上述過程可以看到,IDirect3DSurface9的使用雖然不十分復(fù)雜,但有點(diǎn)不方便 ——?jiǎng)?chuàng)建和釋放總要成對(duì)出現(xiàn),使用過程中還穿插著LPDIRECT3DDEVICE9接口。這些若用一個(gè)類封裝起來(lái),使用就要方便的多。

4、如何封裝:
  按照surfaces的功能,創(chuàng)建它就用來(lái)顯示圖象。因此要有讀取圖象的接口和顯示圖象的接口。又要與LPDIRECT3DDEVICE9設(shè)備接口關(guān)聯(lián),因此需要一個(gè)設(shè)置設(shè)備的接口。如下所示:

1、聲明及釋放
  聲明: LPDIRECT3DSURFACE9
  釋放內(nèi)存 Release()

2、關(guān)聯(lián)圖像:LoadFromFile
  獲取圖象信息: D3DXGetImageInfoFromFile(…)
  創(chuàng)建: CreateOffscreenPlainSurface(…)
  裝載到surfaces中: D3DXLoadSurfaceFromFile(…)

3、顯示圖象 Render
  獲取緩存地址: GetBackBuffer(…)
  顯示: UpdateSurface(…)

4、關(guān)聯(lián)設(shè)備接口 SetDevice

所以CXSurface的定義如下:

class CXSurface
{
protected:
??? LPDIRECT3DSURFACE9 m_Surface;
??? LPDIRECT3DSURFACE9 m_BackBuffer; //Back buffer
??? LPDIRECT3DDEVICE9 m_pDevice; //Direct3D的設(shè)備指針
public:
??? CXSurface(LPDIRECT3DDEVICE9 pDevice);
??? ~CXSurface();
??? HRESULT LoadFromFile(LPCSTR Path);
??? void Render(void);
};


1.2 Textures & Sprite 之封裝CXTexture & CXSprite

1、何為Textures
  Textures是在屏幕上顯示的平面圖形,它能夠提供比 surface 更多的圖形處理效果——移動(dòng)、縮放、旋轉(zhuǎn)及作為紋理皮膚粘貼在3D模型上。在Direct3D中,其封裝的接口為IDirect3DTexture9。

2、何為Sprite
  IDirect3DTexture9能從文件中讀取紋理數(shù)據(jù),但由于Textures不能直接復(fù)制到 back buffer,因此在屏幕上繪制Textures之前,需要另一個(gè)接口——ID3DXSprite(精靈)。ID3DXSprite能夠把若干個(gè)Textures 復(fù)制給back buffer,因此需要ID3DXSprite的一個(gè)實(shí)例就可以繪制所有的紋理。
  所以,IDirect3DTexture9用來(lái)存放程序所需的紋理,但它本身又不能繪制紋理,需要借助接口ID3DXSprite。

3、IDirect3DTexture9和ID3DXSprite的使用過程
  定義:~
  創(chuàng)建:D3DXCreateTextureFromFile
     D3DXCreateSprite
  創(chuàng)建變換矩陣: D3DXMatrixTransformation2D
  變換: SetTransform
  繪制圖象: Draw
  釋放內(nèi)存: ~

代碼如下:

D3DXCreateTextureFromFile(g_pd3dDevice, "c:\\image.bmp”, &g_Texture);
D3DXCreateSprite(g_pd3dDevice, &g_Sprite);

//--------------------------------------------------------------------------
D3DXVECTOR2 Translation;
Translation.x = 500;
Translation.y = 500;
D3DXVECTOR2 Scaling;
Scaling.x = 1.0;f
Scaling.y = 1.0f;
D3DXMATRIX Mat;
D3DXMatrixTransformation2D(&Mat, NULL, 0, &Scaling, NULL, 0, &Translation);
g_Sprite->Begin(0);
g_Sprite->SetTransform(&
g_Sprite->Draw(g_Texture,
g_Sprite->End();

4、 如何封裝
  從以上的基本過程可以看到,CXTexture需要完成的功能:提供與LPDIRECT3DDEVICE9的接口,與紋理文件文件關(guān)聯(lián),對(duì)紋理進(jìn)行處理(縮放、旋轉(zhuǎn)……)。

class CXTexture
{
protected:
??? LPDIRECT3DTEXTURE9 m_Texture;
??? LPDIRECT3DDEVICE9 m_pDevice;
??? D3DXVECTOR2 m_RotationCenter;
??? D3DXVECTOR2 m_Translation;
??? D3DXVECTOR2 m_Scaling;
??? FLOAT m_Rotation;
??? RECT m_SrcRect;
public:
??? CXTexture(LPDIRECT3DDEVICE9 pDevice);
??? ~CXTexture();

??? LPDIRECT3DTEXTURE9 GetTexture() const {return m_Texture;}
??? void SetTexture(LPDIRECT3DTEXTURE9 Texture) const {m_Texture = Texture;}
??? LPDIRECT3DDEVICE9 GetDevice() const {return m_pDevice;}
??? void SetDevice(LPDIRECT3DDEVICE9 pDevice) const {m_pDevice = pDevice;}
??? D3DXVECTOR2 GetRotationCenter() const {return m_RotationCenter;}
??? void SetRotationCenter(D3DXVECTOR2 RotationCenter) {m_RotationCenter = RotationCenter;}
??? D3DXVECTOR2 GetTranslation() const {return m_Translation;}
??? void SetTranslation (D3DXVECTOR2 Translation) const {m_Translation = Translation;}
??? D3DXVECTOR2 GetScaling() const {return m_Scaling;}
??? void SetScaling(D3DXVECTOR2 Scaling) const {m_Scaling = Scaling;}
??? FLOAT GetRotation() const {return m_Rotation;}
??? void SetRotation (FLOAT Rotation) const {m_Rotation = Rotation;}
??? RECT GetRect() const {return m_SrcRect;}
??? void SetRect(RECT SrcRect) const {m_SrcRect = SrcRect;}
??? HRESULT LoadFromFile(char* Path);
};

CXSprite的主要功能就是在屏幕上顯示 CXTexture,因此需要有與 LPDIRECT3DDEVICE9 接口和 CXTexture連接的函數(shù)。

class CXSprite
{
protected:
??? LPD3DXSPRITE m_Sprite;
??? LPDIRECT3DDEVICE9 m_pDevice;
public:
??? CXSprite (LPDIRECT3DDEVICE9 pDevice);
??? ~CXSprite ();

??? LPD3DXSPRITE GetSprite() const {return m_Sprite;}
??? void SetSprite(LPD3DXSPRITE Sprite) const {m_Sprite = Sprite;}
??? LPDIRECT3DDEVICE9 GetDevice() const {return m_pDevice;}
??? void SetDevice(LPDIRECT3DDEVICE9 pDevice) const {m_pDevice = pDevice;}
??? HRESULT DrawTexture(CXTexture* Texture);
};


1.3 Keyboard & Mouse之封裝CXKeyboard & CXMouse

1、何為Keyboard & Mouse
  “地球人都知道”。DX9提供的接口 IDirectInputDevice8。

2、二者的功能
  Keyboard:讀取鍵盤的按鍵信息
  Mouse:讀取鼠標(biāo)的按鍵、位置信息,設(shè)置光標(biāo)屬性(如用圖片表示光標(biāo))。

3、使用過程
  創(chuàng)建 IDirectInput8 對(duì)象 DirectInput8Create
  創(chuàng)建 IDirectInput8 設(shè)備(鍵盤、鼠標(biāo)等) CreateDevice
  設(shè)置設(shè)備屬性 SetCooperativeLevel
  SetDataFormat
  獲取設(shè)備使用權(quán) Acquire
  讀取設(shè)備傳入的數(shù)據(jù) GetDeviceState
  釋放設(shè)備及 IDirectInput8 Release

設(shè)置鼠標(biāo)光標(biāo)過程:
  創(chuàng)建光標(biāo)圖片資源: 參照surfaces
  設(shè)置光標(biāo)為指定的圖片 SetCursorProperties
  設(shè)置光標(biāo)的初始位置 SetCursorPosition
  顯示光標(biāo) ShowCursor

程序段如下:

LPDIRECTINPUT8 g_lpDI;
LPDIRECTINPUTDEVICE8 g_Keyboard;
LPDIRECTINPUTDEVICE8 g_Mouse

//========================================================
HRESULT Result = DirectInput8Create(g_hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&g_lpDI, NULL);

if(SUCCEEDED(Result))
{
??? //創(chuàng)建鍵盤設(shè)備
??? Result = g_lpDI->CreateDevice(GUID_SysKeyboard, &g_lpDIDevice, NULL);
??? if(SUCCEEDED(Result))
??? {
??????? g_lpDIDevice->SetCooperativeLevel(g_hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
??????? g_lpDIDevice->SetDataFormat(&c_dfDIKeyboard);
??? }
}

//-------------------------------------------------------------------------------------------
//獲取按鍵信息
if(SUCCEEDED(g_Keyboard->Acquire())) //Acquire the device
{
??? char KeyState[256];
??? g_Keyboard->GetDeviceState(sizeof(KeyState),(LPVOID)&KeyState);
??? //根據(jù)KeyState返回的數(shù)據(jù)就可以判斷按下何鍵
}

//====================================================
//創(chuàng)建鼠標(biāo)
g_lpDI->CreateDevice(GUID_SysMouse, &g_Mouse, NULL);
g_Mouse->SetDataFormat(&c_dfDIMouse);
g_Mouse->SetCooperativeLevel(g_hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);

//------------------------------------------------------------------------
//設(shè)置鼠標(biāo)光標(biāo)
//獲取光標(biāo)圖片
D3DXIMAGE_INFO ImageInfo;
D3DXGetImageInfoFromFile("C:\\Cursor.jpg”, &ImageInfo);
g_pd3dDevice->CreateOffscreenPlainSurface(ImageInfo.Width, ImageInfo.Height, ImageInfo.Format, D3DPOOL_DEFAULT, &g_MouseCursor, NULL);
D3DXLoadSurfaceFromFile(g_MouseCursor, NULL, NULL, ("C:\\Cursor.jpg”, NULL, D3DX_FILTER_NONE, 0xFF000000, NULL);

//設(shè)置成指定的光標(biāo)
g_pd3dDevice->SetCursorProperties(0,0, g_MouseCursor);

//初試位置
g_pd3dDevice->SetCursorPosition(0,0,D3DCURSOR_IMMEDIATE_UPDATE);

//顯示光標(biāo)
g_pd3dDevice->ShowCursor(true);

//-------------------------------------------------------------------------
//獲取鼠標(biāo)信息
if(SUCCEEDED(g_Mouse->Acquire()))
{
??? DIMOUSESTATE State;
??? g_Mouse->GetDeviceState(sizeof(DIMOUSESTATE),(LPVOID)&State);
??? //信息保存在 State中。
}

//==============================================
//釋放設(shè)備
if(g_lpDI != NULL)
??? g_lpDI->Release();

4、封裝
  CXKeyboard的封裝

class CXKeyboard
{
private:
??? LPDIRECTINPUTDEVICE8 m_pDevice;
??? char m_KeyState[256];
public:
??? CXKeyboard (LPDIRECTINPUT8 pInput, HWND hWnd);
??? ~ CXKeyboard();

??? bool IsKeyPressed(int Key);
??? HRESULT Update();
};

CXMouseSurface的封裝

為了能制作出動(dòng)畫效果的光標(biāo),因此需要一個(gè)surfaces列表,因此從CXSurface繼承一個(gè)CXMouseSurface類,使之能夠操作多個(gè)圖片。

class CXMouseSurface : public CXSurface
{
private:
??? CXMouseSurface* m_pNext;
??? int MouseSurfaceType;
??? UINT HotSpotX;
??? UINT HotSpotY;
public:
??? CXMouseSurface* GetNext() {return m_pNext;}
??? void SetNext(CXMouseSurface* Surf) {m_pNext = Surf;}
??? int GetSurfaceType() {return MouseSurfaceType;}
??? void SetSurfaceType(int Type) {MouseSurfaceType = Type;}
??? UINT GetHotSpotX() {return HotSpotX;}
??? UINT GetHotSpotY() {return HotSpotY;}
??? void SetHotSpotX (UINT X) {HotSpotX = X;}
??? void SetHotSpotY (UINT Y) {HotSpotY = Y;}
??? CXMouseSurface(LPDIRECT3DDEVICE9 pDevice) : CXSurface(pDevice) {m_pNext = NULL;}
??? CXMouseSurface() : CXSurface() {m_pNext = NULL;}
};

CXMouse的封裝

class CXMouse
{
private:
??? CXMouseSurface* m_Surface; //指向光標(biāo)列表
??? CXMouseSurface* m_CurrentCursorSurface; //當(dāng)前光標(biāo)
??? LPDIRECTINPUTDEVICE8 m_pDevice;
??? LPDIRECT3DDEVICE9 m_p3DDevice;
??? DIMOUSESTATE m_State;
??? LONG m_iX;
??? LONG m_iY;

public:
??? CXMouse (LPDIRECT3DDEVICE9 pDevice, LPDIRECTINPUT8 pInput, HWND hWnd, bool Exclusive);
??? ~ CXMouse();

??? HRESULT Update();
??? LONG GetXPos();
??? LONG GetYPos();
??? bool IsButtonPressed(int Button);
??? HRESULT SetCursorImage();
??? HRESULT SetMouseCursor(char* FilePath, UINT HotSpotX, UINT HotSpotY, int Type);
??? void AddCursorSurface(CXMouseSurface* Surface);
??? CXMouseSurface* GetFirstSurface() {return m_Surface;}
??? bool SetCursor(int Type);
??? CXMouseSurface* GetCurrentCursor() {return m_CurrentCursorSurface;}
??? void SetCurrentCursor(CXMouseSurface* Surface) {m_CurrentCursorSurface = Surface;}
??? void SetCursorPosition(int X, int Y);
??? HRESULT SetCursorVisible(bool Show);
};