兩個小時學會DirectDraw程式設計

2021-04-08 23:22:26 字數 4700 閱讀 9047

這並非譁眾取寵, 通常學習一種電腦技術有兩種方法. 一種是自己摸索, 在錯誤的方向上一錯再錯, 屢戰屢敗, 不過最後得道成功. 另一種是有人 或好的材料指導, 因而事半功倍, 在正確的方向上走了速成的捷徑. 就象kfc 的雞一樣. 第一種學法能學出電腦天才, 因為所謂電腦高手, 其實就是排錯試錯的高手. 而第二種則出電腦專才. 這個兩小時(?)的學習, 不能使你深入的掌握dd, 不過可以給你編制dd的框架. 能給你 乙個起始點, 這個教程就算成功了.

directdraw程式設計需要一些背景知識:

directdraw是為在 windows95/nt 下實現高速圖形顯示所寫的程式庫.

高速圖形顯示的基本方法是用一種叫做 page flipping的技術. 關於什麼是 page flipping, 參見古技介紹.如果你 不急的話, 看到下面, 你也會看到.

在 windows95/nt下做 page flipping 分為全屏的和視窗的兩種. 在全屏下page flipping 叫做flip, 在視窗下叫做 blit.

知道了這些背景知識, 我們可以開始寫程式了.

寫所有 directdraw的程式, 差不多都有以下幾個步驟,

1. 初始化, 這是每個程式都需要的勞什子.

2. 設定顯示模式.

3. 在記憶體裡建立pageflipping所需要的兩個頁, 前頁和後頁.

4. 給顯示的區域加個畫框以免畫到外面來.

5. 在後頁畫圖, 然後"刷"的一下子換到前頁來.

步驟一: 初始化

directdraw 是乙個物件導向的函式庫. "物件導向"的意思並不是指面對著你的女朋友, "物件" 在這裡, 你可以簡單地想象成是乙個模板, 比方說,"**", 一旦你說:"我成立了乙個**". 別人 就會立即把你套入"**模板", 自然而然地認為你有印鈔票的功能. 在我們的程式裡, 你一旦宣告 乙個變數(比如 mydd)是 directdraw物件 (directdraw物件的正式名為 lpdirectdraw) , 這個mydd就有了 directdraw物件的所有的功能和特性. 定義 的語法是:

lpdirectdraw pmydd;

除了 dd的物件外, 還有幾個重要的物件, "頁面", "裁剪板" 和 "調色盤". "頁物件"用來定義"前頁"和"後頁". 定義如下:

lpdirectdrawsu***ce pmyddsfront;

lpdirectdrawsu***ce pmyddsback;

乙個"裁剪板物件", 在視窗模式下用來剪去畫出視窗邊界的部份.

lpdirectdrawclipper pmyclipper;

"調色盤"設定螢幕的顏色表, 在讀取256色的 bitmap時要用到.

lpdirectdrawpalette myddpal;

最最重要的"物件"就是這些了. 當然 directx還有很多複雜晦澀的物件. 這是速成不起來的.

編制 windows 程式有一大堆變數和物件是 windows所要求的, 這也是我最煩 microsoft的地方. microsoft 似乎知道這點. 所以在 vc4.0後的版本有了 wizard的功能幫你自動生成**. 盡量地去用它的 wizard使我們的生活變得容易.

由於我們的程式可能會占用乙個視窗, 就給這個視窗乙個 handle:

hwnd mywnd

初始化的工作還沒有完, 我們要把這些物件指向乙個安全的地方 null.

pmydd = null;

pmyddsfront = null;

pmyddsback = null;

pmyclipper = null;

pmyddpal=null;

最後, 在 windows系統為我們的 mydd物件開闢相應的區域:

directdrawcreate( null, //用當前的顯示驅動

&pmydd, null))

okay, 煩人的初始化總算完了.

步驟二: 設定螢幕的顯示方式.

directdraw 有自己的設定螢幕的方式, 而且它的螢幕模式分為"全屏"( exclusive mode)和"視窗"( normal mode). 各有各的設定方法. 設定的主要區別在於 setcooperativeleve的引數.

setcooperativeleve 在"視窗"模式下這樣設定:

pmydd->setcooperativelevel(afxgetmainwnd()->getsafehwnd(),ddscl_normal);

而在"全屏"模式下這樣設定:

pmydd->setcooperativelevel( hwnd, ddscl_exclusive | ddscl_fullscreen );

如果它們的返回值為 dd_ok表示成功. 我們就可以把螢幕調節成我們想要的樣子, 例如 640x480x8. 也就是256色. 究竟有那些螢幕模式可用取決於你的顯示卡

pmydd->setdisplaymode( 640, 480, 8 );

現在, 我們已經有了乙個螢幕, 不過還不能在上面畫畫, 我們需要步驟三來 替我們建立乙個可供畫畫塗塗用的畫板.

步驟三: 建立前後頁(兩塊畫板).

