| ltFast(sx, sy, SpriteSurf, mrectScreen, 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 "请在列表中选择一种显示模式", 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
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.Source, Err.Description, Err.HelpContext, _
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)。
二、 Direct3D Direct3D类对象可以说是DirectX下最重要的同时也是最复杂的对象集合。基本说来,Direct3D可以分为立即模式( Immediate Mode)和保留模式(Retained Mode)。其中保留模式是一种高级3D API编程接口,它是为需要快速开发Direct 3D应用的程序员所准备的。而立即模式是一种低级3D API编程接口,它为需要开发高性能游戏或者多媒体应用的程序员提供了在较低级别上同图形加速硬件打交道的与设备无关的接口。Direct3D的保留模式是建立在立即模式基础之上的,如下图所示:

由上面的图可以看到。Direct3D的立即模式同图形加速硬件之间的结合比较紧密,性能比较高,适合于开发三维游戏。而Direct3D的保留模式具有层次性,可移植性比较的好,可以用于开发商业的三维应用程序(例如设备展示等)。 要建立一个Direct3D应用,首先要建立Direct3D7对象,利用DirectDraw7对象的GetDirect3D方法可以获得一个Direct3D7对象。利用Direct3D7对象可以建立Direct3D对象以及设置三维环境。 利用Direct3D7对象的CreateDevice方法可以建立一个Direct3DDevive7对象,你可以将一个Direct3DDevice7对象想象为一个电影场景,你可以向场景中布置演员(3D对象)、给每个演员安排服装(纹理设置)、设置灯光(光照效果)、设置摄影机(设置视角)。 下面通过一个具体的程序来说明Direct3D立即模式的基本原理 首先建立一个新的工程并保存,为了给三维对象加上纹理,我们需要在工程目录下建立三个位图文件,文件名分别是t1.bmp、t2.bmp、t3.bmp,位图的尺寸要设置为128*128或者256*256像素,将DirectX7 说明库加入到工程文件中。然后在Form1中加入以下代码: Option Explicit
Const pi As Single = 3.141592
Const NUM_CUBE_VERTICES As Integer = 4 * 6
Dim g_vCube(NUM_CUBE_VERTICES) As D3DVERTEX
''''定义三个材质表面
Dim TextureSurface1 As DirectDrawSurface7
Dim TextureSurface2 As DirectDrawSurface7
Dim TextureSurface3 As DirectDrawSurface7
Dim g_dx As New DirectX7
Dim g_dd As DirectDraw7
Dim g_ddsd As DDSURFACEDESC2
Dim MainBuffer As DirectDrawSurface7
Dim BackBuffer As DirectDrawSurface7
Dim Direct3DDevice As Direct3DDevice7
Dim g_rcDest As RECT, g_rcSrc As RECT
Dim ViewPortRect(0) As D3DRECT
Dim bIsRunning As Boolean
Dim bRoAn As Boolean
Dim CNT As Single
Dim iViewSize As Integer
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
''''根据不同的击键值来决定角度的变化
Select Case KeyCode
Case vbKeyUp
CNT = CNT + 6
bRoAn = True
Case vbKeyDown
CNT = CNT - 6
bRoAn = True
Case vbKeyLeft
CNT = CNT + 6
bRoAn = False
Case vbKeyRight
CNT = CNT - 6
bRoAn = False
Case vbKeySubtract
If iViewSize < 12 Then
iViewSize = iViewSize + 1
End If
Case vbKeyAdd
If iViewSize > 4 Then
iViewSize = iViewSize - 1
End If
End Select
End Sub
Private Sub Form_Load()
Dim j As Long
InitDDraw
InitD3D
InitDeviceObjects
Me.Show
bIsRunning = True
Do While bIsRunning = True
RenderScene
FrameMove (CNT / 360), bRoAn
g_dx.GetWindowRect Me.hWnd, g_rcDest
''''将后台绘图平面的内容复制到前台
j = MainBuffer.Blt(g_rcDest, BackBuffer, g_rcSrc, DDBLT_WAIT)
If j <> DD_OK Then
MsgBox "无法将后台绘图平面的内容拷贝到前台,错误代码:" & Hex(j)
End
End If
DoEvents
Loop
End Sub
Private Sub FrameMove(stepVal As Single, bType As Boolean)
Dim matView As D3DMATRIX
Dim matTemp As D3DMATRIX
''''建立线形矩阵
g_dx.IdentityMatrix matView
'''' matView.rc11 = Cos(0.5)
'''' matView.rc12 = Sin(0.5)
'''' matView.rc21 = Sin(-0.5)
'''' matView.rc22 = Cos(0.5)
'''' matView.rc33 = 1
'''' matView.rc43 = iviewsize
''''你可以尝试将下面5句注释掉而使用上面5句进行视矩阵变换,看有什么效果
matView.rc11 = 1
matView.rc22 = Cos(-0.5)
matView.rc23 = Sin(-0.5)
matView.rc32 = -Sin(-0.5)
matView.rc33 = Cos(-0.5)
matView.rc43 = iViewSize
''''对视矩阵进行角度变换
Direct3DDevice.SetTransform D3DTRANSFORMSTATE_VIEW, matView
Dim matWorld As D3DMATRIX
g_dx.IdentityMatrix matWorld
If bType Then
g_dx.RotateXMatrix matWorld, stepVal
Else
g_dx.RotateYMatrix matWorld, stepVal
End If
Direct3DDevice.SetTransform D3DTRANSFORMSTATE_WORLD, matWorld
End Sub
''''RenderScene函数执行场景重绘和渲染
Private Sub RenderScene()
Dim i As Integer
''''将整个视界背景设置为蓝色,并清除Z缓冲
Direct3DDevice.Clear 1, ViewPortRect(), D3DCLEAR_TARGET, &HFF, 1, 0
''''开始绘制场景
Direct3DDevice.BeginScene
''''将TextureSurface1设置为Direct3DDevice的纹理平面
Direct3DDevice.SetTexture 0, TextureSurface1
''''使用TextureSurface1作为纹理绘制g_vCube(0)到g_vCube(3)顶点之间的平面,
Call Direct3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX, g_vCube(0), _
4, D3DDP_DEFAULT)
''''使用TextureSurface1作为纹理绘制g_vCube(4)到g_vCube(7)顶点之间的平面,
Call Direct3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX, g_vCube(4), _
4, D3DDP_DEFAULT)
''''将TextureSurface2设置为Direct3DDevice的纹理平面
Direct3DDevice.SetTexture 0, TextureSurface2
''''使用TextureSurface2作为纹理绘制g_vCube(8)到g_vCube(11)顶点之间的平面,
Call Direct3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX, g_vCube(8), _
4, D3DDP_DEFAULT)
''''使用TextureSurface2作为纹理绘制g_vCube(12)到g_vCube(15)顶点之间的平面,
Call Direct3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX, g_vCube(12), _
4, D3DDP_DEFAULT)
''''将TextureSurface3设置为Direct3DDevice的纹理平面
Direct3DDevice.SetTexture 0, TextureSurface3
''''使用TextureSurface3作为纹理绘制g_vCube(16)到g_vCube(19)顶点之间的平面,
Call Direct3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX, g_vCube(16), _
4, D3DDP_DEFAULT)
''''使用TextureSurface3作为纹理绘制g_vCube(20)到g_vCube(23)顶点之间的平面,
Call Direct3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX, g_vCube(20), _
4, D3DDP_DEFAULT)
''''结束绘制场景
Direct3DDevice.EndScene
End Sub
Private Sub Form_Unload(Cancel As Integer)
bIsRunni上一页 [1] [2] [3] [4] [5] [6] 下一页 |