日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

游戲編輯器框架教程

系統(tǒng) 2199 0

-------------------------------------------------------
游戲編輯器框架教程
無心柳
-------------------------------------------------------

一、前言:

我一直在尋找DX編程和MFC類庫的結(jié)合點(diǎn),前段時(shí)間曾經(jīng)在第二人生http//webking.com.cn/secondlife上放了一個(gè)從《計(jì)算機(jī)編程技巧與雜志》來的例子。應(yīng)該說,那個(gè)例子非常不錯(cuò),唯一的缺點(diǎn)就是它只研究了全屏幕顯示的情況,而對(duì)于地圖編輯器人員來說,迫切需要的是既能夠完全使用原有MFC的框架又能夠使用DX的功能的東西,這也是我一直在尋找的,今天(1999/12/4)總算找到了。

促使我找到這個(gè)辦法的是為MUD編寫的那個(gè)地圖編輯器,雖然功能上沒有什么欠缺,但誠如美工所言,界面太差了,按鈕按下去的時(shí)候沒有一個(gè)響應(yīng)動(dòng)作,而且也不方便使用MFC的全部功能。在完成這個(gè)地圖編輯器以后,其他程序員的MFC編輯器也在趕制之中,而他們的圖形顯示部分是一個(gè)難題。如果要使用經(jīng)典編程方法去操作和顯示256色以上的圖片,在程序上是非常麻煩的。能否將 MFC與DDRAW的窗口模式完美地融合 ?在完成地圖編輯器以后,我已經(jīng)有了這樣的設(shè)想,就等著拿到機(jī)器上去測試了。結(jié)果一試之下,完全可行,而且它是如此地 簡單

二、第一個(gè)例子:

在這個(gè)例子中,我用VC的AppWizard生成了一個(gè)標(biāo)準(zhǔn)的單文檔窗口并保存。然后,在視類CGameEditView的頭文件中加入了四個(gè)DX成員,一個(gè)DDRAW指針,一個(gè)DDRAW4指針,一個(gè)前緩沖,一個(gè)后緩沖,具體可以看源碼。在頭文件中,另外加入了兩個(gè)函數(shù),一個(gè)是Msg函數(shù),用于顯示消息框,這是從別人的例子中直接復(fù)制過來的;另一個(gè)是InitDDrawSurface()函數(shù)。然后在CGameEditView.cpp里加入了這兩個(gè)函數(shù)的函數(shù)體。Msg沒什么說的,你直接復(fù)制上去用就行了。InitDDrawSurface你也可以直接復(fù)制,這個(gè)函數(shù)里創(chuàng)建了一個(gè)DDRAW對(duì)象,再利用它獲取了DDRAW4的接口。然后用DDRAW4接口創(chuàng)建一個(gè)DDSURFACE4主屏幕緩沖頁,它負(fù)責(zé)在屏幕上顯示內(nèi)容。最后創(chuàng)建一個(gè)DDSURFACE4的后臺(tái)緩沖頁,它負(fù)責(zé)在主緩沖在屏幕上顯示之前在后臺(tái)準(zhǔn)備一下畫面。僅此兩個(gè)函數(shù)而已。

程序中有兩個(gè)動(dòng)作,一個(gè)是在預(yù)創(chuàng)建窗口時(shí)執(zhí)行InitDDrawSurface()對(duì)DDRAW頁面進(jìn)行初始化,如果不成功程序就退出。另一個(gè)動(dòng)作就是在視類的OnDraw()中將一塊矩形區(qū)域從后臺(tái)緩沖復(fù)制到前緩沖(也就是在屏幕上顯示出來)。由于后臺(tái)緩沖沒有放入數(shù)據(jù),所以顯示的內(nèi)容將是隨機(jī)的,一般是黑色的。顯示的步驟可以看源碼上的程序注釋,我一般寫得比較細(xì)。

為什么不加入什么撞球等的變化動(dòng)作?這是因?yàn)槲抑幌敫嬖V大家一個(gè)最簡單的DDRAW窗口頁面如何創(chuàng)建和使用,下面的教程中會(huì)慢慢加入如何讀入位圖塊和顯示,時(shí)間控制,窗口區(qū)域檢測,剪切塊,顏色鍵等內(nèi)容。當(dāng)教程結(jié)束的時(shí)候,用MFC和DDRAW做一個(gè)簡單游戲應(yīng)該沒有問題了。

下載源碼 GameEdit1.zip

三、第二個(gè)例子:

