分享
 
 
 

VB.NET实现DirectDraw9 (2) 动画

王朝vb·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

关键字: 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,但是估计就不会这样具体说明了,呵呵.

终于可以安心研究那个混音了

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有