本文來源于網頁設計愛好者web開發社區http://www.html.org.cn收集整理,歡迎訪問。關鍵字: vb.net directx directdraw 9 作者:董含君
轉載請注明來自 http://blog.csdn.net/a11s
===========日記================
發現最近比較懶惰,代碼稍微長那么一點,就不想看了.還是看書比較好.
考慮做游戲,但是目前所學的知識還不夠.革命尚未成功,同志們仍需努力啊
===========end 日記=============
今天是完成全屏幕動畫,1024x768,外加多層繪制(鼠標位置就不值得一提了)
先回想一下我們平時是怎樣畫圖的.(應該是做圖)
1 準備一張紙,這個要給別人看的 (primarysurface)
2 一支筆 (draw方法)
然后自由發揮就可以了 (找坐標,畫..)
這樣是可以的,你的觀眾(坐在顯示器前面的人)不但能看見你的繪制的作品,而且連你如何繪制的都能看見(也許你正在用描點法畫圖...). 很明顯,我們不希望觀眾看見我們繪圖時的“優雅姿態“.我們要的是速度以及效果,這么慢就不叫directdraw了
方案2
1 準備一張紙,這個是給觀眾欣賞的(primarysurface)
2 再準備一個成型的作品,比如達芬奇畫過的雞蛋 (surface)
3 畫筆,尖刀,膠水
大概你知道我要做什么了吧,用粘貼的辦法自然要快于描點.但是,觀眾們依然可以知道你是粘貼上去的!當演示一幅一幅的動畫的時候,往往會粘貼的到處都是.....
方案3
1 找個工作臺,請觀眾坐下慢慢看當前的圖像(primarysurface)
2 自己再另外找一張或者更多的畫板 (backsurface)
3 各種工具,只要能方便使用就好 (drawfast drawrect drawtext drawcircle .....)
4 請一位助手幫忙更換工作臺的作品.(primarysurface.flip)
這樣您可以解放出來,再也不用擔心您的觀眾看到您繪制的過程了.雖然他們可以“猜測“您是如何繪制的.我們這樣做,在backsurface上面用任意的快速方法做圖,當然可以從其他surface上面復制,然后粘貼到backsurface,提交給primarysurface,讓他flip,用戶看到的就是您繪制完之后的結果(primarysurface),當觀眾對您的作品贊不絕口的時候,您正在剛才flip之后的畫板上修改,然后把修改之后的這個畫板再flip...
這樣,兩張畫板解決了問題.同時只有1個是觀眾正在看的,另外1個是您手頭上正在畫的,您的助手(primarysurface)很聰明,不會搞錯,所以你只要安心畫當前的畫板(backbuffer)就夠了
強調一下,您繪制的總是backbuffer,flip方法會把您的backbuffer呈現到primarybuffer,然后繪制,呈現,繪制,呈現...
或者您理解為復制到primarysurface也可(實際上是內存的塊移動)
大體步驟跟前文說得一致,僅僅是多生命了幾個surface用于復制,源代碼不過才200行,主要代碼也就不到100行,里面有比較詳細的注釋.所以再這里就沒有必要解釋了
==================================================
imports microsoft.directx.directdraw
public class form1
inherits system.windows.forms.form
private structure pointapi
public x as integer
public y as integer
end structure
'''api用習慣了....也就繼續用吧...
private declare function getcursorpos lib "user32" (byref lppoint as pointapi) as integer
dim dev as new device(createflags.default)
dim ps as surface 'primarysurface
dim bs as surface 'backsurface
dim s1 as surface 'surface1 用于儲存圖像的,想象成一個bmp就行了
dim s2 as surface 'surface2 同上
'''分別對應上面的四個surface
dim desc1 as surfacedescription
dim desc2 as surfacedescription
dim desc3 as surfacedescription
dim desc4 as surfacedescription
''分別對應上面的surface
dim rp as rectangle
dim rb as rectangle
dim r1 as rectangle
dim r2 as rectangle
'''計時器相關
dim tlast as timespan
dim fps as string
dim tfp as integer = 0
dim mytime as date = datetime.now
dim ts as new timespan
dim qiqi as double
'''游戲控制
dim running as boolean = false
dim tt as threading.thread
'''鼠標位置
dim m as pointapi
'''需要讀取的圖像
const fn1 = "d:/nerv.bmp"
const fn2 = "d:/logo.bmp"
#region " windows 窗體設計器生成的代碼 "
public sub new()
mybase.new()
'該調用是 windows 窗體設計器所必需的。
initializecomponent()
'在 initializecomponent() 調用之后添加任何初始化
end sub
'窗體重寫 dispose 以清理組件列表。
protected overloads overrides sub dispose(byval disposing as boolean)
if disposing then
if not (components is nothing) then
components.dispose()
end if
end if
mybase.dispose(disposing)
end sub
'windows 窗體設計器所必需的
private components as system.componentmodel.icontainer
'注意: 以下過程是 windows 窗體設計器所必需的
'可以使用 windows 窗體設計器修改此過程。
'不要使用代碼編輯器修改它。
friend withevents label1 as system.windows.forms.label
<system.diagnostics.debuggerstepthrough()> private sub initializecomponent()
me.label1 = new system.windows.forms.label
me.suspendlayout()
'
'label1
'
me.label1.location = new system.drawing.point(64, 64)
me.label1.name = "label1"
me.label1.size = new system.drawing.size(80, 24)
me.label1.tabindex = 0
me.label1.text = "init&&play"
'
'form1
'
me.autoscalebasesize = new system.drawing.size(6, 14)
me.clientsize = new system.drawing.size(292, 273)
me.controls.add(me.label1)
me.name = "form1"
me.text = "form1"
me.resumelayout(false)
end sub
#end region
private sub label1_click(byval sender as system.object, byval e as system.eventargs) handles label1.click
initddraw() '初始化
loadsurfaces() '讀取圖像
if tt is nothing then '用于繪制的線程
tt = new threading.thread(addressof mainloop)
running = true
tt.start()
end if
end sub
sub initddraw()
dev.setcooperativelevel(me, cooperativelevelflags.fullscreenexclusiveallowmodex)
dev.setdisplaymode(1024, 768, 16, 0, false)
'primarybuffer的設置
desc1 = new surfacedescription
desc1.surfacecaps.videomemory = true
desc1.surfacecaps.primarysurface = true
desc1.surfacecaps.flip = true
desc1.surfacecaps.complex = true
desc1.backbuffercount = 1
ps = new surface(desc1, dev)
desc2 = new surfacedescription
desc2.surfacecaps.backbuffer = true
bs = ps.getattachedsurface(desc2.surfacecaps)
bs.forecolor = system.drawing.color.blue
bs.fonttransparency = true
''ok只要把primarybuffer跟backbuffer設置好就算初始化完成,其他的圖像都往上貼
end sub
sub loadsurfaces()
'''讀取其他圖層
''' 不要把surface想得那么神秘,就是一個bmp附加上了更多的屬性而已,這樣理解簡單很多
desc3 = new surfacedescription
desc3.surfacecaps.offscreenplain = true '幕后的
desc3.height = bs.surfacedescription.height '大小
desc3.width = bs.surfacedescription.width
s1 = new surface(fn1, desc3, dev) '讀取
desc4 = new surfacedescription
desc4.surfacecaps.offscreenplain = true '直接讀
s2 = new surface(fn2, desc4, dev)
dim key as colorkey '用來設置透明的
key.colorspacehighvalue = 0
key.colorspacelowvalue = 0
s2.setcolorkey(colorkeyflags.sourcedraw, key) '設置透明色
'''''設置矩形位置信息
'''
rb.width = bs.surfacedescription.width
rb.height = bs.surfacedescription.height
r1.width = s1.surfacedescription.width
r1.height = s1.surfacedescription.height
r2.width = s2.surfacedescription.width
r2.height = s2.surfacedescription.height
r2.x = 100
r2.y = 100
end sub
sub mainloop()
while (running = true) '''如果游戲沒有結束
blt() '''主要繪制過程
tfp += 1 '''fps++
if tfp = 200 then '''200次的時候計算時間
tfp = 0
ts = (datetime.now.subtract(mytime))
mytime = datetime.now
if ts.totalseconds <> 0 then
qiqi = 200 / (ts.totalseconds)
fps = qiqi.tostring("##.##") + "f c"
end if
end if
tt.sleep(10) '''硬性規定休息一下,當然可以去掉發揮max速度
end while
end sub
sub blt()
if bs is nothing then exit sub
getmousepos() '得到鼠標位置
'''下面的就是利用backsurface的方法來繪制了,隨便畫,呵呵
bs.drawfast(0, 0, s1, r1, drawfastflags.wait)
bs.drawtext(10, 10, "1024x768 frames per second " + fps, false)
bs.drawtext(10, 30, "當前位置:x=" + m.x.tostring + ",y=" + m.y.tostring, false)
bs.drawtext(10, 50, "esc 退出", false)
'''畫出貼圖
bs.drawfast(m.x, m.y, s2, drawfastflags.sourcecolorkey or drawfastflags.wait)
'''順便在鼠標的位置打出它的坐標
bs.drawtext(m.x + 50, m.y, "(" + m.x.tostring + "," + m.y.tostring + ")", false)
'''關鍵一步,翻轉,而且不要使用wait,這樣可能會丟幀,但是不影響速度
ps.flip(nothing, flipflags.novsync)
end sub
private sub form1_keyup(byval sender as object, byval e as system.windows.forms.keyeventargs) handles mybase.keyup
if e.keycode = keys.escape then end 'esc退出
end sub
sub getmousepos()
getcursorpos(m) '調用api,得到鼠標位置
end sub
end class
=====================================
很多代碼跟前面說得一樣,大體思路也是跟我舉的例子(方案3)一致
通過代碼.可以了解具體步驟
directdraw再往下就是圖像的透明度計算(這個有公式的),大小變換,旋轉.具體請參考現成的代碼以及公式,我計算機圖形學沒有學過,估計是很困難.而且ddraw還有很多內置的方法可以提供簡單的轉換方式,這個估計需要查閱英文原版的directdraw7才能找到相應的方法了...
ok directdraw到此結束,如果可能,還會寫一個應用directdraw的demo,但是估計就不會這樣具體說明了,呵呵.
終于可以安心研究那個混音了