1、上個(gè)例子中有個(gè)明顯的漏洞,在InitDDrawSurface()中創(chuàng)建后臺(tái)緩沖的時(shí)候,顯式地指定了寬和高。在前緩沖lpMainSurface創(chuàng)建時(shí),沒有指定大小,因?yàn)椴恍枰熬彌_指的就是整個(gè)屏幕的范圍,它使用的是顯示內(nèi)存。而后緩沖是不顯示的內(nèi)容,它實(shí)際是在系統(tǒng)內(nèi)存中(窗口模式不能在顯示內(nèi)存中再創(chuàng)建后臺(tái)頁面)創(chuàng)建的一個(gè)頁面,一般情況下,應(yīng)該設(shè)置得和前緩沖一樣大或者更大。1024*768的顯式指定對(duì)一般顯示器可能夠了,但萬一用戶使用更大的分辨率就可能導(dǎo)致錯(cuò)誤。所以第二個(gè)例子中首先修改了InitDDrawSurface()中創(chuàng)建后臺(tái)緩沖的部分,用標(biāo)準(zhǔn)WINDOWS函數(shù)GetDeivceCaps獲取了當(dāng)前顯示分辯率的高和寬(當(dāng)然也可以獲得顏色位數(shù),源碼中有)。然后用獲取的高和寬來創(chuàng)建后臺(tái)緩沖,這樣就保證了與分辨率的大小相同。當(dāng)然這也不是絕對(duì)保險(xiǎn),萬一用戶運(yùn)行中修改了分辨率仍有可能導(dǎo)致錯(cuò)誤,但一般我們不需要為那種情況負(fù)責(zé)了,可以不去考慮。

2、這次我們要讀入一個(gè)圖片,看起來挺恐怖,你好象需要去研究BITMAP的文件結(jié)構(gòu)。其實(shí)不需要那么復(fù)雜,對(duì)一般的游戲和編輯器來說,根本不用去了解那些細(xì)節(jié)的問題,在DX的例程中多次用到的兩個(gè)文件可以直接搬過來用,它們是ddutil.h和ddutil.cpp,你可以在大部分DX的例程中找到它們,然后復(fù)制到你程序的文件夾下,再在工程中加入這兩個(gè)文件,試試重編譯。直接重編譯是無法成功的,這是因?yàn)镸FC程序有點(diǎn)特殊性,要使它能被MFC所用,必須在上面提到的這兩個(gè)文件首部都追加一句#include "stdafx.h"。用過這個(gè)語句,MFC就認(rèn)這兩個(gè)文件,然后可以正常編譯通過。當(dāng)然,如果你想在VIEW類中使用里的函數(shù),還要在GameEditView.cpp的頭部加入#include "ddutil.h"。這是常識(shí),說這些好象有點(diǎn)多余,在源碼中這幾個(gè)步驟都做了而且有說明。

3、通過第2步,已經(jīng)可以隨時(shí)讀入BMP文件了,具體的讀法是非常簡單的,因?yàn)槟阋呀?jīng)可以使用ddutil.cpp里的函數(shù)。如果需要,你也可以去修改這個(gè)文件的源碼或者制作修改版。作為例子,我先在GameEditView.h中增加了一個(gè)DDSURFACE4的頁面指針:

LPDIRECTDRAWSURFACE4 lpBitMapBuffer;//DirectDraw讀入的位圖頁面保存在這里

再在GameEditView.cpp的預(yù)創(chuàng)建窗口PreCreateWindow()函數(shù)中將一幅位圖讀入這個(gè)位圖頁面。讀入成功后,將這個(gè)臨時(shí)頁面的內(nèi)容復(fù)制到后臺(tái)緩沖。這樣,后臺(tái)緩沖就有了內(nèi)容。再編譯一次程序,會(huì)發(fā)現(xiàn)原來窗口左上角那個(gè)黑塊已經(jīng)變成這幅圖片(一幅UO中截下來的騎馬圖),代碼如下:

lpBitMapBuffer=DDLoadBitmap(lpDD4,"test.bmp",200,200);
if(NULL==lpBitMapBuffer)//如果沒有讀入成功,退出程序
{
Msg("無法裝入位圖,演示無法進(jìn)行");
exit(-2);
}
//讀入成功就復(fù)制到后臺(tái)緩沖去
lpBackBuffer->BltFast(0,0,lpBitMapBuffer,&(CRect(0,0,200,200)),FALSE);

你可以看到代碼中指定的位圖文件名是test.bmp,所以你也需要一個(gè)這樣文件名的位圖文件,在下面的源碼包里附有一個(gè),如果你想換一個(gè)文件也可以,不過這個(gè)文件以后將用于演示動(dòng)畫的例子。

第二個(gè)例子完,需要的話請(qǐng)下載源碼 GameEdit2.zip

三、與GDI結(jié)合:

