作者StubbornLin (Victor)
看板GameDesign
标题[程式] 小型2D线上游戏心得分享 : 图像引擎
时间Fri Jul 28 02:50:41 2006
经过了宣传期之後,游戏设计版好像几乎没什麽文章,身为版主的我感到有点惭愧
最近因为要把我小型的线上游戏先赶出来,所以还蛮忙的,不过,我一直在想
(虽然每天都有写程式,不过在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
1F:推 mlwmlw:看起来好厉害(流口水)=_= 07/30 14:31