DirectX в Visual Basic 2005 для начинающих (исходники)

Источник: GOT DOT NET
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


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=7374