上面的兩個(gè)例子的源碼中沒有包含資源文件,所以在使用的時(shí)候請(qǐng)先按照上面提到的方法建立自己的簡單MFC單文檔程序,再將源碼文件替換你自己的文件再編譯。

在第二個(gè)例子中,讀入了一幅位圖并顯示在窗口的左上角。這在程序運(yùn)行中沒有任何問題,而且速度還相當(dāng)快。但如果你同時(shí)運(yùn)行了其他程序,或者將窗口移動(dòng)到屏幕的邊緣位置,會(huì)出現(xiàn)一些不正常現(xiàn)象。如果將窗口移動(dòng)到屏幕邊緣,在從后臺(tái)到前臺(tái)進(jìn)行傳送的時(shí)候,會(huì)發(fā)生非常矩形錯(cuò)誤,意思是指你試圖將頁面?zhèn)魉偷狡聊粎^(qū)域外,也就是前緩沖以外(前面說過,前緩沖與屏幕大小是一樣的)。其結(jié)果并不會(huì)使你的程序當(dāng)機(jī),只是這次傳送不會(huì)進(jìn)行。另外,當(dāng)你用其他程序的窗口蓋住本程序窗口并移動(dòng)上面的窗口的時(shí)候,本窗口的刷新可能導(dǎo)致將位圖蓋在其他窗口區(qū)域內(nèi)。這是個(gè)嚴(yán)重的問題,在編寫全屏幕程序的時(shí)候不會(huì)發(fā)生這種情況,因?yàn)槠聊槐荒愕某绦颡?dú)占了,而在編寫窗口程序的時(shí)候,你的程序就會(huì)顯示非常差勁。

要解決上面的問題,一個(gè)辦法是當(dāng)程序失去焦點(diǎn)的時(shí)候,你就禁止將位圖從后緩沖傳送到前緩沖,當(dāng)重新獲得焦點(diǎn)的時(shí)候,再恢復(fù)位圖傳送。但有時(shí)候這樣不理想,比如你在進(jìn)行程序或者游戲的時(shí)候,同時(shí)發(fā)ICQ的信息,雖然ICQ占的屏幕面積不大,還是會(huì)導(dǎo)致你的程序停止更新畫面,而如果你在游戲中此時(shí)正在緊張而且隨時(shí)需要你干預(yù)的話,程序看起來就非常不友好。

另一個(gè)辦法是與GDI結(jié)合,與GID結(jié)合會(huì)導(dǎo)致在圖像速度上有微小的下降,但會(huì)使你的程序看來非常自然。其實(shí)方法也非常簡單,就是獲取后臺(tái)緩沖的HDC,然后用HDC的BitBlt方法將后臺(tái)緩沖復(fù)制給窗口CDC,可以將OnDraw中的BltFast的方法修改為:

HDC hdc;

lpBackBuffer->GetDC(&hdc); //獲得后臺(tái)緩沖的HDC

::BitBlt(pDC->m_hDC,0,0,100,100,hdc,0,0,SRCCOPY); //將后臺(tái)緩沖的圖片傳送到窗口DC

lpBackBuffer->ReleaseDC(hdc); //不要忘了用完后釋放HDC,否則會(huì)出錯(cuò)

為了與HDC匹配,所以使用pDC的成員m_hDC。BitBlt的具體用法可以看一下幫助文件。使用這個(gè)辦法以后,無論你將窗口移動(dòng)到什么位置,以及無論你用什么窗口蓋住程序的窗口,都不會(huì)有任何不正常的現(xiàn)象發(fā)生。它唯一的缺點(diǎn)就是比BltFast慢一點(diǎn)點(diǎn)。因?yàn)镈C的處理方法是分幾次進(jìn)行,第一次復(fù)制到一個(gè)DC自己的后臺(tái)緩沖,然后根據(jù)窗口的合法區(qū)域分一次或多次復(fù)制到屏幕。所以這個(gè)方法適用于制作編輯器以及對(duì)速度不是極度敏感的游戲。如果要達(dá)到最高速度,當(dāng)然是非全屏幕模式莫屬。

?



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=3405


游戲編輯器框架教程


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 遵义县| 商城县| 积石山| 镇平县| 南康市| 晋宁县| 靖江市| 大姚县| 灌阳县| 郴州市| 玉山县| 缙云县| 庐江县| 屯门区| 彭阳县| 开平市| 武城县| 临西县| 修文县| 高密市| 万荣县| 淅川县| 哈密市| 双江| 新野县| 万州区| 固镇县| 南平市| 荆州市| 察雅县| 图木舒克市| 神农架林区| 双鸭山市| 彰化市| 凌源市| 清苑县| 武乡县| 琼中| 洛扎县| 郎溪县| 巴里|