VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)

VB爱好者乐园(VBGood)

 找回密码
 立即注册
搜索
查看: 17413|回复: 23

Dx8 从零开始(学习Dx8的请进)

[复制链接]
 楼主| 发表于 2010-12-4 23:30:04 | 显示全部楼层 |阅读模式
首先要说明的是使用DX8必须引用DirectX 8 for Visual Basic Type Library,以下是对DX8使用的初步介绍。

  一、DX设备的创建

  1.DX基本设备的创建

  (1)定义变量

  Public DXForm As Form

  Public D3DPresentParam As D3DPRESENT_PARAMETERS

  Public DX As DirectX8

  Public D3D As Direct3D8

  Public D3DDevice As Direct3DDevice8

  Public D3DX As D3DX8

  (2)定义语句

  参数说明:

  Set DX = New DirectX8

  Set D3D = DX.Direct3DCreate

  D3DPresentParam.BackBufferWidth = BackBufferWidth

  D3DPresentParam.BackBufferHeight = BackBufferHeight

  '这两句设置分辨率,BackBufferWidth、BackBufferHeight分别是游戏中使用分辨率的宽度、高度,分辨率的设计必须是机子上有的才可以,否则会报错

  D3DPresentParam.BackBufferFormat = BackBufferFormat

  '这句设置显示模式,属于CONST_D3DFORMAT常数类型,里面可以根据需要定义不同的A、R、G、B的位数,本教程使用D3DFMT_A8R8G8B8。

  D3DPresentParam.SwapEffect = D3DSWAPEFFECT_DISCARD

  '设置换页效果为丢弃后台缓存

  D3DPresentParam.Windowed = 0

  '这句设置是否是窗体,如果为1是窗体,为0是全屏

  Set D3DDevice = D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, DXForm.hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, D3DPresentParam)

  '这句是创建D3DDevice设备,游戏中常常用到,这里的DXForm指的是窗体对象(本文之后用到的窗体对象都叫DXForm)

  Set D3DX = New D3DX8

  2.DX的Sprite对象的创建

  (1)定义变量

  Public Sprite As D3DXSprite

  (2)创建语句

  Set Sprite = D3DX.CreateSprite(D3DDevice)

  3.DX控制设备的创建

  (1)定义变量

  Public DI As DirectInput8

  Public DIDEVKeyboard As DirectInputDevice8

  Public DIKeyboard As DIKEYBOARDSTATE

  Public DIDEVMouse As DirectInputDevice8

  Public DIMouse As DIMOUSESTATE

  (2)创建语句

  Set DI = DX.DirectInputCreate()

  '创建DirectInput8对象

  Set DIDEVKeyboard = DI.CreateDevice("GUID_SysKeyboard")

  '创建键盘对象

  DIDEVKeyboard.SetCommonDataFormat DIFORMAT_KEYBOARD

  设置它的数据格式

  DIDEVKeyboard.SetCooperativeLevel DXhFocusWindow, DISCL_BACKGROUND Or DISCL_NONEXCLUSIVE

  设置它的协作级

  DIDEVKeyboard.Acquire

  '获取设备

  Set DIDEVMouse = DI.CreateDevice("GUID_SysMouse")

  '创建鼠标对象

  DIDEVMouse.SetCommonDataFormat DIFORMAT_MOUSE

  设置它的数据格式

  DIDEVMouse.SetCooperativeLevel DXhFocusWindow, DISCL_BACKGROUND Or DISCL_NONEXCLUSIVE

  设置它的协作级

  If D3DPresentParam.Windowed <> 1 Then

  DIDEVMouse.Acquire

  End If

  '这里需要判断是否为窗口模式,因为如果是窗口模式获取设备会出错

  二、DX的使用

  1.主循环

  Do

  If D3DDevice.TestCooperativeLevel = 0 Then '检测是否可以渲染

  DIDEVKeyboard.GetDeviceStateKeyboard DIKeyboard '更新键盘信息

  If DIKeyboard.Key(DIK_ESCAPE) Then End '如果按下ESC键,则程序退出(这里只是举例怎么判断键盘按下哪个键,DIK_ESCAPE属于CONST_DIKEYFLAGS常数类型,其它的按键都有相应的常数,判断某个键按下只要写入相应的参数就行)

  DIDEVMouse.GetDeviceStateMouse DIMouse'更新鼠标信息

  If DIMouse.Buttons(0) Then End'如果按下鼠标左键,则程序退出(这里只是举例怎么判断鼠标按下哪个键,上面的0代标左键,1是代表右键)

  '这里可以写游戏数据的改变的代码

  D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET, 0, 0, 0 '清屏

  D3DDevice.BeginScene'开始场景

  '渲染代码(后面会提到)

  D3DDevice.EndScene'结束场景

  D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0'显示场景

  Else

  If DXForm.WindowState <> 1 Then‘检测窗体是否是最小化,如果不是,才可以进行设备重置

  '文字设备摧毁(后面会有介绍)

  '用来渲染纹理设备摧毁(后面会有介绍)

  Set Sprite = Nothing'DX图形设备摧毁

  D3DDevice.Reset D3DPresentParam 'DX重置

  Set Sprite = D3DX.CreateSprite(D3DDevice)'DX图形设备重建

  '文字设备重建(后面会有介绍)

  '纹理设备重建(后面会有介绍)

  End If

  End If

  DoEvents

  Loop

  2.纹理

  (1)定义变量

  Public tex As Direct3DTexture8'纹理对象

  Public TexDesc(1) As D3DXIMAGE_INFO'用来储存纹理大小信息(只有当从文件里读数据才需要,创建空的纹理时不需要)

  (2)创建对象

  方法一:通过文件名载入图片来创建纹理

  Set tex = D3DX.CreateTextureFromFileEx(D3DDevice, FileName, width, height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE, Transcolor, TexDesc(0), ByVal 0)

  方法二:创建空的纹理对象

  Set tex = D3DX.CreateTexture(D3DDevice, width, height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED)

  '其中FileName指文件名,width, height分别指纹理的高度和宽度,如果都设为-1则由DX本身决定其大小,D3DFMT_A8R8G8B8指的就是图片显示模式,Transcolor指透明色(DX的透明色有专门的一组函数来输入颜色,本文中使用的是D3DFMT_A8R8G8B8模式,因此使用D3DcolorARGB函数,如果用紫色表示透明色,则用D3DcolorARGB(255,255,0,255),这四个参数的含义分别是透明度、红、绿、蓝),TexDesc数组是用来读取纹理大小信息,读取以后TexDesc(0).height、TexDesc(0).width分别表示纹理高度、宽度

  (3)访问纹里的内存(这里仅说明在D3DFMT_A8R8G8B8模式下的操作方法)

  Dim pData As D3DLOCKED_RECT'用来存储纹理中数据

  Dim pxArr() As Byte'这个数组用来存储纹理中各点的颜色数据

  Tex.LockRect 0, pData, ByVal 0, 0'在内存访问之前必须锁定纹理

  ReDim pxArr(pData.Pitch * height) As Byte'height'代表纹理高度

  DXCopyMemory pxArr(0), ByVal pData.pBits, pData.Pitch * height'将纹理中数据拷贝到pxArr数组

  pos = posy * pData.Pitch + posx * 4'posx,posy代表纹理上某一点的坐标

  '此时pxArr(pos + 3)、pxArr(pos + 2)、pxArr(pos + 1)、pxArr(pos)分别代表A、R、G、B值,获取这些点的值方法很简单,比如a=pxArr(pos + 3)就获取了该点的R值

  pxArr(pos + 3) =100

  pxArr(pos + 2) = 100

  pxArr(pos + 1) = 100

  pxArr(pos) = 100

  '以上就修改了pos点的ARGB值,但要想修改生效还需下面那句的拷贝

  DXCopyMemory ByVal pData.pBits, pxArr(0), pData.Pitch * height

  Tex.UnlockRect 0'在内存访问之后解锁纹理

  3.表面

  (1)定义变量

  Public Sur As Direct3DSurface8

  (2)获取纹理的表面

  Set Sur = Tex.GetSurfaceLevel(0)

  (3)拷贝贴图

  拷贝一张贴图一部分到目标贴图一个位置的方法:

  Dim SouSur As Direct3DSurface8

  Dim DesSur As Direct3DSurface8

  Set SouSur = soutex.GetSurfaceLevel(0)'soutex代表源纹理

  Set DesSur = destex.GetSurfaceLevel(0)'destex代表目标纹理

  Dim tRect As RECT'表示源纹理截取的部分(left、right、top、bottom分别代表要截取部分的左右上下的坐标

  tRect.left = 10

  tRect.Right = 20

  tRect.top = 10

  tRect.bottom = 20

  Dim tDest As Point'表示要拷贝到的目标纹理的坐标

  tDest.x = desx

  tDest.y = desy

  D3DDevice.CopyRects SouSur, tRect, 1, DesSur, tDest

  'SouSur代表源纹理表面,tRect代表源纹理截取位置,1代表只拷贝一张图(如果要拷贝2张图就写2)tDest代表目标纹理位置DesSur代表目标纹理表面

  拷贝一张贴图多个部分到目标贴图多个位置的方法:

  dim sou() as rect'一张贴图多个截取部分用数组存放

  dim des() as rect'目标贴图多个位置用数组存放

  Dim SouSur As Direct3DSurface8

  Dim DesSur As Direct3DSurface8

  Set SouSur = soutex.GetSurfaceLevel(0)

  Set DesSur = destex.GetSurfaceLevel(0)

  D3DDevice.CopyRects SouSur, sou(LBound(sou)), UBound(sou) - LBound(sou) + 1, DesSur, des(LBound(des))

  4.Sprite对象的使用

  (1)定义变量

  public Rect1 As RECT

  public Tran As D3DVECTOR2'D3DVECTOR2结构有x,y两个属性

  public Scal As D3DVECTOR2

  public Center As D3DVECTOR2

  (2)贴图

  Sprite.Begin'开启Sprite对象

  Sprite.Draw tex, Rect1, Scal, Center, Rotation, Tran, color

  'tex代表纹理对象,rect1代表从纹理截取的部分,scal代表放大倍数(x代表横向放大倍数,y代表纵向放大倍数),Center代表旋转点的坐标,Rotation代表旋转的角度,旋转时是以Center为中心点旋转Rotation角度,Tran代表在目标位置贴图的坐标,color表示渲染时显示图片的程度(比如d3dcolorargb(128,255,255,255)就表示A值只显示纹理本身A值的一半,又如d3dcolorargb(255,0,0,255)就表示只显示该图的B值分量,R,G的分量不显示,所以这时显示出来的图片就是蓝色的效果)

  Sprite.End'关闭Sprite对象

  '要说明的是在Sprite.Begin和Sprite.End可以写若干句Sprite.Draw,由于游戏里面主要是图片,所以Sprite.Begin和Sprite.End经常也写到主循环里面,但是在Sprite.Begin和Sprite.End之间是不能够画点线面的,所以本文不把它作为主循环的一部分

  5.在纹理中渲染

  DX中有种用来渲染的纹理,它可以把文字等等内容都渲染到纹理上,以实现显示文字的一部分等等效果

  (1)定义变量

  Public rendertex As Direct3DTexture8'纹理对象

  (2)创建对象

  Set rendertex = D3DX.CreateTexture(D3DDevice, width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT)'注意D3DUSAGE_RENDERTARGET这个参数,它说明的是这个纹理用来渲染

  (3)在纹理中渲染

  主循环中默认是对屏幕渲染,当前渲染的对象D3DDevice.GetRenderTarget(是Direct3DSurface8类型的),在改变渲染对象之前要将当前渲染的对象保存以来,以免改变渲染对象之后改变不回来了

  dim oldSur As Direct3DSurface8

  set oldSur=D3DDevice.GetRenderTarget

  dim rendersur As Direct3DSurface8

  set rendersur=rendertex.GetSurfaceLevel(0)

  D3DDevice.EndScene'要先结束对当前对象(屏幕)的渲染

  D3DDevice.SetRenderTarget rendersur, Nothing, ByVal 0'这句是设置渲染对象,以下的代码跟之前所说的主循环是一样的

  D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET, 0, 0, 0

  D3DDevice.BeginScene

  '渲染代码(这里都是对rendertex进行渲染,不会显示在屏幕上)

  D3DDevice.EndScene'结束场景

  D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0'显示场景

  '如果想让rendertex显示在屏幕上,就需要如下的代码

  D3DDevice.SetRenderTarget oldSur, Nothing, ByVal 0

  D3DDevice.BeginScene

  Sprite.Begin

  Sprite.Draw rendertex, Rect1, Scal, Center, Rotation, Tran, color

  Sprite.End

  6.渲染文字

  (1)定义变量

  public Rect1 As RECT

  public IFont As IFont

  public Font As D3DXFont

  (2)创建对象

  Dim tStdFont As New StdFont

  tStdFont.name = FontName'字体名

  tStdFont.Bold = Bold'是否粗体

  tStdFont.Italic = Italic‘是否斜体

  tStdFont.Underline = Underline'是否下划线

  tStdFont.Size = size'字的大小

  Set IFont = mStdFont

  Set Font = D3DX.CreateFont(D3DDevice, IFont.hFont)'这句执行以后,文字对象就建立了

  (3)渲染文字

  D3DX.DrawText Font, color, caption, Rect1, DT_VCENTER

  'Font代表文字对象,color代表文字颜色,caption代表文字内容,rect1代表渲染文字的目标位置,DT_VCENTER代表文字的对齐方式,这里是代表垂直居中显示(DT_VCENTER属于CONST_DTFLAGS常数类型,里面的各个参数用来实现靠左、靠右、居中等等)

  7.画图形

  首先要注意不能在Sprite.Begin和Sprite.End之间画图形,所以如果之前有Sprite.Begin,此时得先Sprite.End。

  (1)定义类型

  Private Type TLVERTEX

  x As Single

  y As Single

  Z As Single

  rhw As Single

  color As Long

  Tu As Single

  Tv As Single

  End Type

  (2)画点

  D3DDevice.SetVertexShader D3DFVF_XYZRHW Or D3DFVF_TEX1 Or D3DFVF_DIFFUSE

  Dim CreateTLVertex2D(0) As TLVERTEX'因为点本身只有一个顶点,所以数组元素只需要一个

  CreateTLVertex2D(0).x = x

  CreateTLVertex2D(0).y = y

  '设置点的坐标

  CreateTLVertex2D(0).rhw = 1

  CreateTLVertex2D(0).color = color

  '设置点的颜色

  D3DDevice.DrawPrimitiveUP D3DPT_POINTLIST, 1, CreateTLVertex2D(0), Len(CreateTLVertex2D(0))

  '画点

  (3)画线

  D3DDevice.SetVertexShader D3DFVF_XYZRHW Or D3DFVF_TEX1 Or D3DFVF_DIFFUSE

  Dim CreateTLVertex2D(1) As TLVERTEX'因为线有两个顶点,所以数组元素需要两个

  CreateTLVertex2D(0).x = x1

  CreateTLVertex2D(0).y = y1

  CreateTLVertex2D(0).rhw = 1

  CreateTLVertex2D(0).color = color

  '设置第一个顶点的坐标、颜色

  CreateTLVertex2D(1).x = x2

  CreateTLVertex2D(1).y = y2

  CreateTLVertex2D(1).rhw = 1

  CreateTLVertex2D(1).color = color

  '设置第二个顶点的坐标、颜色

  D3DDevice.DrawPrimitiveUP D3DPT_LINELIST, 1, CreateTLVertex2D(0), Len(CreateTLVertex2D(0))

  '画线

  (4)画矩形

  D3DDevice.SetVertexShader D3DFVF_XYZRHW Or D3DFVF_TEX1 Or D3DFVF_DIFFUSE

  Dim CreateTLVertex2D(3) As TLVERTEX'因为矩形有四个顶点,所以数组元素需要四个

  CreateTLVertex2D(0).x = x1

  CreateTLVertex2D(0).y = y1

  CreateTLVertex2D(0).rhw = 1

  CreateTLVertex2D(0).color = color

  CreateTLVertex2D(1).x = x2

  CreateTLVertex2D(1).y = y1

  CreateTLVertex2D(1).rhw = 1

  CreateTLVertex2D(1).color = color

  CreateTLVertex2D(2).x = x1

  CreateTLVertex2D(2).y = y2

  CreateTLVertex2D(2).rhw = 1

  CreateTLVertex2D(2).color = fcolor

  CreateTLVertex2D(3).x = x2

  CreateTLVertex2D(3).y = y2

  CreateTLVertex2D(3).rhw = 1

  CreateTLVertex2D(3).color = fcolor

  '以上根据矩形的四点的坐标设置四个顶点

  D3DDevice.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, CreateTLVertex2D(0), Len(CreateTLVertex2D(0))

  '画面

  '这里要说明的是,第二个参数为什么之前写1而这里写2,实际上这个面是由2个三角形构成的,CreateTLVertex2D(0),CreateTLVertex2D(1),CreateTLVertex2D(2)这三个顶点构成了一个三角形,CreateTLVertex2D(1),CreateTLVertex2D(2),CreateTLVertex2D(3)这三个顶点又构成了一个三角形,DX是先把前三个顶点作成一个三角形,再把后三个顶点作成一个三角形,然后形成了矩形的效果,如果把各个顶点的数据修改下,两个三角形就体现了很明显了。这里所说的只是四个顶点的情形,当有五个顶点的时侯,就会有3个三角形,六个的时侯就有4个三角形,以此类推。

  8.设备重置

  在DX中Sprite对象、文字、用来渲染的纹理、表面对象需要重置,设备重置的大体流程在主循环中已经写过,这里只说明文字和用来渲染的纹理设备重置方法

  (1)文字设备重置方法

  摧毁代码:

  Set Font = Nothing

  重建代码:

  Set Font = D3DX.CreateFont(D3DDevice, IFont.hFont)

  (2)用来渲染的纹理设备重置方法

  摧毁代码:

  Set rendertex = Nothing

  重建代码:

  Set rendertex = D3DX.CreateTexture(D3DDevice, width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT)

  要注意的是DX所有的文字、用来渲染的纹理对象、表面对象都需要重置,只要漏了一个,D3DDevice.Reset D3DPresentParam这句就不能执行,所以当出现切换回游戏有自动化错误的时侯,就是因为对象没有清空干净。
