bikinandrey
Начнем с небольшого вступления. Что нужно для того чтоб работала скомпилированная программа, использующая функции DirectX? А нужен для этого установленный Microsoft DirectX и все. Как пример любая игра, использующая DirectX, которая обычно этот DirectX несет с собой на диске. А вот для того, чтоб делать DirectX программу в Visual Studio 2005, нужен еще один компонент Managed DirectX (управляемый DirectX). Устанавливается Managed DirectX автоматически вместе с установкой Microsoft DirectX (начиная с каких-то версий DirectX 2006 года, точно не знаю).
Устанавливаем самый свежий из имеющихся у нас Microsoft DirectX (я использовал 4.9.0.904 за февраль 2007 года). Самый свежий, во-первых, для того, чтоб в его составе был Managed DirectX, а во-вторых, по той причине, что прорисовка трехмерной графики в новых версиях DirectX (даже в пределах одного и того же DirectX9) качественно отличается от старых версий. Теперь проверим, действительно ли Managed DirectX установился в нашей системе. Для этого зайдем в папку "C:\WINDOWS\Microsoft.NET" которая естественно должна присутствовать, если у вас установлена Visual Studio и проверим, есть ли там папка "DirectX for Managed Code" или "Managed DirectX", если есть, то все нормально.
Создаем новый проект "WindowsApplication" в Visual Studio 2005 с использованием языка Visual Basic. Переходим в окно "Class View", нажимаем правую кнопку мыши, выбираем "Add Reference". Переходим на вкладку "Browse" находим папку " C:\WINDOWS\Microsoft.NET\DirectX for Managed Code" и подключаем пять библиотек:
- Microsoft.DirectX
- Microsoft.DirectX.Direct3D
- Microsoft.DirectX.Direct3DX
- Microsoft.DirectX.DirectSound
- Microsoft.DirectX.DirectInput
Вот и все, теперь импортировав пространство имен, соответствующее названиям этих библиотек, мы сможем использовать функции DirectX. Переходим в окно кода и копируем в него весь нижеприведенный код. Этого будет достаточно, чтобы программа сразу же запустилась (никакие свойства формы менять не надо и добавлять какие-либо компоненты на форму тоже не надо). Из кода исключено все лишнее, показано только использование функций Direct3D (Трехмерная графика), DirectSound (Звук), DirectInput (Устройства ввода) плюс немного геометрии для изучения движения объектов в трехмерном пространстве. Весь код тщательно прокомментирован, поэтому думаю, вам нетрудно будет в нем разобраться.
Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D
Imports Microsoft.DirectX.DirectSound
Imports Microsoft.DirectX.DirectInput
Public Class Form1
' Объявление переменных Direct3D
Private Direct3D_Device As Direct3D.Device
Private Direct3D_PresentParameters As New Direct3D.PresentParameters
Private Ship_1, Ship_2, Ship_3, Planet As Direct3D.Mesh
Private Direct3D_Material As Direct3D.Material
' Объявление переменных DirectSound
Private DirectSound_Device As DirectSound.Device
Private DirectSound_SecondaryBuffer As DirectSound.SecondaryBuffer
' Объявление переменных DirectInput
Private DirectInput_Device As DirectInput.Device
Private DirectInput_MouseState As New DirectInput.MouseState
' Объявление остальных переменных
Private Ship_Matrix As Microsoft.DirectX.Matrix
Private VectorOX, VectorOY, VectorOZ, Planet_Position(10000), Ship_Position, Ship_Vector As Microsoft.DirectX.Vector3
Private AngleX, AngleY As Single
Private I As Integer
Private DateTime1 As DateTime
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Location = New Point(50, 20) ' Положение окна
ClientSize = New Size(800, 600) ' Размер окна
' Инициализация Direct3D в окне программы
Direct3D_PresentParameters.Windowed = True
Direct3D_PresentParameters.SwapEffect = SwapEffect.Discard
Direct3D_PresentParameters.EnableAutoDepthStencil = True
Direct3D_PresentParameters.AutoDepthStencilFormat = DepthFormat.D16
Direct3D_Device = New Direct3D.Device(0, Direct3D.DeviceType.Hardware, Me.Handle, CreateFlags.SoftwareVertexProcessing, Direct3D_PresentParameters)
Direct3D_Device.Transform.Projection = Matrix.PerspectiveFovLH(CSng(Math.PI) / 4, 4 / 3, 1, 100)
' Освещение (два источника света направленные противоположно друг другу)
Direct3D_Device.RenderState.Lighting = True
Direct3D_Device.Lights(0).Diffuse = Color.White
Direct3D_Device.Lights(0).Type = LightType.Directional
Direct3D_Device.Lights(0).Direction = New Vector3(0, 0, 1)
Direct3D_Device.Lights(0).Enabled = True
Direct3D_Device.Lights(1).Diffuse = Color.White
Direct3D_Device.Lights(1).Type = LightType.Directional
Direct3D_Device.Lights(1).Direction = New Vector3(0, 0, -1)
Direct3D_Device.Lights(1).Enabled = True
' Инициализация DirectSound
DirectSound_Device = New DirectSound.Device
DirectSound_Device.SetCooperativeLevel(Me, CooperativeLevel.Priority)
DirectSound_SecondaryBuffer = New SecondaryBuffer("C:\WINDOWS\Media\Windows XP - отказ оборудования.wav", DirectSound_Device)
' Инициализация DirectInput
DirectInput_Device = New DirectInput.Device(SystemGuid.Mouse)
DirectInput_Device.SetCooperativeLevel(Me, CooperativeLevelFlags.Exclusive Or CooperativeLevelFlags.Foreground)
' Инициализация остальных переменных
VectorOX = New Vector3(1, 0, 0)
VectorOY = New Vector3(0, 1, 0)
VectorOZ = New Vector3(0, 0, 1)
Ship_Matrix.Translate(0, 0, 0)
' Корабль - сфера и два бокса
Ship_1 = Mesh.Box(Direct3D_Device, 0.5, 0.003, 0.1)
Ship_2 = Mesh.Box(Direct3D_Device, 0.003, 0.5, 0.1)
Ship_3 = Mesh.Sphere(Direct3D_Device, 0.02, 20, 20)
' Планета - сфера радиусом 1
Planet = Mesh.Sphere(Direct3D_Device, 1, 20, 20)
Randomize()
For I = 0 To 10000
' Массив координат планет из случайных чисел в ограниченном пространстве
' 500 единиц по каждому измерению
Planet_Position(I) = New Vector3(Rnd() * 500 - 250, Rnd() * 500 - 250, Rnd() * 500 - 250)
Next
End Sub
Private Sub Form1_Activated(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Activated
DirectInput_Device.Acquire() ' Захват устройств ввода при активации окна
End Sub
Private Sub Form1_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
If e.KeyCode = Keys.Escape Then
Close() ' Если нажат Escape то выход
End If
End Sub
Private Sub Form1_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
While Created
If (Now - DateTime1).TotalMilliseconds > 30 Then ' Прорисовку выполняем через каждые 30 миллисекунд
' если не устанавливать временной интервал, то цикл будут выполняться
' через разные промежутки времени, и движение корабля будет неравномерным
' Также если ваша система не будет успевать выполнять код за 30 миллисекунд
' то движение корабля тоже будет неравномерным, можно увеличить до 40
' но это уже будут видимые глазу скачки в движении
' Реальное время в миллисекундах, за которое происходит выполнение
' цикла отображаем в заголовке окна
' Если система успевает выполнить цикл, в заголовке будет отображаться число 31.25
Me.Text = (Now - DateTime1).TotalMilliseconds
DateTime1 = Now ' Создание точки отсчета времени
Try
' Получение состояние мыши
DirectInput_MouseState = DirectInput_Device.CurrentMouseState
Catch
End Try
' Расчет углов поворота корабля в зависимости от состояния мыши
AngleX = AngleX + DirectInput_MouseState.X / 30000
If AngleX < -0.03 Then AngleX = -0.03
If AngleX > 0.03 Then AngleX = 0.03
AngleY = AngleY + DirectInput_MouseState.Y / 30000
If AngleY < -0.03 Then AngleY = -0.03
If AngleY > 0.03 Then AngleY = 0.03
Direct3D_Device.BeginScene() ' Начало сцены
' Очистка (выполняется в каждом цикле, то есть каждый цикл все объекты прорисовываются заново)
Direct3D_Device.Clear(ClearFlags.Target Or ClearFlags.ZBuffer, System.Drawing.Color.DarkBlue, 1, 0)
' Расчет матрицы направления корабля путем поворота вокруг векторов
' VectorOY и VectorOX на углы AngleX и AngleY
' А также поворот самих векторов VectorOY, VectorOX, VectorOZ
Ship_Matrix = Ship_Matrix * Matrix.RotationAxis(VectorOY, AngleX)
VectorOX.TransformCoordinate(Matrix.RotationAxis(VectorOY, AngleX))
Ship_Matrix = Ship_Matrix * Matrix.RotationAxis(VectorOX, AngleY)
VectorOY.TransformCoordinate(Matrix.RotationAxis(VectorOX, AngleY))
VectorOZ.TransformCoordinate((Matrix.RotationAxis(VectorOX, AngleY) * Matrix.RotationAxis(VectorOY, AngleX)))
Ship_Vector = New Vector3(0, 0, 1) ' Изначальный вектор направления движения (+1 по оси OZ)
Ship_Vector.TransformCoordinate(Ship_Matrix) ' вектор направления движения изменяем матрицей
Ship_Position = Ship_Position + Ship_Vector ' К позиции корабля прибавляем вектор движения
' Устанавливаем координаты положения корабля (поворот, поворот вокруг оси OZ на 45 градусов и позиция)
Direct3D_Device.Transform.World = Ship_Matrix * Matrix.RotationAxis(VectorOZ, Math.PI / 4) * Matrix.Translation(Ship_Position)
' Устанавливаем камеру сзади корабля с направлением обзора по направлению движения корабля
Direct3D_Device.Transform.View = Matrix.LookAtLH(Ship_Position - Ship_Vector * 1.1, Ship_Position, VectorOY)
' Цвет материала красный
Direct3D_Material.Diffuse = Color.Red
Direct3D_Device.Material = Direct3D_Material
' Создание корабля
Ship_1.DrawSubset(0)
Ship_2.DrawSubset(0)
Ship_3.DrawSubset(0)
' Если расстояние между кораблем и планетами меньше 75 то рисуем планету с индексом I
For I = 0 To 10000
If (Ship_Position - Planet_Position(I)).Length < 75 Then
' Устанавливаем координаты положения планеты
Direct3D_Device.Transform.World = Matrix.Translation(Planet_Position(I))
' Цвет материала светло-зеленый
Direct3D_Material.Diffuse = Color.LightGreen
Direct3D_Device.Material = Direct3D_Material
' Создание планеты
Planet.DrawSubset(0)
End If
Next
' Если расстояние между кораблем и планетами меньше 1
' (столкновение корабля и планеты) то проигрываем звук
For I = 0 To 10000
If (Ship_Position - Planet_Position(I)).Length < 1 Then
DirectSound_SecondaryBuffer.Play(0, BufferPlayFlags.Default)
End If
Next
Direct3D_Device.EndScene() ' Конец сцены
Direct3D_Device.Present() ' Прорисовка сцены
Application.DoEvents() ' Выполнение других событий, для того чтобы
' программа не зависала на выполнении цикла
End If
End While
End Sub
End Class