兩塊畫板的好處是可以一邊在一塊上面畫, 一邊給別人看已經畫好的另一塊. 等這塊畫好了, 兩塊板就對調一下, 讓別人看新畫好的這塊. 如果畫的足夠快, 換的足夠快. 看的人就會看到動畫了, 就象電影的效果一樣. 我們把這叫做 page flipping.

這裡先要介紹的是怎樣在系統中建立兩塊畫板( double buffering), 不過你也可以根據需要建立三塊,四塊畫板.

ddsu***cedesc ddsd; //這個結構描述"頁"的特徵.

ddsd.dwflags = ddsd_caps;

ddsd.ddscaps.dwcaps = ddscaps_primarysu***ce;//指定我們用的是前頁.

ddsd.dwsize = sizeof(ddsd); //尺寸

// 做前頁:

hresult result;

result = pmydd->createsu***ce(&ddsd, &pmyddsfront, null);

當發生錯誤時, 要記得 release物件.

if (result!=dd_ok)

ddsd.dwwidth = scr_width; //設定後頁的大小,

ddsd.dwheight = scr_height;

//指定 我們要後頁

ddsd.dwflags = ddsd_width | ddsd_height | ddsd_caps;

ddsd.ddscaps.dwcaps = ddscaps_offscreenplain;

//做後頁

result = pmydd->createsu***ce(&ddsd, &pmyddsback, null);

} 步驟四: 給顯示區加乙個畫框(裁剪板).

在視窗下. 為了防止 directdraw 畫到視窗外面去. 需要加乙個畫框(裁剪板). 可以用 createclipper來 建立剪貼簿.

result = pmydd->createclipper(0, &pmyclipper, null);

建立後,把它套到視窗上去, 所以要知道是那乙個視窗( handle).

mywnd = afxgetmainwnd()->getsafehwnd();// 從系統中拿到視窗的 handle

result = pmyclipper->sethwnd(0, mywnd);

// 把剪貼簿加到視窗上去

result = pmyddsfront->setclipper(myclipper);

步驟五: 在後頁畫圖, 前後頁互換.

其實到這裡才是真正開始寫遊戲的地方, 以前在 dos下寫遊戲, 就是直接從 這個步驟開始的. 以上這些工作, 都是 microsoft強加給我們的.

寫遊戲之前我們先來解決前後互換的問題.

// 如果前頁的記憶體被 windows"徵用"了, 這裡把它要回來. 這個檢察常常會被忘記.

if (pmyddsfront->islost() == dderr_su***celost)

pmyddsfront->restore();

directdraw 用來互換的語句有 blt和 bltfast. bltfast據稱比 blt快10%.

result = pmyddsfront->blt(&rcto, pmyddsback, &rcfrom, ddblt_wait,null);

result = pmyddsfront->bltfast( 0, 0, pmyddsback, &rcfrom, ddbltfast_srccolorkey);

如果程式工作在"全屏"模式下. 前後頁互換容易得多, 只是一句:

result = pmyddsfront->flip( null, 0 );

現在就到了遊戲的主要部份了, 我們稱之為"遊戲邏輯"部, 在普通的遊戲中, "遊戲邏輯" 通常 要做很多事, 如畫遊戲場景, 故事處理等等. 做完這些事後, 再和前頁做換屏. 不過怎樣做你的 遊戲, 就沒有我什麼事了:-)

進入 ide環境後, 加入乙個新 cpp file, 把上面用到的子函式的**打入.

當然你還需要乙個 .h file 來放變數名, 物件名和子程式名.

mfc(microsoft fried checken)的 wizard會幫你生成 ::initinstance() 和 ::onidle(long lcount), 把你的 初始化部份, 建頁等步驟放在 initinstance子類裡. 把"遊戲邏輯"和換頁放在 onidle裡. 

昨天 github 掛了兩個小時

首先說下 www.githubstatus.com 可以實時的檢視到 github 服務的可用性狀態 文中關於可用性的截圖都來自這裡。下圖就是今天 2020年06月30 能看到的服務狀態,可以看到昨天 github 的除了 git pages 服務,其他服務都出現了事故 incidence 其中 g...

下午去華為面了兩個小時

下午去華為面了兩個小時 title 周五下午,收到華為的 叫週日下午2點去面試。這些天真是累夠戧,今天還跑來單位加班。吃完午飯,一看時間1點過了就出發到了港灣的辦公樓。華為把港灣搞垮了之後,港灣的房子也是它的了。到點的時間是1 45,因為搞不太清楚從哪個門進去,並且週末前台也沒人,於是給一位 姓王的...

兩個小時成為ISA2004專家

來自isa中文站的風間子 全文14章,共計114頁,目錄如下 一 isa 2004 王者歸來 1 新功能概述 2 全新的多網路架構支援 3 增強的虛擬專用網路 vpn 4 更方便的管理 1 全新的管理介面 2 策略模板支援 3 配置的匯出和匯入 4 其他管理增強 5 全面的協議支援 6 讓網路更安全...