[程式] 小型2D線上遊戲心得分享 : 圖像引擎
經過了宣傳期之後,遊戲設計版好像幾乎沒什麼文章,身為版主的我感到有點慚愧
最近因為要把我小型的線上遊戲先趕出來,所以還蠻忙的,不過,我一直在想
(雖然每天都有寫程式,不過在PTT上面打嘴炮的時間也不少 XD)
要把一些製作上的心得分享,主要是想能拋磚引玉,讓更多人能夠有更熱烈的討論
心得的分享等等,所以我的文章參考看看就好,如果有錯誤的地方,請一定要指出來
不過,其實我整個遊戲並還沒有完成,本來打算整個完成後再開始寫,但是怕太多
到時反而整天都在寫文章,因此打算慢慢寫
而我遊戲的製作進度,可以參考我的網站
http://www.kinmen.info/vic
目前MapEditor已經接近完工的狀態
------------------------------------------------------------------------
今天我們首先講的是圖像引擎,圖像引擎可以說是一個遊戲的重要基石,其實
不管是寫遊戲還是做其它軟體也好,只要專案大到一定程度,都像在堆積木一樣
從底層開始做然後慢慢往上堆,而圖像引擎可以說是非常底層的的積木,因為
日後整個遊戲的畫面處理都由這個引擎完成,因此可以說是非常重要的部份
如果寫得好的話,就算寫其它遊戲,也可以直接套用。
但是一個好的圖像引擎其實並不是很容易寫,因為要考濾的東西不少,對未來開發
時會遇到的需求等等,都要考濾進去,最重要也最困難的部份,就是
Interface
好的Interface,跟OpenGL、DirectX...等等底層的東西,最好都要沒有關聯
盡可能的抽像化,但是又要能考慮到實作的情況,除此之外還有功能上的完備性,
因此需要用心的規劃和思考才能定出一套很好的Interface,如果規劃得好的話
你的圖像引擎會非常有彈性,你可以用DirectX或OpenGL或其它方式,來實作引擎
而你要選擇輸出方式的話,只要在一開始把Interface所指向的實作類別改成
你喜歡的那個就行了,更進一步,與作業系統無關的話,你可以讓你的遊戲
跨平台,總而言之好處非常多
我個人把Interface分成兩種,一種是提供環境給圖像引擎的的Framework Interface
另一種則是操作用的Graphical Interface,當要使用時,Framework的實作,會建立
一個可以讓Graphical Interface使用的環境
以下是Framework的範例:
/**
@brief 負責提供Windows環境給圖像係統
此類別只會存在一個
**/
class CGraphicalFramework : public CGraphicalObject{
public:
CGraphicalFramework():
m_Width(0),m_Height(0),
m_Bits(0),
m_DC(NULL),
m_Wnd(NULL)
{
}
virtual ~CGraphicalFramework(){}
/**
@brief 初始化整個Framwrok
@param [in] 視窗標題
@param [in] 畫面寬度
@param [in] 畫面高度
@param [in] 畫面顏色深度
@param [in] 是否為全螢幕
@return 是否成功
**/
virtual bool Initialize(int Width, int Height, int BSP,HDC DC,HWND Wnd) = 0;
/**
@brief 摧毀Framework
**/
virtual void Destroy() = 0;
/**
@brief 取得畫面寬度
@return m_Width
**/
int getWidth() const {
return m_Width;
}
/**
@brief 取得畫面高度
@return m_Height
**/
int getHeight() const {
return m_Height;
}
/**
@brief 取得畫面色深
@return m_Bits
**/
int getBits() const {
return m_Bits;
}
protected:
/**
畫面的寬高
**/
int m_Width;
int m_Height;
/**
螢幕的色深
**/
int m_Bits;
/**
GDI Device Context
**/
HDC m_DC;
/**
Window Handle
**/
HWND m_Wnd;
};
由於我的遊戲沒有跨平台的打算,因此我也沒花心力去讓它與作業系統無關
接著就是Graphical Interface,畫面的各種操作,都是靠這個Interface,
它的操作可以分成幾種
1.環境設定
例如改變視窗大小時需要的重新設定,清除畫面、更新畫面,改變顏色等等
2.圖像輸出
各種自定或是標準的圖像格式輸出到畫面上
3.幾合圖形
在畫面上畫出線段之類的幾合圖形
4.單位換算
換算螢幕上與空間以及ViewPort之類的單位
5.點擊測試
測試某些形狀或圖片是否有被滑鼠點中
以上只是最基本的,如果你有多餘的精力,可以加入一些全畫面的特效操作等等
以下是Graphical Interface的範例:
/**
@brief 圖像引擎介面
**/
class CGraphicalInterface : public CGraphicalObject{
public:
CGraphicalInterface():
m_Width(0),
m_Height(0),
m_ViewportWidth(0),
m_ViewportHeight(0),
m_Z(0)
{}
virtual ~CGraphicalInterface(){}
/**
@brief 初始化圖像引擎
@param [in] 視窗標題
@param [in] 畫面寬度
@param [in] 畫面高度
@param [in] 畫面顏色深度
@param [in] 是否為全螢幕
@return 是否成功
**/
virtual bool Initialize(int Width,int Height) = 0;
/**
@brief 摧毀圖像引擎
**/
virtual void Destroy() = 0;
/**
@brief 重設圖像畫面大小
@return 是否成功
**/
virtual bool Resize(int Width,int Height,bool IsOrtho = false) = 0;
/**
@brief 建立材質
@return 是否成功
**/
virtual TEXTURE CreateTexture(unsigned char *pBuffer,int Width,int
Height,int BPP) = 0;
/**
@brief 填滿整個區域
@return 是否成功
**/
virtual bool FillTexture(const TEXTURE &Texture,float Width,float
Height,const SURFACE_POINT Points[4],float Alpha) = 0;
/**
@brief 繪出Texture
@return 是否成功
**/
virtual bool DrawTexture(const TEXTURE &Texture,float X,float Y,float
Rotate,float ScaleX,float ScaleY,float Alpha) = 0;
/**
@brief 繪出自訂寬高的Texture
@return 是否成功
**/
virtual bool DrawTexture(const TEXTURE &Texture,float Width,float
Height,float X,float Y,float Rotate,float ScaleX,float ScaleY,float Alpha) =
0;
/**
@brief 繪出Surface
@return 是否成功
**/
virtual bool DrawSurface(const CSurface &Surface,float X,float Y,float
Rotate,float ScaleX,float ScaleY,float Alpha) = 0;
/**
@brief 繪出來自記憶體的影像
@return 是否成功
**/
virtual bool DrawPixels(const unsigned char *pBuffer,int Wdith,int
Height,float X,float Y) = 0;
/**
@brief 在螢幕上畫出矩形
@param [in] 座標X
@param [in] 座標Y
@param [in] 寬度
@param [in] 高度
**/
virtual void Rect(float X,float Y,float Width,float Height,bool IsFilled) =
0;
/**
@brief 在螢幕上畫出線段
@param [in] 來源座標X1
@param [in] 來源座標Y1
@param [in] 來源座標X2
@param [in] 來源座標Y2
**/
virtual void Line(float X1,float Y1,float X2,float Y2) = 0;
/**
@brief 在螢幕上畫出立體線段
@param [in] 來源座標X1
@param [in] 來源座標Y1
@param [in] 來源座標Z1
@param [in] 來源座標X2
@param [in] 來源座標Y2
@param [in] 來源座標Z2
**/
virtual void Line(float X1,float Y1,float Z1,float X2,float Y2,float Z2) = 0;
/**
@brief 設定選取模式
@param [in] X座標
@param [in] Y座標
@param [in] 選取的範圍寬
@param [in] 選取的範圍高
@param [out] 存放結果的Buffer
**/
virtual void BeginSelectionMode(float X,float Y,float Width,float
Height,unsigned int *pSelectBuffer,int BufferSize) = 0;
/**
@brief 設定物件名稱
@param [in] 物件名稱
**/
virtual void LoadName(unsigned int Name) = 0;
/**
@brief 增加物件名稱
@param [in] 物件名稱
**/
virtual void PushName(unsigned int Name) = 0;
/**
@brief 結束選取模式
@return 有多少物件被選取
**/
virtual int EndSelectionMode() = 0;
/**
@brief 線段寬度
@param [in] 寬度
**/
virtual void SetLineWidth(float Width) = 0;
/**
@brief 設定線段的樣式
@param [in] 放大的比例
@param [in] 樣式
@param [in] 是否啟用線段樣式
**/
virtual void SetLinePattern(int Factor,unsigned short Pattern,bool IsEnable
= true) = 0;
/**
@brief 設定顏色
@param [in] 顏色R
@param [in] 顏色G
@param [in] 顏色B
@param [in] 顏色A
**/
virtual void SetColor(float R,float G,float B,float A) = 0;
/**
@brief 清除畫面
@return 是否成功
**/
virtual bool Clear() = 0;
/**
@brief 交換緩衝區
@return 是否成功
**/
virtual bool SwapBuffers(HDC DC) = 0;
/**
@brief 將以視窗上的Pixel為單位的座標轉換成螢幕上的相對座標
@param [in/out] 來源座標X
@param [in/out] 來源座標Y
**/
virtual void PixelToScreen(float &X,float &Y) const = 0;
/**
@brief 將以Viewport的座標轉換成螢幕上的相對座標
@param [in/out] 來源座標X
@param [in/out] 來源座標Y
**/
virtual void ViewportToScreen(float &X,float &Y) const = 0;
/**
@brief 將螢幕上的相對座標轉換成以 視窗上的Pixel為單位的座標
@param [in/out] 來源座標X
@param [in/out] 來源座標Y
**/
virtual void ScreenToPixel(float &X,float &Y) const = 0;
/**
@brief 計算X在螢幕上移動了視窗上的PixelX後的值
@param [in] 來源座標X
@param [in] 來源座標PixelX
**/
virtual float MovePixelX(float X,float PixelX) const = 0;
/**
@brief 計算Y在螢幕上移動了視窗上的PixelX後的值
@param [in] 來源座標Y
@param [in] 來源座標PixelY
**/
virtual float MovePixelY(float Y,float PixelY) const = 0;
/**
@brief 計算X在視埠上移動了PixelX後的值
@param [in] 來源座標X
@param [in] 來源座標PixelX
**/
virtual float MoveViewportX(float X,float PixelX) const = 0;
/**
@brief 計算Y在視埠上移動了PixelX後的值
@param [in] 來源座標Y
@param [in] 來源座標PixelY
**/
virtual float MoveViewportY(float Y,float PixelY) const = 0;
inline int getWidth() const {
return m_Width;
}
inline int getHeight() const {
return m_Height;
}
inline int getViewportWidth() const {
return m_ViewportWidth;
}
inline int getViewportHeight() const {
return m_ViewportHeight;
}
inline float getZ() const{
return m_Z;
}
inline void setZ(float Z){
m_Z = Z;
}
protected:
/**
@biref 視窗寬度
**/
int m_Width;
/**
@biref 視窗高度
**/
int m_Height;
/**
@biref 視埠寬度
**/
int m_ViewportWidth;
/**
@biref 視埠高度
**/
int m_ViewportHeight;
/**
@brief 貼圖位置的Z座標
**/
float m_Z;
};
因為為了讓遊戲開發進度快一點,所以我並沒有一開始就把Interface做到最完善
取而代之的是一邊開發,一邊實作加入需要的東西,然後增加Interface的項目
所以並沒有非常完備,因為是一邊實作OpenGL一邊訂出來的Interface,所以
有某些部份沒有完全抽像化= =",算是有點偷工減料
以上,今天的部份,圖像引擎就到這邊,如果有想到什麼再補完或是修正
--
VICTOR工作室 | PTT遊戲設計版隆重開幕!
| 不管是新手老手,程式美工音樂企劃....
URL : http://www.kinmen.info/vic/ | 都歡迎來遊戲設計版參與討論 XD
| 戰略高手>
C/C++ | GameTopics>
Visual Basic 6.0 | GameDesign
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.116.64.70
推
07/30 14:31, , 1F
07/30 14:31, 1F
GameDesign 近期熱門文章
PTT遊戲區 即時熱門文章
15
19
22
32