VB中使用DirectX库的简明教程(2)

首先在上面的程序中加入一个函数SetNewdisplayMode,函数代码如下:

Private Function SetNewdisplayMode()

On Error GoTo ErrHandler

Dim ddsd As DDSURFACEDESC2
Dim i As Long

i = List1.ListIndex
If i = -1 Then
MsgBox "请在列表中选择一种显示模式",vbOKOnly,"错误"
Exit Function
End If

objEnumModes.GetItem (i + 1),ddsd

''设置协作模式
objDraw.SetCooperativeLevel Me.hWnd,DDSCL_FULLSCREEN Or _
DDSCL_ALLOWMODEX Or DDSCL_EXCLUSIVE

''设置显示模式
objDraw.SetdisplayMode ddsd.lWidth,ddsd.lHeight,_
ddsd.ddpfPixelFormat.lRGBBitCount,_
0,DDSDM_DEFAULT

Me.Refresh

ErrHandler:
Select Case Err.Number
Case 0 ''No Errors
Case Else
Err.Raise Err.Number,Err.source,Err.Description,Err.HelpContext,_
Err.HelpContext
Call Cleanup
End Select
End Function
在Command2的Click事件中加入以下代码
Dim i

For i = 0 To Form1.Controls.Count - 1
Form1.Controls(i).Visible = False
Next i

SetNewdisplayMode

  再次运行程序,点击列表中的任意一个显示模式,然后点击"设置显示模式"按钮,可以看到屏幕的显示模式被设置成了你在列表中选择的模式。

  上面介绍的是如何设置显示模式,下面介绍如何利用DirectSurface对象来进行图形绘制以及如何利用前台绘图平面同后台绘图平面相配合工作。这个程序要实现的目的是:在屏幕上显示一幅背景位图,然后有一个角色在屏幕上移动。为了实现上面的目的,我们需要建立四个绘图平面,一个主平面,就是程序运行时可以看到的平面;一个后台缓冲平面,用于进行图像操作;一个位图平面,用于显示背景位图;一个角色位图平面,用于显示角色位图。在程序运行时首先将背景位图贴到后台缓冲平面,然后将角色位图平面贴到后台缓冲平面,在后台缓冲平面输出一些提示文字,最后将后台缓冲平面的内容贴到主平面上。
 为完成下面的 程序,首先要在你的工程文件的目录下建立一个名字为Demo.bmp的位图文件最为背景和一个名字为 Sprite.bmp 的位图作为角色位图。在Form1中加入一个ListBox控件和两个CommandButton控件。加入Directx7说明库,然后在Form1的代码窗口中添加以下的代码

Option Explicit

Dim objDx As New DirectX7
Dim objDraw As DirectDraw7
Dim objEnumModes As DirectDrawEnumModes

Dim MainSurf As DirectDrawSurface7
Dim BackSurf As DirectDrawSurface7
Dim BmpSurf As DirectDrawSurface7
Dim SpriteSurf As DirectDrawSurface7

Dim ddsd As DDSURFACEDESC2
Dim ddsd1 As DDSURFACEDESC2
Dim ddsd2 As DDSURFACEDESC2
Dim ddsd3 As DDSURFACEDESC2
Dim ddsd4 As DDSURFACEDESC2
Dim ddsd5 As DDSURFACEDESC2

Dim bRun As Boolean
Dim lastTime As Long
Dim fps As Long
Dim lfps As Long
Dim FrameCount As Long
Dim Clipper As DirectDrawClipper
Dim x As DDPIXELFORMAT
Dim sx,sy As Integer
Dim Pict() As Byte

Sub InitSurf()
On Error GoTo ErrHandler

'设置主绘图平面的属性
ddsd1.lFlags = DDSD_CAPS Or DDSD_BACKBUFFERCOUNT
ddsd1.lBackBufferCount = 1
ddsd1.ddsCaps.lCaps = DDSCAPS_COMPLEX Or DDSCAPS_FLIP Or DDSCAPS_PRIMARYSURFACE
'设置缓冲绘图平面的属性
ddsd2.ddsCaps.lCaps = DDSCAPS_BACKBUFFER

