早想寫一點游戲設(shè)計的文章與大家交流,一是經(jīng)驗的問題,二是公司正在緊張的游戲制作期,實在抽不出多少時間,一直沒有動手,今天忽然頭腦發(fā)熱,寫了一段,以后準(zhǔn)備陸續(xù)寫一些游戲創(chuàng)意,策劃,制作,流程管理,和制作工具等方面的文章供大家參考.
我們的游戲設(shè)計經(jīng)驗主要是冒險游戲和角色扮演游戲,但我們設(shè)計游戲工具時盡量適應(yīng)其余題材,不過是否可行未經(jīng)檢驗. 寫這篇文章的意圖一是想為游戲界做點事,拋磚引玉吧,另外是公司正在尋找志同道合的戰(zhàn)友, 我寫一點文章交一交朋友,許多東西僅僅是我們的經(jīng)驗,不一定很好.參考而已吧
游戲設(shè)計工具包括游戲編輯工具和游戲引擎兩塊;
游戲編輯工具
交互編輯游戲數(shù)據(jù),生成游戲引擎所需的數(shù)據(jù)文件,包括以下幾個功能塊: 圖像編輯,場景編輯,物品編輯,動畫編輯,人物編輯,事件編輯等,具體介紹在以后的文章介紹.
游戲引擎
語言:VC5.0
操作系統(tǒng):WIN95
圖像引擎:DIRECT X 5.0
支持游戲風(fēng)格:各種類型和視角以及多層次的冒險游戲和角色扮演游戲
整個游戲引擎包括以下功能塊:
資源管理:
圖像庫CIMGLIB,聲音庫CSOUNDLIB,通過編輯工具形成的資源文件來定義,每種資源包括定義管理和一些操作接口.圖像庫圖"像包括多種格式(BMP,GIF.AVI,FLC等)以及他形成的內(nèi)存格式定義,子圖定義(每一張圖片包括許多小圖,需定義它的小圖位置,當(dāng)然可以自動生成),游戲需要的特殊定義,比如行走,身體性質(zhì),中心定位點,觸發(fā)區(qū),可以根據(jù)自己的要求擴充各種性質(zhì)定義. 圖像最好允許圖像組合定義.聲音庫包括WAV和 MID的定義和再現(xiàn). 資源由IMGLIB.DAT和 SOUNGIMG.DAT定義,調(diào)試版本中最好不要將資源打包,而是指向正常的文件名,發(fā)行版本中再打包,這樣修改和不同工作人員協(xié)調(diào)容易一些,否則最好有一個自己的資源管理器.我們在調(diào)試版本中數(shù)據(jù)文件采用文本描述格式.許多數(shù)據(jù)可以手工編寫而不需要專門的編輯工具.
資源管理對象還包括內(nèi)存管理,比如設(shè)置時間閥釋放長期不用的資源.
聲音管理:
CSOUND,包括Creat(),Sound(char *fileName...),SetPos(),等,DirectSound有一些函數(shù),我們要做的是封裝簡化,減少對外的接口.
窗口系統(tǒng):
接管標(biāo)準(zhǔn)窗口系統(tǒng),一個完善的游戲引擎最好有一個自己的界面系統(tǒng),至于簡單還是復(fù)雜根據(jù)自己情況具體分析,一個具備基本功能的界面系統(tǒng)1000行程序就可以對付下來,需要窗口系統(tǒng)的原因是一般的圖像引擎不支持標(biāo)準(zhǔn)窗口,二是可以便于移植到別的操作系統(tǒng).在我們的游戲引擎中,游戲只是窗口系統(tǒng)的一種特殊控件(CWINGMCTR),因此可以實現(xiàn)多窗口游戲等特殊要求.
CWINGMCTR是一種特殊控件,通過他來控制游戲.包括控制和顯示.
圖像引擎:
所使用的圖像引擎的管理,我們使用的是DirectX,包括Creat(),CreatSurface(), OutToScr(),Bilt()等對外接口;他不是游戲的重點,我們盡量將圖像引擎細節(jié)封裝起來.
圖像管理:
這是處理圖像的中心,一般處理游戲顯示喜歡以某種圖像引擎為中心來設(shè)計,我覺得最好設(shè)計自己的對象來封裝別人的圖像引擎,這樣不會因某引擎而受限制,移植也比較容易,我們雖然使用的DIRECT X ,但實際上對外的接口是一種CPICPAGE的界面,他不但包括DIRECT X 的surface, 也包括標(biāo)準(zhǔn)的位圖,AVI界面,GIF動畫界面,以及自定義的格式,他將各種類型的圖像統(tǒng)一起來,對外使用統(tǒng)一操作,比如DRAWTEXT,BILT,LINE等標(biāo)準(zhǔn)圖形圖像操作,以及擴充的ALPHA通道,透明度等操作.為了減少內(nèi)存的需求,特別是16M高彩,不要將全部圖像使用DIRECT X的表面,對一些刷新不多的圖像,比如背景,可以使用標(biāo)準(zhǔn)256色位圖,甚至一種GIF表面,需要時再解壓,我們還使用一種單色位圖用來從背景中摳圖,比如一所場景中一棵巨大的樹,只要不是動畫,我們可以用單色摳圖的形式從背景中扣除來作為另外一層,這樣我們可以大大降低圖像的內(nèi)存需求.因此采用全部手繪(或3D場景), 而不是小圖拼貼的場景成為可能.通過各種手段可以節(jié)約60%的內(nèi)存需求.
CPICPAGE可以通過TimeTrace()以及多線程來改寫內(nèi)容,比如AVI的改變.
游戲控制:
這部分包括顯示和控制,由CGAME->CGAMEPAGE->CGMOBJ對象組成,CGAME是總控對象, 包括許多CGAMEPAGE游戲頁,CGAMEPAGE是一個具有連續(xù)場景的游戲片斷,有點類似于游戲的一關(guān), CGAMEPAGE由一系列CGMOBJ組成,CGMOBJ是游戲的基本對象,由他繼承出地圖,物體,物品,人物,武器, 動畫,觸發(fā)器,多媒體按鈕等特殊游戲?qū)ο?這是一個根據(jù)游戲要求不斷豐富和改寫的部分,對外的接口是:SendDraw(),Draw(),TimeTrace(),AcceptMsg(),SendNetMsg(),AcceptNetMsg()等,他是通過CWINGMCTR來調(diào)用,每種對象有許多控制參數(shù),對象之間允許通訊,以及有自己的生長死亡發(fā)展的控制,盡量做到對象與外界減少直接接口,通過消息實現(xiàn)交流.
對象分為兩類:
景色對象和活動對象,
景色對象定義了組成場景的元素,包括背景和前景兩層,可以是由整個圖片組成或由RPG常用的圖片拼貼法的組成,它的特點只作為背景或前景,活動物是在他們的之間活動,一般定義后不做改變, 也不做控制,由于支持圖像界面多格式,所以我們可以方便地使用AVI或 GIF動畫作為背景來增加場景的效果和真實性.景色還包括了行走性質(zhì)定義,我們采用的是8x8為一單元,每個單元定義了一種性質(zhì),比如平地,草地,障礙物等.
活動對象是在背景和前景之間活動,他們之間有相互的位置關(guān)系,前后關(guān)系隨著位置改變會不斷改變,因此他在所屬的CGAMEPAGE中次序是動態(tài)的.對象的關(guān)系一般是由Y軸定義,由于要支持斜視角和復(fù)雜的地形結(jié)構(gòu),光靠Y軸是不夠的,我們引入了地基線的概念,通過在地基線之上還是之下來判斷前后關(guān)系,地基線的定義在圖像定義中描述.活動對象有復(fù)雜的參數(shù),可以接受外界消息,可以有自己的各種反應(yīng).我們在引擎中使用了一種描述語言來描述他們的反應(yīng),比如對鼠標(biāo)擊打,人物經(jīng)過等產(chǎn)生參數(shù)改變,發(fā)聲,對話等的回應(yīng).描述語言將作為專門的一章來介紹. 游戲顯示過程是這樣的, 在每次刷新期時窗口的游戲控件調(diào)用他所屬的游戲頁 CGAMEPAGE->SendDraw(); 游戲頁將要顯示的對象按前后次序送往窗口,同時注明此對象是否改變,窗口分析改寫的區(qū)域,調(diào)用每個對象的Draw()接口來刷新活動的區(qū)域,為了增加速度,并不是顯示所有的區(qū)域,而是只改寫活動區(qū)域,因此我們設(shè)計了一個CCLIP的對象來管理刷新定義,它的原理是將表面分為16*16的單元, 最終顯示時計算出優(yōu)化后的多個剪切區(qū)域.整個窗口系統(tǒng)和每個游戲控件擁有自己的CCLIP對象.另外一項增加速度的方案是游戲控件擁有一個比顯示窗大兩倍的顯示頁,這樣場景滾動時只要將顯示位置改變即可,不用刷新所有區(qū)域. 游戲控制的過程是這樣的:AcceptMsg()來接受各種消息調(diào)用腳本來改變自己參數(shù)和狀態(tài)并影響別的對象,另外每次時鐘來時,調(diào)用每個對象的TimeTrace()來改變狀態(tài),比如動畫改變,運動軌跡改變, 觀察周圍的對象做出反應(yīng)等.
系統(tǒng)控制模塊:
對系統(tǒng)的參數(shù)做出反應(yīng).不同的題材控制不一樣,比如即時戰(zhàn)略等.只要改寫這部分以及擴充游戲?qū)ο?引擎便能支持不同的題材.至于人工智能,智能行走,只是對象的方法,比較簡單,只是需要時間. 游戲控制部分比較復(fù)雜,每一種游戲?qū)ο蠖加性S多控制的細節(jié),在這篇文章里不做具體描述,以后再說吧.
最后一個是網(wǎng)絡(luò)模塊:
我們正在開發(fā)的是國內(nèi)第一個圖形化MUD游戲,網(wǎng)絡(luò)是它的核心部分,介紹網(wǎng)絡(luò)的內(nèi)容很多,需專門文章.我們使用的不是DirectPlay,使用的是WinSoct,考慮的是UNIX作為服務(wù)器的需求.網(wǎng)絡(luò)要解決的難點是安全,同步和數(shù)據(jù)壓縮,這里要用到許多技巧.
游戲是通過數(shù)據(jù)文件來定義:
數(shù)據(jù)文件格式:
數(shù)據(jù)文件包括資源定義文件和游戲定義,界面定義文件,文件的數(shù)據(jù)格式我們采用的是文本形式,類似于WEB的文本,這樣的好處一是版本升級容易處理,二是可以減少前期對編輯工具的功能要求,因為我們可以用文字編輯器處理大部分數(shù)據(jù),然后有時間再設(shè)計一個強大的工具比較現(xiàn)實, 當(dāng)然,最終提供給用戶的是處理后的數(shù)據(jù)文件.他中間有一個轉(zhuǎn)換模塊.
游戲的運行流程描述(不是真正的過程,按DOS格式描述):
CreatGameWindow();//初始化window窗口
CreatDraw(hWnd); //初始化圖像引擎
CreatSound();//初始化聲音引擎
CreatAvi()//初始化AVI引擎
CreatNet();//初始化網(wǎng)絡(luò)引擎
LoadGameData();//讀取游戲定義數(shù)據(jù),包括資源定義文件和游戲定義,界面定義
While(1)
{
WINTraceMsg();//處理系統(tǒng)消息,比如鼠標(biāo),鍵盤等
GameTimeTarce();//處理活動的游戲頁的時間反應(yīng)
WinPaint();//刷新游戲顯示
OutToScr();
}
我們這里介紹的是單線程結(jié)構(gòu),許多部分可以用多線來加快游戲速度,但結(jié)構(gòu)是一樣的,就不多介紹了.
游戲引擎的系統(tǒng)分析是游戲設(shè)計技術(shù)方面的成功關(guān)鍵,是最容易走彎路的部分,希望我們的文章能給大家一點啟發(fā),由于今天的游戲趨向于多類型綜合,設(shè)計引擎時一定不要拘泥于某一單項題材, 我們在策劃這套引擎時要求他支持的游戲非常廣,甚至支持多媒體設(shè)計,這套引擎只要擴充或改寫參數(shù)管理以及游戲?qū)ο?便能支持各種風(fēng)格的2D類游戲.將來我們要做的是一套可以交互設(shè)計各種游戲的開發(fā)平臺,當(dāng)然不是<<游戲工廠>>似的玩具.
今天就寫到這里,這只是對引擎結(jié)構(gòu)的大概介紹,其中每一點將來都有詳細的描述,歡迎同志商討. 我們盡量回答朋友們的意見,歡迎加入我們的隊伍.
游戲引擎與游戲引擎開發(fā)入門2
windows下比較常用的圖像引擎是DirectX,國內(nèi)資料比較少,我給大家推薦過《高性能 WINDOWS圖形設(shè)計》這本書,大家不妨找一下. 在我們的游戲引擎中,目前使用的也是DirectX,網(wǎng)上見到有關(guān)DirectX的簡化接口的對象庫,沒有使用過,不知如何,最好是自己做這些對象,靈活些. 圖像引擎在游戲中的作用是這樣的,設(shè)置顯示模式,管理操作一種特殊圖像表面,顯示到屏幕.
圖像引擎對象:
class DirectDrawWin
{
HWND hWnd;
BOOL IsUse;
int winWidth,winHeight;
LPDIRECTDRAW2 ddraw2;
LPDIRECTDRAWSURFACE primsurf;
LPDIRECTDRAWPALETTE palette;
CDirectPAGE
bakDirectPAGE;//背景表面,是CPICPAGE的繼承對象CDirectPAGE的實例
LPDIRECTDRAWCLIPPER clipper;
RECT displayrect;
int displaydepth;
WORD loREDbit, numREDbits;
WORD loGREENbit, numGREENbits;
WORD loBLUEbit, numBLUEbits;
public:
DirectDrawWin();
~DirectDrawWin();
BOOL IsWorking(void);
int OnCreate(HWND _hWnd,BOOL IsFullWin=FALSE,int colors=16,int width=640,int height=480);
void DrawScene();
BOOL ClearSurface( LPDIRECTDRAWSURFACE surf, DWORD clr, RECT* rect=0 );
BOOL ClearSurface( LPDIRECTDRAWSURFACE surf, DWORD r, DWORD g, DWORD b, RECT* rect=0 );
BOOL BltSurface(LPDIRECTDRAWSURFACE destsurf,LPDIRECTDRAWSURFACE srcsurf,
int srcInX, int srcInY,DWORD flap,
RECT *DecView=NULL,RECT *souRectBlt=NULL,//源圖片目標(biāo)區(qū)
RECT *lpFillRect=NULL);
CPICPAGE *GetDecDrawPage(void);
LPDIRECTDRAWSURFACE CreateSurface( DWORD w, DWORD h );
HRESULT SetColorKey(IDirectDrawSurface *pdds, COLORREF rgb);
//======================================================================
private:
void SetHWnd(HWND _hWnd);
HWND GetSafeHwnd(){return hWnd;};
BOOL CreateFlippingSurfaces();
void OnDestroy();
DWORD RGBtoPixel(DWORD r, DWORD g, DWORD b);
void GetSurfaceRect(LPDIRECTDRAWSURFACE surf,RECT *lpRc);
DWORD ColorMatch(IDirectDrawSurface *pdds, COLORREF rgb);
BOOL GetSurfaceRect( LPDIRECTDRAWSURFACE surf, RECT& rect);
//////////////////////////////////////////////////////////////////////
WORD LowBitPos( DWORD dword );
WORD HighBitPos( DWORD dword );
BOOL StorePixelFormatData();
BOOL DetectDisplayMode();
};
大家可以看到,對外的接口有限,主要是初始設(shè)置OnCreate,輸出到屏幕DrawScene, 然后是表面的生成CreateSurface和圖像操作ClearSurface,BltSurface; 初始設(shè)置OnCreate():初始DrectX,設(shè)置顯示模式,申請前表面,背景表面.對于即時滾屏的游戲,為了加快速度,可以將背景表面設(shè)置得比顯示區(qū)大,這樣滾動時只要局部更改活動區(qū),設(shè)置DrawScene時的起始位置即可.但我們沒有使用這項技巧,我們的系統(tǒng)設(shè)計原則之一是:盡量少用技巧,靠系統(tǒng)設(shè)計提高速度,而不是局部技巧,原因是技巧的適應(yīng)范圍一般有限.系統(tǒng)盡量要求通用. 表面的生成和圖像操作被一個叫CPICPAGE的通用圖像頁調(diào)用,CPICPAGE是一個包括各種位圖格式的統(tǒng)一管理對象,游戲在進行圖像操作時,不直接與DirectX圖像表面打交道, CPICPAGE擴展了DirectX圖像操作功能,比如帶alpha通道的BLT,以及帶亮度的BLT,直接對表面的Line,DrawTxt等.BltSurface()是一個包括許多剪裁定位輸求的函數(shù). 對于窗口模式下的DrawScene,為了避免屏幕產(chǎn)生圖像撕裂現(xiàn)象,可以利用垂直同步刷新同步地更新屏幕,為了減少此過程的等待時間,可以使用多線程技術(shù). 為了加快游戲顯示速度,在使用DirectX中有許多可以挖掘的技巧. 有關(guān)DirectX的部分我不作詳細介紹,網(wǎng)上有一部分資料,另外可參閱《高性能 WINDOWS圖形設(shè)計》一書,我們的這個對象就是在其書的基礎(chǔ)上簡化而來,需要這部分源代碼的朋友可來信與我們聯(lián)系.
游戲引擎與游戲引擎開發(fā)入門3
圖像頁指的是內(nèi)存中保存圖像數(shù)據(jù)的各種表面,屏幕緩存,各種圖片數(shù)據(jù),窗口界面的界面數(shù)據(jù)等,不要只依靠DirectX的表面,最好單獨用一個對象來管理這些內(nèi)容,避免直接與 DirectX打交道,這樣改變引擎和移植到別的操作系統(tǒng)的工作量會小得多. 在我們的游戲引擎設(shè)計中,CPICPAGE是一個功能強大而且擴充性極好的對象,比如我們不想使用DirectX表面,而想自己設(shè)計一種表面結(jié)構(gòu),游戲的其余部分不須任何改變,只要從CPICPAGE 發(fā)展出CSELFPAGE的對象即可.象我知道的"騰圖"公司的余雪松和吳冬黎(兩個非常優(yōu)秀的程序師,我從他們那里收益非淺,他們也是國內(nèi)比較早的"xx"游戲站點的主人)就有一套自己的功能強大的圖像表面.游戲?qū)D像的操作一般不是直接對具體類型的表面操作,而是調(diào)用他們的根對象CPICPAGE.
在我們的游戲引擎中,圖像頁結(jié)構(gòu)是這樣的
CPICPAGE
CBitmapPage//標(biāo)準(zhǔn)windows的位圖,如果使用16M色模式,對于一些不常更新的圖像,使用
//16M色的DirectXDraw是種巨大的浪費,比如背景,我們可以保存一塊比視
//口大的DirectXDraw表面作為背景區(qū),只在一定條件下才將256色原圖
//CBitmapPage寫入背景區(qū)(使用任意調(diào)色版可保證非常高的圖像質(zhì)量,特別
//是使用Potoshop 5.0或Animatorfor Window 作為真彩轉(zhuǎn)換256色工具,顏
//色失真極小),平時游戲讀的是高速的DirectXDraw背景表面
CDirectXDrawPage//標(biāo)準(zhǔn)的DirectXDraw表面,
CGifPage//Gif動畫表面,隨著時間自動修改圖像內(nèi)容,繼承CDirectXDrawPage
CAviPage//AVi動畫表面,隨著時間自動修改圖像內(nèi)容,繼承CDirectXDrawPage,可以帶自己線程
CFlcPage//Flc動畫表面,隨著時間自動修改圖像內(nèi)容,繼承CDirectXDrawPage
目前我們只設(shè)計了這些類型,但可以供據(jù)需要隨時擴充.
class CPICPAGE
{
protected:
char picStyle;//圖像類型
BOOL CanWrite;//是否可以寫
int picWidth,picHeight;//尺寸
DWORD activeMode;//靜態(tài),可釋放,
unsigned short
useTimeMark;//使用時間標(biāo)記,如果長時間未使用,則保存到虛擬文件中
char *programeBuf;//可以用代碼來控制圖像的改變,
//我們支持腳本語言對圖像進行特殊控制
char *lpImgBuf;//圖像內(nèi)存
long imgBufLen;//內(nèi)存長度
HDC hDC;//標(biāo)準(zhǔn)設(shè)備句柄,指對CDirectXDrawPage和它的繼承對象有效
BOOL hasChg;//圖像內(nèi)容是否已經(jīng)改變
BOOL UseClip;//是否設(shè)定顯示剪裁區(qū)
RECT clipRc;//顯示剪裁區(qū)
public:
CPICPAGE();
~CPICPAGE();
virtual void Destroy(void);
char GetPicStyle(void);
BOOL GetSize(int *w,int *h);
void GetRect(RECT *lpRc);
char *GetImgBuf(void);
BOOL Load(char *lpFileName,long startOfs=0);從文件中讀取內(nèi)容
virtual BOOL LoadFile(FILE *lpFileHandle,long
startOfs=0){return FALSE;};
virtual void BeginDraw(){};//如果是標(biāo)準(zhǔn)的DirectXDraw表面,再進行
//Window的標(biāo)準(zhǔn)圖形讀寫時要獲得HDC,如果是連續(xù)寫,不要
//馬上釋放,反復(fù)申請和釋放HDC會大大降低速度
virtual void EndDraw(){};//終止Window的標(biāo)準(zhǔn)圖形讀寫,釋放HDC
virtual HDC GetHDC(void){return NULL;};
virtual void Line(int bx,int by,int ex,int ey,COLORREF rgb);
virtual void drawStrgs(char *strg,short bx,short by,
char drawBox,short choice);
virtual void Draw(RECT *lpRc,COLORREF *lpCr,char
drawStyle,DWORD otherMess);
virtual void Fill(RECT *rc=NULL,COLORREF colorFill=0);
virtual void DrawRect(RECT *rc,COLORREF colorLeft,COLORREF
colorRight,
COLORREF colorFill,COLORREF colorKey,
DWORD drawStyle);
virtual BOOL BltInView(
CPICPAGE *lpDec,
int srcInX, int srcInY,//x,y是souRectBlt相對于整個des表面的位置
DWORD flap=0,
RECT *DecView=NULL,
RECT *souRectBlt=NULL,//源圖片目標(biāo)區(qū)
RECT *lpFillRect=NULL)
{return FALSE;};
virtual BOOL FillRect(CPICPAGE *lpSou,RECT *lpSouRect=NULL,RECT
*lpDecRect=NULL){return FALSE;};
virtual BOOL Scroll(int scrollX,int scrollY,RECT
*lpRect=NULL){return FALSE;};
virtual BOOL ChgSize(int chgWidth,int chgHeight,int
mode=0){return FALSE;};//0 設(shè)置尺寸,1 改變尺寸
virtual BOOL HasLost(void){return FALSE;}; //已經(jīng)丟失圖像數(shù)據(jù)
virtual BOOL Scroll(int scrollX,int scrollY,COLORREF
fillColor=0,
RECT *lpScrollRc=NULL){return FALSE;};
virtual void
TimeTrace(vodi);//時間跟蹤,動畫可以在此時更改自己的圖像
};
class CDIBPAGE:public CPICPAGE
{
HDIB hDIB;
LPSTR lpDIBHdr;
unsigned aLineByte;
BYTE biBitCount;
char style;
char *LpGetIMG(void);
public:
CDIBPAGE(){picStyle=BMPPIC;};
BOOL Creat(int width,int height,DWORD mode=0);
BOOL SetBmp(char *_lpImgBuf);
BOOL LoadFile(FILE *lpFileHandle,long startOfs=0);
BOOL StretchDIBits(HDC hDC,LPRECT lpDCRect,LPRECT
lpDIBRect,DWORD dwRop,BOOL canChg=FALSE);
BOOL Blt(HDC hDC,LPRECT lpDCRect,LPRECT lpDIBRect,DWORD
dwRop=SRCCOPY);
virtual BOOL BltInView(
CPICPAGE *lpDec,
int srcInX, int srcInY,//x,y是souRectBlt相對于整個des表面的位置
DWORD flap=0,
RECT *DecView=NULL,
RECT *souRectBlt=NULL,//源圖片目標(biāo)區(qū)
RECT *lpFillRect=NULL);
};
class CDirectPAGE:public CPICPAGE
{
LPDIRECTDRAWSURFACE surf;
public:
CDirectPAGE(){surf=NULL;picStyle=DIRECTPIC;}
~CDirectPAGE();
void Destroy(void);
BOOL Creat(int width,int height,DWORD mode=0);
LPDIRECTDRAWSURFACE GetSurface(void) {EndDraw();return surf;}
virtual BOOL LoadFile(FILE *lpFileHandle,long startOfs=0);
HDC GetHDC(void);
void BeginDraw();
void EndDraw();
virtual BOOL BltInView(
CPICPAGE *lpDec,
int srcInX, int srcInY,//x,y是souRectBlt相對于整個des表面的位置
DWORD flap=0,
RECT *DecView=NULL,
RECT *souRectBlt=NULL,//源圖片目標(biāo)區(qū)
RECT *lpFillRect=NULL);
void Fill(RECT *rc=NULL,COLORREF colorFill=0);
BOOL Scroll(int scrollX,int scrollY,COLORREF fillColor=0,
RECT *lpScrollRc=NULL);
};
游戲引擎與游戲引擎開發(fā)入門4
這里所說的游戲資源管理不僅僅只是資源打包,它包括了定義和壓縮,打包,以及各種性質(zhì)定義和操作接口. 本章只介紹圖像資源管理. 定義文件名:IMGLIB.DAT 在調(diào)試版本中我們使用的腳本語言,只有在發(fā)行版本中才將其加密和壓縮. 文本舉例:
PATH ".\IMGLIB\"
//放置圖片的路徑,在調(diào)試版本中,圖片是不打包的,發(fā)行版本中
//才打包和壓縮在一個文件中
#def
id=0,name="1",file//對象類型,有文件型,圖素拼貼型,復(fù)合型等,可以擴充自己的類型
#begin
include file "man.bmp" //包含"man.bmp"的圖片
include file "manalpha.bmp" //alpha通道圖片
makpicpage directXpage
//生成的表面類型,缺省是DirectXDraw表面,參見"第四章"
memctroll TRUE //內(nèi)存自動管理
litImgs 16 //總共有16張小圖
litimg place (0,0,30,30)
(30,0,60,30)...//子圖在圖片中的位置,可以自動生成
//litimg place auto //子圖在圖片中的位置,自動生成
defgo 0,0,0,0,0,3,5... //行走性質(zhì)定義,我們使用的8*8為一單元
touch litimg=0,(10,0,0,1,1,30,30..)//可以定義子圖復(fù)雜的觸發(fā)區(qū),這在
//冒險游戲和多媒體中有時需要
middle all in top( or all in bottom or seldef 0,0,..)
//每張子圖片的中心定位點,這在人物行走時特別重要
//定位有幾種方法:頂點,坐標(biāo),....
#end
大家可以看出,這是一個很復(fù)雜的定義格式.他不像許多游戲直接使用圖片作為資源,而是包含了一些控制描述的復(fù)合定義,當(dāng)然最簡單的形式也就是一個文件名,其余可以使用缺省控制. 首先說說素材的類型,我們經(jīng)??吹降貓D編輯器的介紹,提來提出無非是什么拼貼視角等等詞語, 在我們的引擎中,許多界限都被打破,比如地圖的構(gòu)成,象《仙劍奇?zhèn)b》許多游戲使用的是一種我們稱為"圖素拼貼"的技術(shù)構(gòu)成,它的原理是采用8*8(或其他尺寸的單元)距陣紀錄每個單元對用的材質(zhì)的序列號,而不是使用實際的點陣數(shù)據(jù),這樣可以節(jié)約大量的內(nèi)存,另外一種方法是直接使用整張繪制的圖像,比如直接由3D設(shè)計的一個場景,這在象《命運之手》等游戲中使用過.而在我們的引擎中, 這些游戲類型的定義都打破了,我們統(tǒng)一使用的是大的圖片,但這張圖片可以是只包含索引的拼貼紀錄,甚至可以是其他已定義資源的合成資源. 隨著硬件內(nèi)存的增加,使用整張圖片作為連續(xù)滾屏(而不是切換)的背景成為可能,但如果不注意壓縮,16M色的內(nèi)存需求仍然讓人恐怖,雖然效果是上去了,所以我們一方面提出了一些場景組成方案, 圖像壓縮使用方案,在某些局部兼容原來的"圖素拼貼"的技術(shù)有時也是必要的. 這個資源使用的方法很簡單:
IMGLIB::Blt(int imgid,int sonImgNo,CPICPAGE *decPage,RECT *decPlace,...);
省略的是其他擴展寫法,比如亮度控制,alpha控制等等.不管資源是什么類型,接口一致,保證了系統(tǒng)的擴充性,這就是對象繼承的優(yōu)勢,在整個系統(tǒng)構(gòu)架中,我們都注意了這些,比如前面提到的 "三:圖像頁CPICPAGE介紹".
子圖:每一張圖片可以包含許多小圖片,比如一個人的一套動作包含一張圖片中,這樣容易管理, 子圖數(shù)要定義其在圖像中的Rect,我們使用一種色為子圖邊框色,這樣可以自動得到位置,而不是每個手工測量,也沒有子圖必須使用統(tǒng)一尺寸的要求.當(dāng)然怎么做不重要,只要你得到了結(jié)果,生成尺寸也是配套的開發(fā)工具必須解決的事情. 每一張圖片可以帶對應(yīng)的一張圖片作為alpha通道圖片,這是生成一些特技效果的需求,我們會在另外一張專門介紹當(dāng)前比較常用的一些特技效果技術(shù)比如光影煙霧等和實現(xiàn)辦法以及他對提高游戲效果的意義.
行走性質(zhì)的定義:定義每張圖片的一些性質(zhì),比如地面,懸崖,障礙等,對如人物,還有頭,手,心等詳細定義,這樣可以制作一些格斗游戲.
觸發(fā)區(qū):普通的圖片觸發(fā)區(qū)要么是包含它的方框,要么是實體區(qū),對于一些多媒體,要求在一張圖片中包含多個非規(guī)則的觸發(fā)區(qū),比如一個人的圖片,擊打不同的軀體位置顯示不同的動畫,這便用到此定義,使用:int IMGLIB::GetTouch(int imgId,int sonImgNo,POINT *pt);得到此點在觸發(fā)區(qū)的序號. 生成表面類型:定義此資源生成的CPICPAGE的類型,這是為了盡量減少內(nèi)存的需要. 見第三章.
中心定位點:一般地圖背景使用的做左上角為定位點,而人物通常使用的是圖片的下部中間為定位點,我們在腳本語言中規(guī)定了幾種標(biāo)準(zhǔn)定位方式,但對于一些非規(guī)則體,比如中心位置不標(biāo)準(zhǔn)的人物圖片,允許使用坐標(biāo)標(biāo)定.
圖像資源管理使用的是一個CIMGLIB的對象,對象包含了一個資源的列表單. 通過前幾章,我們基本上可以顯示一個地圖和人物動畫了,再加上控制,一個簡單的游戲就可以演示了.
下面簡單的描述一下過程:
hWnd=InitWindow(640,480)
DirectXWin.OnCreat(640,480,TRUE);
ImgLib.Load("IMGLIB.DAT");
while(1)//按dos寫法
{
delay(100);
time++;
//刷新游戲顯示
{
CPIGPAGE *lpPage=DirectXWin.GetBakPage();//得到背景圖像頁
Imglib.Blt(0,1,lpPage,0,10);//將序號為0,子圖號為1的背景圖片顯示在0,10上
Imglib.Blt(2,time%10,lpPage,100,100);//將序號為2,子圖號不斷改變的人物圖片顯示在背景上
}
DirectXWin.OutToScr();//輸出到屏幕
}
一個游戲引擎包含了太多的內(nèi)容,不知這篇文章什么時候能寫完?! 由于這套引擎本身功能比較全,要介紹的特別具體我們時間不允許,里面許多地方由于時間關(guān)系語言邏輯沒有條理, 甚至不通,大家原諒.