发表于 2010-12-5 11:47:54 | 显示全部楼层
文字不用摧毁,只需要调用OnXXXX那个方法就可以了……
回复 支持 反对

使用道具 举报

发表于 2010-12-5 11:49:27 | 显示全部楼层
另外你们怎么这么喜欢用古老过时的DX8啊……我现在都升级成DX9了,只不过因为这里没有Vista,要不然就升级到DX10,DX11了……
回复 支持 反对

使用道具 举报

发表于 2010-12-5 12:30:22 | 显示全部楼层
学习一下了,看看的脑袋云云的.........
回复 支持 反对

使用道具 举报

发表于 2010-12-5 16:49:32 | 显示全部楼层
3# acme_pjz

等我整理好~!我在?上?2D Engine -- Project impactX
我把它改成DX9版的了~!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-12-5 19:02:15 | 显示全部楼层
5# a153957 呵呵 等待你的作品~
回复 支持 反对

使用道具 举报

发表于 2011-1-11 00:10:57 | 显示全部楼层
学习学习再学习
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-1-11 21:04:52 | 显示全部楼层
DrawTextW 绘文字 很慢  TextOut 又绘不上  这是个非常郁闷的问题

点评

用多线程...分条线程出来专门绘制文字用..  发表于 2012-4-8 00:39
回复 支持 反对

使用道具 举报

发表于 2011-1-12 00:28:53 | 显示全部楼层
8# 19900603

D3DXFont不是可以么?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-1-15 14:04:29 | 显示全部楼层
速度开可以 就是不太给力
昨天把大部分文字(汉字 字母 数字 特殊符号 大约32000 多个)转换成图片进行打包
按照Asc码进行排列 读取按照Asc 码进行读取 替换原先的 DrawFont  
发现 速度还是不很给力,并且 字体颜色也不好控制 所以放弃了,,,,
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

文字版|手机版|小黑屋|VBGood  

GMT+8, 2022-7-4 05:32

VB爱好者乐园(VBGood)
快速回复 返回顶部 返回列表