我的DirectDraw7學習之旅

2021-04-02 21:48:42 字數 4294 閱讀 4089

我的directdraw7學習之旅

學習directdraw大概兩個月,這兩個月也是我系統地學習遊戲程式設計的兩個月。所以在這個時間段裡,我還學習了其他的東西,例如c++----當然,c++不是容易學的,我只學了點皮毛-----後來看《c++程式設計經典》,看到滿世界的物件,頓時覺得自己的程式中的那些「物件導向」是多麼粗糙!

我的整個學習過程都是以漸進式做東西而推進的,即是學到乙個階段了就會去做乙個遊戲---這樣學習很快,可以很快的把握住乙個整體的脈絡!

下面是我在自己的學習日誌中記錄的一些東西,前面一些比較零散,後面有專門做總結的,有意見的或者想要詳細資料的可以email我。

2005.12.1

要在視窗模式下對頁面進行象素級別的操作,只能判斷當前顏色深度從而執行不同的**。在視窗模式下,預設的頁面位深度是和當前螢幕的位深度相同的,當然你可以指定乙個顏色深度來建立表面,但是網友們說那沒有多大意義。而我覺得有意義的地方在於:可以只寫一分**,而不用去根據當前桌面位深度去執行不同的**!事實上,要在視窗模式下建立指定位深度的頁面,只能建立非rgb模式的頁面,且只能放進系統記憶體!

而在全屏模式下,其他頁面的位深度也和主頁面相同。

2005.11.16

對於點陣圖的象素級操作,無非就是從點陣資訊的每個點中取出顏色資訊,然後再構造成頁面允許的格式寫入頁面,從而達到blt。

2005.11.17

模糊效果,簡單的方法是取目標點四周4點的平均值。但是如果對於同乙個頁面,這樣顯然是不行的。(每次都會影響旁邊的點)。

所以應該用兩個頁面(當然也可以放置兩個記憶體區域,都是一樣的原理)進行這種操作,在頁面a取目標點四周4點的平均值,然後在把這個值寫入頁面b的目標位置處,然後頁面b就會比頁面a模糊一點!(在xheartblue的**上的fireworks程式中就用到了這個技術----事實上我的這個方法就是從他的那個程式裡學到的。當初在學習粒子系統的時候,想找份原**,就發郵件給那篇文章的作者,就是xheartblue,他就給了我他的個人**位址,使我得到了那份**~)

2005.11.18

directdraw學習總結 1.

首先要明白的是,directdrawsu***ce 物件是記憶體(視訊記憶體)裡的一塊連續的儲存區。 2.

當乙個頁面被鎖定(呼叫lock或者getdc)後,再呼叫其 blit方法向其它頁面位塊傳送,就會返回dderr_su***cebusy或者dderr_lockedsu***ces的錯誤資訊。 3.

結構即使剛定義也最好用zeromemory將其清0,否則建立頁面等就不會成功。directdraw 4.

貼位圖到頁面上:

hdc hmemdc=createcompatibledc(null);

hbitmap hbitmap=(hbitmap)loadimage(null,filename,

image_bitmap,0,0,lr_loadfromfile);

selectobject(hmemdc,hbitmap);

lpddssu***ce->getdc(&hdc);

bitblt(hdc,0,0,width,height,hmemdc,0,0,srccopy);

lpddssu***ce->releasedc(hdc);

5.無論是在視窗模式下還是在全螢幕模式下,主頁面都代表整個螢幕。建立主頁面上時就不需要指定其大小,而建立離屏頁面就要指定。 6.

果你要把頁面a以ddblt_srcblt方式傳送到頁面b,即頁面a是作為源頁面,那麼在你就要給頁面a設定顏色鍵。 7.

計時機制的tick=gettickcount()不能放到訊息迴圈中,否則當沒有訊息時,tick就得不到更新。 8.

預設情況下,離屏頁面的位深度等於主頁面的位深度,在視窗模式下,主頁面的位深度為當前螢幕設定的位深度。 9.

得到乙個頁面的位深度,可以先lock後,從填充的ddsd.ddpfpixelformat.dwrgbbitcount得到,也可以呼叫idirectdrawsu***ce::getpixelformat來得到,對於16位頁面,還可以得到其是565格式還是555格式。(如果是565格式,dwrgbbitcount==16,555就等於15),

由於一般每個頁面位深度都是一樣的,都和當前的顯示模式相同—即使顯示模式是你自己定義的(即全螢幕模式下setdisplaymode),所以還可以呼叫idirectdraw4::getdisplaymode(lpddsu***cedesc2);從ddsd.ddpixelformat.dwrgbbitcount得到!

10.

對頁面進行象素級的操作,先 lock住乙個頁面,然後就以ddsd.lpsu***ce(void*型別的),和ddsd.lpitch。對於24位和32位頁面,由於rgb都有乙個位元組,所以a:取lpsu***ce為byte*型的,自己移動來取得rgb顏色分量。b:取 lpsu***ce為dword(4位元組,24位由於沒有哪種資料型別為3位元組的,所以這個方法對它不行),用來容納乙個點(包含了rgb顏色分量在其中),然後從其中分離得到rgb顏色分量。反之,將顏色分量(或整個象素)寫進lpsu***ce即可達到寫頁面的目的。

