VB6编程:DirectX 2D图形学习日志27图形引擎分析
一、初始化
1.设置全屏分辨率: 源码是800600,我修改成1024768
Fullscreen_Width = 1024
Fullscreen_Height = 768
With frmMain
.Caption = "DirectX教程19:2d游戏图形引擎"
.ScaleMode = 3
.Width = (1024 / 2) * Screen.TwipsPerPixelX '表示横坐标中每像素有多少缇
.Height = (768 / 2) * Screen.TwipsPerPixelY '表示纵坐标中每像素有多少缇
End With
2、 初始化DirectX和Direct3D子程序( DirectX_Initialize )
其中:
Private Scalar As D3DVECTOR2'Type D3DVECTOR2成员X,Y
当全屏时:
Scalar.X = Fullscreen_Width / frmMain.ScaleWidth
Scalar.Y = Fullscreen_Height / frmMain.ScaleHeight
当窗口化时:
Scalar.X = 1
Scalar.Y = 1
3、设置_地图 子程序(Setup_Map)
地图类型的结构定义如下:
Private Type Map_Type
Map() As String
Tile() As Long
New_Tile() As Long
Width As Long '宽度
Height As Long '高度
New_Width As Long '新宽度
New_Height As Long '新宽度
Number_Of_Vertices_Per_Tile_Set() As Long '数量_顶点数_瓷砖数_套数
Number_Of_Polygons_Per_Tile_Set() As Long '数量_多边形数_每_瓷砖_设置
Number_Of_Textures As Long '_ _ _纹理的数量
Texture_List() As Direct3DTexture8
Number_Of_Vertices As Long
End Type
Private Map As Map_Type
这里的地图上的物体代码存在一个19*15的数组里:每个横纵位置表示一个物体编号,
0=草地:
1=植物:
2=标识牌:
3=池塘1:
4=池塘2:
5=池塘3:
6=池塘4:
'地图数组
Map.Width = (20) - 1
Map.Height = (16) - 1
ReDim Map.Map(Map.Height) As String
'地图结构
Map.Map(0) = "2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2"
Map.Map(1) = "0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0"
Map.Map(2) = "0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0"
Map.Map(3) = "0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0"
Map.Map(4) = "0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0"
Map.Map(5) = "0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0"
Map.Map(6) = "0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0"
Map.Map(7) = "0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0"
Map.Map(8) = "0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0"
Map.Map(9) = "0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0"
Map.Map(10) = "0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0"
Map.Map(11) = "0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0"
Map.Map(12) = "0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0"
Map.Map(13) = "0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0"
Map.Map(14) = "0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0"
Map.Map(15) = "2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2"
ReDim Map.Tile(Map.Width, Map.Height) As Long
ReDim Map.New_Tile(Map.Width, Map.Height) As Long
For Y = 0 To Map.Height
Temp = Split(Map.Map(Y), ", ", -1)
For X = 0 To Map.Width
Map.Tile(X, Y) = CLng(Temp(X))
Next X
Next Y
4. 从文件加载纹理贴图子程序(Load_Textures )
过程同前文所述
5.创建多边形子程序: (Create_Polygons)
'顶点数
Map.Number_Of_Vertices = ((Map.Width + 1) * (Map.Height + 1) * Number_Of_Vertices_Per_Quad)
'主_顶点列表(顶点数-1)
ReDim Master_Vertex_List(Map.Number_Of_Vertices - 1) As TLVERTEX
'顶点列表(顶点数-1)
ReDim Vertex_List(Map.Number_Of_Vertices - 1) As TLVERTEX
'排序_顶点列表(顶点数-1)
ReDim Sorted_Vertex_List(Map.Number_Of_Vertices - 1) As TLVERTEX
'映射_ To_顶点_列表_和_剪辑 主_顶点列表(顶点数-1),顶点列表(顶点数-1)
Map_To_Vertex_List_And_Clip Map, Master_Vertex_List(), Vertex_List()
'排序_多边形_依纹理 顶点列表(顶点数-1), 排序_顶点列表(顶点数-1)
Sort_Polygons_By_Texture Map, Vertex_List(), Sorted_Vertex_List()
'创建顶点缓冲区。
Set Vertex_Buffer = Direct3D_Device.CreateVertexBuffer(Len(Sorted_Vertex_List(0)) * Map.Number_Of_Vertices, 0, FVF_TLVERTEX, D3DPOOL_MANAGED)
D3DVertexBuffer8SetData Vertex_Buffer, 0, Len(Sorted_Vertex_List(0)) * Map.Number_Of_Vertices, 0, Sorted_Vertex_List(0)
Direct3D_Device.SetStreamSource 0, Vertex_Buffer, Len(Sorted_Vertex_List(0))
创建多边形过程如下:
①顶点数=((地图的宽 + 1) * (地图的高 + 1) * 数量_顶点数_每个_四边形)
② Map_To_Vertex_List_And_Clip子程序作用:映射_ To_顶点_列表_和_剪辑
函数代码:
Private Sub Map_To_Vertex_List_And_Clip(Map As Map_Type, Old_Vertex_List() As TLVERTEX, New_Vertex_List() As TLVERTEX)
Dim X As Long, Y As Long
Dim X2 As Long, Y2 As Long
Dim I As Long, J As Long
Dim Temp As Long
Temp = -1
For Y = 0 To Map.Height '地图高
For X = 0 To Map.Width '地图宽
'先循环X轴的贴图,旧_顶点列表0-5
Old_Vertex_List(I + 0) = Create_TLVertex(GlobalX + ((TILE_WIDTH * X) + 0) * Scalar.X, GlobalY + ((TILE_HEIGHT * Y) + 0) * Scalar.Y, 0, 1, D3DColorRGBA(255, 255, 255, 0), 0, 0, 0)
Old_Vertex_List(I + 1) = Create_TLVertex(GlobalX + ((TILE_WIDTH * X) + TILE_WIDTH) * Scalar.X, GlobalY + ((TILE_HEIGHT * Y) + 0) * Scalar.Y, 0, 1, D3DColorRGBA(255, 255, 255, 0), 0, 1, 0)
Old_Vertex_List(I + 2) = Create_TLVertex(GlobalX + ((TILE_WIDTH * X) + 0) * Scalar.X, GlobalY + ((TILE_HEIGHT * Y) + TILE_HEIGHT) * Scalar.Y, 0, 1, D3DColorRGBA(255, 255, 255, 0), 0, 0, 1)
Old_Vertex_List(I + 3) = Create_TLVertex(GlobalX + ((TILE_WIDTH * X) + TILE_WIDTH) * Scalar.X, GlobalY + ((TILE_HEIGHT * Y) + 0) * Scalar.Y, 0, 1, D3DColorRGBA(255, 255, 255, 0), 0, 1, 0)
Old_Vertex_List(I + 4) = Create_TLVertex(GlobalX + ((TILE_WIDTH * X) + TILE_WIDTH) * Scalar.X, GlobalY + ((TILE_HEIGHT * Y) + TILE_HEIGHT) * Scalar.Y, 0, 1, D3DColorRGBA(255, 255, 255, 0), 0, 1, 1)
Old_Vertex_List(I + 5) = Create_TLVertex(GlobalX + ((TILE_WIDTH * X) + 0) * Scalar.X, GlobalY + ((TILE_HEIGHT * Y) + TILE_HEIGHT) * Scalar.Y, 0, 1, D3DColorRGBA(255, 255, 255, 0), 0, 0, 1)
'如果 Clip_Polygon(剪辑_多边形的子程序)
If Clip_Polygon(Old_Vertex_List(I + 0), Old_Vertex_List(I + 4)) = False Then
New_Vertex_List(J + 0) = Old_Vertex_List(I + 0)
New_Vertex_List(J + 1) = Old_Vertex_List(I + 1)
New_Vertex_List(J + 2) = Old_Vertex_List(I + 2)
New_Vertex_List(J + 3) = Old_Vertex_List(I + 3)
New_Vertex_List(J + 4) = Old_Vertex_List(I + 4)
New_Vertex_List(J + 5) = Old_Vertex_List(I + 5)
X2 = X2 + 1
If Temp <> Y Then
Temp = Y
X2 = 1
Y2 = Y2 + 1
End If
Map.New_Tile(X2 - 1, Y2 - 1) = Map.Tile(X, Y)
J = J + Number_Of_Vertices_Per_Quad
End If
I = I + Number_Of_Vertices_Per_Quad
Next X
Next Y
Map.New_Width = X2
Map.New_Height = Y2
End Sub
③ Clip_Polygon(剪辑_多边形的子程序)
Private Function Clip_Polygon(Polygon_A As TLVERTEX, Polygon_B As TLVERTEX) As Boolean '剪辑_多边形
Dim R As RECT
Dim Border_Size As Long
Border_Size = 0
If Fullscreen_Enabled = False Then
R.Left = Border_Size * Scalar.X
R.Top = Border_Size * Scalar.Y
R.Right = Me.ScaleWidth - Border_Size * Scalar.X
R.bottom = Me.ScaleHeight - Border_Size * Scalar.Y
Else
R.Left = Border_Size * Scalar.X
R.Top = Border_Size * Scalar.Y
R.Right = Fullscreen_Width - Border_Size * Scalar.X
R.bottom = Fullscreen_Height - Border_Size * Scalar.Y
End If
If (Polygon_A.X < R.Left And Polygon_B.X < R.Left) Or (Polygon_A.X > R.Right And Polygon_B.X > R.Right) Or _
(Polygon_A.Y < R.Top And Polygon_B.Y < R.Top) Or (Polygon_A.Y > R.bottom And Polygon_B.Y > R.bottom) Then Clip_Polygon = True
End Function
④Sort_Polygons_By_Texture :排序_多边形_依纹理
Private Sub Sort_Polygons_By_Texture(Map As Map_Type, Old_Vertex_List() As TLVERTEX, New_Vertex_List() As TLVERTEX)
Dim X As Long, Y As Long
Dim I As Long, J As Long, K As Long
For Current_Texture = 0 To Map.Number_Of_Textures
I = 0
For Y = 0 To Map.New_Height - 1
For X = 0 To Map.New_Width - 1
If Map.New_Tile(X, Y) = Current_Texture Then
New_Vertex_List(J + 0) = Old_Vertex_List(I + 0)
New_Vertex_List(J + 1) = Old_Vertex_List(I + 1)
New_Vertex_List(J + 2) = Old_Vertex_List(I + 2)
New_Vertex_List(J + 3) = Old_Vertex_List(I + 3)
New_Vertex_List(J + 4) = Old_Vertex_List(I + 4)
New_Vertex_List(J + 5) = Old_Vertex_List(I + 5)
'对所有顶点求和,请勿重置此变量。
J = J + Number_Of_Vertices_Per_Quad
'每个纹理的顶点总数。
K = K + Number_Of_Vertices_Per_Quad
End If
I = I + Number_Of_Vertices_Per_Quad
Next X
Next Y
Map.Number_Of_Polygons_Per_Tile_Set(Current_Texture) = K / 3
Map.Number_Of_Vertices_Per_Tile_Set(Current_Texture) = K
K = 0 '重置此纹理,另一个纹理即将到来
Next Current_Texture
End Sub
6、DirectInput _初始化_键盘子程序(DirectInput_Initialize_Keyboard)
键盘初始化
Set Direct_Input = DirectX8.DirectInputCreate
Set Keyboard_Device = Direct_Input.CreateDevice("GUID_SysKeyboard")
Keyboard_Device.SetCommonDataFormat DIFORMAT_KEYBOARD
Keyboard_Device.SetCooperativeLevel Window.hWnd, DISCL_BACKGROUND Or DISCL_NONEXCLUSIVE
Keyboard_Device.Acquire
Keyboard_Device.GetDeviceStateKeyboard Keyboard_State
7、高精度计时器初始化子程序(Hi_Res_Timer_Initialize)
过程同前文所述
经过前边7个步骤后进入游戏循环子程序
二、游戏循环子程序:(ame_Loop)
1.键盘控制子程序:Control 前边使用Form_KeyDown来判断按键值,这里使用单独的DirectX子程序来判断, DirectInput_Key_State(DirectInput _键_状态:key(0 To 255) As Byte)
'根据按键移动画面
Private GlobalX As Single, GlobalY As Single
If DirectInput_Key_State(DIK_ESCAPE) <> 0 Then Close_Program'ESC退出程序
'---------------------------------------------
'左右
'---------------------------------------------
If DirectInput_Key_State(DIK_LEFT) <> 0 And DirectInput_Key_State(DIK_RIGHT) = 0 Then
GlobalX = Initial_Global.X + Speed * Time(0) * Scalar.X
ElseIf DirectInput_Key_State(DIK_LEFT) = 0 And DirectInput_Key_State(DIK_RIGHT) <> 0 Then
GlobalX = Initial_Global.X - Speed * Time(1) * Scalar.X
ElseIf (DirectInput_Key_State(DIK_LEFT) <> 0 And DirectInput_Key_State(DIK_RIGHT) <> 0) Or _
(DirectInput_Key_State(DIK_LEFT) = 0 And DirectInput_Key_State(DIK_RIGHT) = 0) Then
Milliseconds(0) = Elapsed_Time
Milliseconds(1) = Elapsed_Time
Initial_Global.X = GlobalX
End If
'---------------------------------------------
'---------------------------------------------
'上/下
'---------------------------------------------
If DirectInput_Key_State(DIK_UP) <> 0 And DirectInput_Key_State(DIK_DOWN) = 0 Then
GlobalY = Initial_Global.Y + Speed * Time(2) * Scalar.Y
ElseIf DirectInput_Key_State(DIK_UP) = 0 And DirectInput_Key_State(DIK_DOWN) <> 0 Then
GlobalY = Initial_Global.Y - Speed * Time(3) * Scalar.Y
ElseIf (DirectInput_Key_State(DIK_UP) <> 0 And DirectInput_Key_State(DIK_DOWN) <> 0) Or _
(DirectInput_Key_State(DIK_UP) = 0 And DirectInput_Key_State(DIK_DOWN) = 0) Then
Milliseconds(2) = Elapsed_Time
Milliseconds(3) = Elapsed_Time
Initial_Global.Y = GlobalY
End If
'---------------------------------------------
2、碰撞检测子程序 (Collision_Detection)
在移动窗口的时候,用来检测是否超过边界
Dim R As RECT
R.Left = (-(Map.Width * TILE_WIDTH / 2) - TILE_WIDTH / 2) * Scalar.X
R.Top = (-(Map.Height * TILE_HEIGHT / 2) - TILE_HEIGHT / 2) * Scalar.Y
R.Right = 0
R.bottom = 0
If GlobalX <= R.Left Then GlobalX = R.Left
If GlobalY <= R.Top Then GlobalY = R.Top
If GlobalX >= R.Right Then GlobalX = R.Right
If GlobalY >= R.bottom Then GlobalY = R.bottom
3、Create_Polygons,创建多边形 这时候根据GlobalX,GlobalY 坐标重新绘制多边形并显示