'根据ddsd1建立主绘图平面
Set MainSurf = objDraw.CreateSurface(ddsd1)
'将BackSurf设置为MainSurf的附加平面
Set BackSurf = MainSurf.GetAttachedSurface(ddsd2.ddsCaps)
'设置背景绘图平面的字体和颜色
BackSurf.SetForeColor RGB(255,255,255)
Form1.Font.Name = "宋体"
BackSurf.SetFont Form1.Font

'获得缓冲绘图平面的属性并设置到ddsd4中
BackSurf.GetSurfaceDesc ddsd4
'设置图形绘图平面的属性
ddsd3.lFlags = DDSD_CAPS Or DDSD_HEIGHT Or DDSD_WIDTH
ddsd3.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
ddsd3.lWidth = ddsd4.lWidth
ddsd3.lHeight = ddsd4.lHeight
'建立图形绘图平面
Set BmpSurf = objDraw.CreateSurfaceFromFile(App.Path + "/demo.bmp",ddsd3)

'设定角色位图平面的属性
ddsd5.lFlags = DDSD_CAPS
ddsd5.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
'建立角色位图平面
Set SpriteSurf = objDraw.CreateSurfaceFromFile(App.Path + "/sprite.bmp",ddsd5)

Dim key As DDCOLORKEY
'设定透明色(在这里设定为0,黑色)
key.low = 0
key.high = 0
SpriteSurf.SetColorKey DDCKEY_SRCBLT,key
sx = 20: sy = 20

lastTime = objDx.TickCount

While True
DoEvents
Blt
Wend
ErrHandler:
Select Case Err.Number
Case 0 ''No Errors
Case Else '错误退出
Call Cleanup
End Select
End Sub
Sub Blt()
Dim mrectScreen As RECT
Dim sTimePass As Single
Dim sFramePerS As Single

'以黑色清除并填充后台绘图平面
BackSurf.BltColorFill mrectScreen,0

'获得背景位图平面的矩形区域的尺寸
mrectScreen.Right = ddsd2.lWidth
mrectScreen.Bottom = ddsd2.lHeight
'将图形绘图平面中的内容复制到后台绘图平面上
Call BackSurf.BltFast(0,BmpSurf,mrectScreen,DDBLTFAST_WAIT)

'获得前景角色位图平面的矩形区域
mrectScreen.Right = ddsd5.lWidth
mrectScreen.Bottom = ddsd5.lHeight
'将前景角色位图复制到后台绘图平面上。
Call BackSurf.BltFast(sx,sy,SpriteSurf,DDBLTFAST_SRCCOLORKEY)
sx = sx + 2: sy = sy + 2
If sx > 400 Then sx = 20
If sy > 400 Then sy = 20

'在后台绘图平面上输出文本
BackSurf.DrawText 30,30,"This is my first DirectX program",False
BackSurf.DrawText 30,60,"点击屏幕退出程序",False

'获得每秒的播放帧数。
FrameCount = FrameCount + 1
sTimePass = (objDx.TickCount - lastTime) / 1000
If sTimePass > 0.5 Then
sFramePerS = FrameCount / sTimePass
End If
BackSurf.DrawText 30,90,"每秒帧数:" + Format$(sFramePerS,"##00.0"),False

'将后台绘图平面上的内容翻转到前台
MainSurf.Flip nothing,DDFLIP_WAIT
End Sub
Private Function SetNewdisplayMode()
On Error GoTo ErrHandler

Dim i As Long

i = List1.ListIndex
If i = -1 Then
MsgBox "请在列表中选择一种显示模式","错误"
Exit Function
End If

'获得用户选择的显示模式
objEnumModes.GetItem (i + 1),DDSCL_FULLSCREEN Or DDSCL_ALLOWMODEX _
Or DDSCL_EXCLUSIVE

''设置显示模式
objDraw.SetdisplayMode ddsd.lWidth,ddsd.ddpfPixelFormat.lRGBBitCount,DDSDM_DEFAULT

Me.Refresh
ErrHandler:
Select Case Err.Number
Case 0 ''No Errors
Case Else
Err.Raise Err.Number,_
Err.HelpContext
Call Cleanup
End Select
End Function

Sub Cleanup() 'Cleanup函数回复屏幕并且清除DirectX对象
Call objDraw.RestoredisplayMode
Call objDraw.SetCooperativeLevel(Me.hWnd,DDSCL_norMAL)
Set objDraw = nothing
Set objDx = nothing
End
End Sub