11.

關於位圖:24位位圖的三基色是以bgr的形式排列的。讀入位圖資料,一般只需要點陣資料:二進位制形式開啟檔案

à讀入fileheader,如果bftype!=0x4d42則不是bmp檔案-

à讀入infoheader,取得width,height,bits 來確定分配多大的記憶體空間---

à分配記憶體--

à移動檔案指標( 根據fileheader的bfoffbits)到點陣資料處,讀點陣資料放到剛剛分配的記憶體。從記憶體中根據座標分離每個點的顏色資訊,然後寫入頁面,即可達到blt到頁面的作用。

12.

簡易演算法(由xheartblue的 煙火程式學來)

blur

建立兩個螢幕大小的點陣圖()這裡是對整個螢幕進行模糊,建立位圖本質上是分配記憶體,主要是此技術模擬了

dib),從位圖

a取乙個點周圍四點的顏色資訊(需要分離

rgb)的加權值,然後將結果放入位圖

b及後台緩衝頁面,這樣當處理完

a的所有資料時,

b中就有了一幅相對較模糊的圖案,交換兩個點陣圖的位址(就是交換兩個指標的值),迴圈呼叫這一過程,這樣就可以達到整個螢幕模糊到什麼也看不到的效果。

2005.11.22

對於淡入淡出效果,其實就是alpha-blending的靈活運用。 alpha-blending技術是一種象素混合技術,簡單的說,就是先分別從目標頁面(並不侷限於頁面)和源頁面取出象素的rgb顏色資訊,再分別對每個象素的rgb三基色做 alpha混合運算,最後把結果寫入目標頁面,這個時候目標頁面就是兩個頁面 alpha混合後的結果!

alpha混合的基本公式是:result=alpha*srcpixel+(1-alpha)*destpixel其中0<=alpha<=1;有時候因為速度問題會對這個公式進行一定的變形!---從這個公式可以看出,其實就是要讓最後的結果既有源象素的特徵又有目標象素的特徵,這樣看上去就會呈現出混合效果了!

首先我們要會對頁面進行象素級別的操作------因為必須要去取出象素—然後把象素裡的rgb三基色分離出來。例如以下為16位565格式,假設color已經儲存了乙個象素。

得到三基色的方法:blue=color&0x1f;

green=(color>>5)&0x3f;

red=(color>>11)&0x1f;

很簡單的位操作,在乙個象素中,red在最高5位,中間6位是綠色,最低5位是蘭色。

分離了顏色資訊後,再分別對每個象素的三基色進行alpha混合。

db=((sb-db)*alpha)/32+db;

dg=((sg-dg)*alpha)/32+dg;

dr=((sr-dr)*alpha)/32+dr;

db代表destblue,sb代表sourceblue,其他的變數就可以自己推出。這裡為什麼沒有採用》5而是要去/32呢?我也不清楚,反正我當時用》5為時沒有成功,顏色資訊是亂的,用/32是正確的。希望高手幫我指正一下!

最後再把顏色資訊合成起來,並放進目標表面即可。

color=blue | ( green<<5 ) | ( red <<11 );

以下是詳細**,它工作在16位色深模式:

bool alphablend16(lpdirectdrawsu***ce7 lpddsdest,rect rectdest,lpdirectdrawsu***ce7 lpddssrc,rect rectsrc,int alpha)

lpddsdest->unlock(null);

lpddssrc->unlock(null);

return true; }

ok~本文就暫告一段落了,全文沒有什麼很高深的技術,甚至是些過時的技術。我只是把它寫出來給自己做個總結,也算是複習吧!

有問題請mail我[email protected]

我的學習記錄7

2017.10.17 李錦浩 第07天 1 今天完成了昨天未完成的程式,並且除錯成功,目前 沒有發現有什麼問題,但對於程式的高效簡潔性來說我覺得我做的還是不夠,還需要繼續努力。2 今天還自學了函式的呼叫和自定義,對於函式中的返回值及函式的部分呼叫機制理解並能夠運用。附 昨天的程式完成版 includ...

41 我的C 學習筆記7

關係運算子屬於二元運算子,用於程式中的變數之間 變數和自變數之間以及其它型別的資訊之間的比較,它返回乙個代表運算結果的布林值。當運算子對應的關係成立時,運算結果為true,否則為false 所有關係運算子通常用在條件語句中來做為判斷的依據。c 中的關係運算子共有6個。關係運算子就好像對兩個鐵球進行比...

我的linux學習日記day7

r read 讀取檔案列表的許可權,數字4表示 w write 寫入 刪除 修改的許可權,數字2表示 x execute 進入目錄的許可權,數字1表示 許可權分配 檔案所有人 檔案所屬主 其他使用者 例如 rw r r 換成數字 644 修改所屬人或組 chown 檔案所有人 檔案所屬主 檔名 修改...