Private Sub Command1_Click()
End
End Sub

Private Sub Command2_Click()
Dim i

For i = 0 To Form1.Controls.Count - 1
Form1.Controls(i).Visible = False
Next i

SetNewdisplayMode
InitSurf
End Sub

Private Sub Form_Click()
Cleanup
End Sub

Private Sub Form_Load()
Command1.Caption = "结束"
Command2.Caption = "设置显示模式"

On Error GoTo ErrHandler:

Dim ddsd As DDSURFACEDESC2
Dim i As Long,lgCount As Long

Set objDx = New DirectX7
'建立 DirectDraw 对象
Set objDraw = objDx.DirectDrawCreate("")

'将DirectDraw对象支持显示模式设置到DirectDrawEnumModes对象中
Set objEnumModes = objDraw.GetdisplayModesEnum(DDEDM_DEFAULT,ddsd)

'将数据设置到ListBox
lgCount = objEnumModes.GetCount()
For i = 1 To lgCount
objEnumModes.GetItem i,ddsd
List1.AddItem CStr(ddsd.lWidth) & "x" & CStr(ddsd.lHeight) & "x" _
& CStr(ddsd.ddpfPixelFormat.lRGBBitCount)
Next i

ErrHandler:

Select Case Err.Number
Case 0 ''没有错误
Case Else
Err.Raise Err.Number,_
Err.HelpContext
Call Cleanup
End Select
End Sub

   现在程序全部完成了,运行程序,点击列表中的任意显示模式,然后点击"设置显示模式"按钮,可以看到位图被显示在屏幕上并且在屏幕上显示出程序中的文本。

  上面的程序比较简单,但是包含了基本的DirectDraw的应用,下面来分析一下:

  首先通过DirectX7的DirectDrawCreate方法建立一个DirectDraw对象,然后通过GetdisplayModesEnum方法获得DirectDraw对象支持显示模式,当选择某一种显示模式之后,调用DirectDraw对象的SetdisplayMode方法设置所选择的显示模式。

  接下来是设置绘图平面,如果对于 游戏编程有一些了解的朋友都会知道,为了不使在游戏的图像切换时发生闪烁,我们一般需要设置一个后台绘图平面,对所有的画面首先在后台缓冲平面上做所需要的处理,然后再将它翻转到前台来。从上面的程序可以看到,在程序中一共设置了三个不同的绘图平面:MainSurf、BackSurf、BmpSurf、SpriteSurf。MainSurf是主绘图平面,是程序运行时可以看到的部分;而BackSurf是后台绘图平面;BmpSurf是背景位图平面;SpriteSurf是角色位图平面。我们使用MainSurf的GetAttachedSurface方法将BackSurf设置为MainSurf的附加平面,所有的图形操作首先在在BackSurf上进行,然后在翻转到主平面上来。BmpSurf在程序中利用DirectDraw的CreateSurfaceFromFile函数被设置为一个包含位图的绘图平面。SpriteSurf也做同样的设定,但是为了使只有角色显示出来而无关的部分不显示,我们需要设置SpriteSurf的ColorKey,在上面设置为0黑色,即在粘贴图像时Sprite.bmp 中的黑色部分不会显示出来。然后建立一个无限循环,在每个循环内首先将BmpSurf上的位图转贴到BackSurf上,然后在BackSurf上输出文字,等在BackSurf上的操作全部完成之后,再利用MainSurf的Flip方法后台绘图平面的内容翻转到前台平面上来。读者需要注意的是这四个绘图平面的不同属性(从ddsd1到ddsd5)。

相关文章

Format[$] ( expr [ , fmt ] ) format 返回变体型 format$ 强...
VB6或者ASP 格式化时间为 MM/dd/yyyy 格式,竟然没有好的办...
在项目中添加如下代码:新建窗口来显示异常信息。 Namespace...
转了这一篇文章,原来一直想用C#做k3的插件开发,vb没有C#用...
Sub 分列() ‘以空格为分隔符,连续空格只算1个。对所选...
  窗体代码 1 Private Sub Text1_OLEDragDrop(Data As Dat...