Книга Справочник Жаркова по проектированию и программированию искусственного интеллекта. Том 4: Программирование на Visual Basic искусственного интеллекта - читать онлайн бесплатно, автор Валерий Алексеевич Жарков. Cтраница 7
bannerbanner
Вы не авторизовались
Войти
Зарегистрироваться
Справочник Жаркова по проектированию и программированию искусственного интеллекта. Том 4: Программирование на Visual Basic искусственного интеллекта
Справочник Жаркова по проектированию и программированию искусственного интеллекта. Том 4: Программирование на Visual Basic искусственного интеллекта
Добавить В библиотекуАвторизуйтесь, чтобы добавить
Оценить:

Рейтинг: 0

Добавить отзывДобавить цитату

Справочник Жаркова по проектированию и программированию искусственного интеллекта. Том 4: Программирование на Visual Basic искусственного интеллекта

Щёлкаем по этой команде “Звук 1” и в панели Properties (для этой команды) значение свойства Checked задаём как True (рис. 6.5), чтобы на форме слева от этой команды появился флажок. А чтобы этот флажок можно было удалить и снова установить (после щелчка по команде мышью), в панели Properties для этой команды значение свойства CheckOnClick также задаём как True.

Дважды щёлкаем по этой команде “Звук 1” (в режиме проектирования). Появляется файл Form1.vb с автоматически сгенерированным шаблоном метода, выше которого объявляем булеву переменную, а в шаблон записываем код, как показано на следующем листинге.

Листинг 6.8. Код для приостановки и возобновления звука.

'Объявляем логическую переменную OffOn и задаём ей True:

Dim OffOn As Boolean = True

Private Sub Sound1ToolStripMenuItem_Click( _

ByVal sender As System.Object, ByVal e As System.EventArgs) _

Handles Sound1ToolStripMenuItem.Click

'Изменяем значение на противоположное:

OffOn = Not OffOn

'Выключаем Stop и включаем Play звук 1:

If (OffOn = False) Then

My.Computer.Audio.Stop()

Else

My.Computer.Audio.Play("..\..\drumpad-crash.wav", _

AudioPlayMode.BackgroundLoop)

End If

End Sub



Рис. 6.4. Команды MenuStrip.



Рис. 6.5. Задаём свойства команды.

Теперь в режиме выполнения (Build, Build Selection; Debug, Start Without Debugging), поочерёдно удаляя или устанавливая мышью флажок напротив этой команды “Звук 1”, мы будем выключать методом Stop и включать методом Play циклическое (Loop) непрерывное воспроизведение звукового файла, который мы добавили в проект.

Если после каждой установки флажка нам нужно воспроизводить звуковой файл только один раз, то вместо строки:

My.Computer.Audio.Play("..\..\drumpad-crash.wav", _

AudioPlayMode.BackgroundLoop)

записываем:

My.Computer.Audio.Play("..\..\drumpad-crash.wav")

Аналогично можно использовать команду “Звук 2” для управления вторым звуковым файлом.

Аналогично по этой методике мы можем добавить в проект много звуковых файлов, а в меню MenuStrip – много команд для приостановки и возобновления звукового сопровождения разнообразных игр (в режиме выполнения).

6.4. Методика воспроизведения звуковых файлов на основе встроенного ресурса

Недостатком предыдущей методики на основе пространства имён My является невозможность её использования для мобильных устройств (карманных компьютеров, коммуникаторов, смартфонов, мобильных телефонов и т.п.) с операционной системой Windows Mobile.

И среда выполнения .NET Framework для настольных компьютеров, и среда выполнения .NET Compact Framework для мобильных устройств позволяет записать неуправляемый код для воспроизведения звуковых файлов по методике встроенного ресурса (Embedded Resource) с использованием платформы Platform Invoke (сокращенно P/Invoke) и динамически подключаемой библиотеки (dynamic link library) winmm.dll (для настольного компьютера) или CoreDll.dll (для мобильного устройства) из более общей библиотеки Windows API (Application Programming Interfaces).

Данная универсальная методика на основе встроенного ресурса удобна при переносе какого-либо приложения (со звуковым сопровождением) с настольного компьютера на мобильное устройство и наоборот.

В данном параграфе мы разработаем универсальную методику воспроизведения звуковых файлов на основе нового файла Sound.vb, в котором имеется одноименный класс Sound.

Мы назвали эту методику универсальной потому, что она может быть применена во многих самых разнообразных играх, и далее будет нами применена в некоторых типичных играх.

В приложении класс Sound должен обеспечить:

выключение звука, если пользователь не желает его слушать;

непрерывный циклический звук;

одиночный звук.

Для каждого звука мы создаём объект класса Sound. Есть также несколько перегруженных конструкторов этого класса, чтобы мы могли создать объект при использовании внутреннего ресурса в виде пути к звуковому файлу filename или потока (Stream), как показано в следующем коде:

'Метод для считывания звукового файла:

Private Sub readStream(ByVal soundStream As Stream)

'Создаём массив soundBytes с элементами типа Byte

'и инициализируем размерность этого массива

'как длину звукового файла soundStream.Length:

soundBytes = New Byte(soundStream.Length) {}

'Из потока soundStream считываем звуковой файл

'в массив soundBytes:

soundStream.Read(soundBytes, 0, soundStream.Length)

End Sub

'Объявляем метод-конструктор класса Sound

'с параметром в виде потока soundStream класса Stream:

Public Sub New(ByVal soundStream As Stream)

'Вызываем метод для считывания звукового файла:

readStream(soundStream)

End Sub

'Объявляем метод-конструктор класса Sound

'с параметром в виде пути filename к звуковому файлу:

Public Sub New(ByVal filename As String)

Dim execAssem As System.Reflection.Assembly = _

System.Reflection.Assembly.GetExecutingAssembly()

Dim soundStream As Stream = _

execAssem.GetManifestResourceStream(filename)

If (soundStream Is Nothing) Then

System.Windows.Forms.MessageBox.Show( _

"Missing file : " + filename, "Audio Load")

Return

End If

readStream(soundStream)

End Sub

Метод readStream выполняет фактическую загрузку звука. Операционная система управляет звуком. Класс Sound использует платформу Platform Invoke (P/Invoke), чтобы при помощи этого метода вызвать и управлять звуком, как показано в следующем коде:

Public Enum Flags

SND_ALIAS = &H10000

SND_ALIAS_ID = &H110000

SND_FILENAME = &H20000

SND_RESOURCE = &H40004

SND_SYNC = &H0

SND_ASYNC = &H1

SND_NODEFAULT = &H2

SND_MEMORY = &H4

SND_LOOP = &H8

SND_NOSTOP = &H10

SND_NOWAIT = &H2000

SND_VALIDFLAGS = &H17201F

SND_RESERVED = &HFF000000

SND_TYPE_MASK = &H170007

End Enum

Private Declare Function PlaySound _

Lib "winmm.dll" Alias "PlaySound" (ByVal szSound() As Byte, _

ByVal hModule As IntPtr, ByVal dwFlags As Integer) As Integer

В этом коде ряд флажков (Flags) непосредственно управляет генерацией звука. Класс Sound содержит статический член, который в настоящее время имеет ссылку на непрерывный циклический звук (или любой другой). Если звук был выключен и затем снова включён, циклический звук возобновляется. Класс Sound содержит методы Play и PlayLoop для одиночного и циклического воспроизведения звукового файла, как показано в следующем коде:

'Метод для разового воспроизведения звукового файла:

Public Sub Play()

loopSound = Nothing

If (Sound.Enabled) Then

PlaySound(soundBytes, IntPtr.Zero, _

Fix(Flags.SND_ASYNC Or _

Flags.SND_MEMORY))

End If

End Sub

'Метод для циклического воспроизведения звукового файла:

Public Sub PlayLoop()

loopSound = soundBytes

If (Sound.Enabled) Then

PlaySound(soundBytes, IntPtr.Zero, _

Fix(Flags.SND_ASYNC Or _

Flags.SND_MEMORY Or _

Flags.SND_LOOP))

End If

End Sub

Метод StopSound в классе Sound останавливает проигрывающийся звук, задавая массиву soundBytes нулевое значение (Zero) следующим образом:

Public Sub StopSound()

If (Not loopSound Is Nothing) Then

PlaySound(Nothing, IntPtr.Zero, _

0)

End If

End Sub

Метод ResumeSound возобновляет звук только тогда, если до этого воспроизводился циклический звук, как показано в следующем коде:

Public Sub ResumeSound()

If (Not Sound.Enabled) Then

Return

End If

If (Not loopSound Is Nothing) Then

PlaySound( _

loopSound, _

IntPtr.Zero, _

Flags.SND_ASYNC Or Flags.SND_MEMORY Or _

Flags.SND_LOOP)

End If

End Sub

Теперь от описания приступим к конкретной реализации.

А именно, для воспроизведения звуковых файлов, которые добавлены в проект по описанной ранее схеме, при помощи универсального (для многих приложений и игр) файла Sound.vb, в панели Solution Explorer выполняем правый щелчок по имени проекта и в контекстном меню выбираем Add, New Item. В панели Add New Item выделяем шаблон Code File, в окне Name записываем имя Sound.vb и щёлкаем кнопку Add.

В проект (и в панель Solution Explorer) добавляется этот файл, открывается пустое окно редактирования кода, в которое записываем следующий код.

Листинг 6.9. Файл Sound.vb.

Imports System.IO 'Для класса Stream.

Public Class Sound

'Переменная включает и выключает звук:

Public Shared Enabled As Boolean = True

'Свойство для приостановки и возобновления звука:

Public Property EnabledProperty() As Boolean

Get

Return Enabled

End Get

Set(ByVal value As Boolean)

Enabled = value

If (value) Then

ResumeSound()

Else

StopSound()

End If

End Set

End Property

'Массив для циклического звучания:

Private loopSound() As Byte = Nothing

'Массив для одноразового воспроизведения звука:

Private soundBytes() As Byte


'Флажки (константы) для управления методами

'операционной системы Windows CE, а именно,

'методом PlaySound из библиотеки CoreDll.dll

'при воспроизведении звукового файла:

Public Enum Flags

SND_ALIAS = &H10000

SND_ALIAS_ID = &H110000

SND_FILENAME = &H20000

SND_RESOURCE = &H40004

SND_SYNC = &H0

SND_ASYNC = &H1

SND_NODEFAULT = &H2

SND_MEMORY = &H4

SND_LOOP = &H8

SND_NOSTOP = &H10

SND_NOWAIT = &H2000

SND_VALIDFLAGS = &H17201F

SND_RESERVED = &HFF000000

SND_TYPE_MASK = &H170007

End Enum

'Из пространства имён System.Runtime.InteropServices

'импортируем библиотеку CoreDll.dll и

'объявляем функцию PlaySound этой библиотеки:

Private Declare Function PlaySound _

Lib "winmm.dll" Alias "PlaySound" (ByVal szSound() As Byte, _

ByVal hModule As IntPtr, ByVal dwFlags As Integer) As Integer

'Метод для считывания звукового файла:

Private Sub readStream(ByVal soundStream As Stream)

'Создаём массив soundBytes с элементами типа Byte

'и инициализируем размерность этого массива

'как длину звукового файла soundStream.Length:

soundBytes = New Byte(soundStream.Length) {}

'Из потока soundStream считываем звуковой файл

'в массив soundBytes:

soundStream.Read(soundBytes, 0, soundStream.Length)

End Sub

'Объявляем метод-конструктор класса Sound

'с параметром в виде потока soundStream класса Stream:

Public Sub New(ByVal soundStream As Stream)

'Вызываем метод для считывания звукового файла:

readStream(soundStream)

End Sub

'Объявляем метод-конструктор класса Sound

'с параметром в виде пути filename к звуковому файлу:

Public Sub New(ByVal filename As String)

Dim execAssem As System.Reflection.Assembly = _

System.Reflection.Assembly.GetExecutingAssembly()

Dim soundStream As Stream = _

execAssem.GetManifestResourceStream(filename)

If (soundStream Is Nothing) Then

System.Windows.Forms.MessageBox.Show( _

"Missing file : " + filename, "Audio Load")

Return

End If

readStream(soundStream)

End Sub

'Метод для разового воспроизведения звукового файла:

Public Sub Play()

loopSound = Nothing

If (Sound.Enabled) Then

PlaySound(soundBytes, IntPtr.Zero, _

Fix(Flags.SND_ASYNC Or _

Flags.SND_MEMORY))

End If

End Sub

'Метод для циклического воспроизведения звукового файла:

Public Sub PlayLoop()

loopSound = soundBytes

If (Sound.Enabled) Then

PlaySound(soundBytes, IntPtr.Zero, _

Fix(Flags.SND_ASYNC Or _

Flags.SND_MEMORY Or _

Flags.SND_LOOP))

End If

End Sub

'Метод остановки воспроизведения звукового файла:

Public Sub StopSound()

If (Not loopSound Is Nothing) Then

PlaySound(Nothing, IntPtr.Zero, _

0)

End If

End Sub

'Метод для восстановления воспроизведения звукового файла:

Public Sub ResumeSound()

If (Not Sound.Enabled) Then

Return

End If

If (Not loopSound Is Nothing) Then

PlaySound( _

loopSound, _

IntPtr.Zero, _

Flags.SND_ASYNC Or Flags.SND_MEMORY Or _

Flags.SND_LOOP)

End If

End Sub

End Class

Этот файл Sound.vb можно использовать во многих приложениях и играх для воспроизведения звуковых файлов, добавляя его в проект по стандартной схеме Project, Add Existing Item, как мы сейчас покажем на конкретном примере нового проекта.

Для создания проекта в VS щёлкаем кнопку New Project (или File, New, Project). В панели New Project в окне Project Types выбираем тип проекта Visual Basic, Windows, в окне Templates выделяем шаблон Windows Forms Application, в окне Name записываем любое имя проекта, например, Sounds4 и щёлкаем OK. Создаётся проект, появляется форма Form1 (рис. 6.6) в режиме проектирования.



Рис. 6.6. Форма Form1 в режиме выполнения.

Проектируем (или оставляем по умолчанию) эту форму, как описано в параграфе “Методика проектирования формы”.

Для добавления звукового файла move.wav в проект, в меню Project выбираем Add Existing Item, в панели Add Existing Item в окне Files of type устанавливаем All Files, в окне "Look in" находим (например, в папке с загруженным из Интернета файлом) файл и щёлкаем кнопку Add (или дважды щёлкаем по имени файла). Этот файл мы увидим в панели Solution Explorer.

В панели Solution Explorer выделяем имя этого файла, а в панели Properties (для данного файла) в свойстве Build Action (Действие при построении) вместо заданного по умолчанию выбираем значение Embedded Resource (Встроенный ресурс).

Аналогично добавляем и встраиваем в проект второй файл win.wav типа мажорной мелодии.

Аналогично можно добавить и встроить в проект ещё много звуковых файлов, которые мы желаем послушать во время выполнения приложения или игры.

Открываем файл Form1.vb (например, так: File, Open, File) и вверху записываем директиву для подключения требуемого пространства имен:

Imports System.Reflection 'Для класса Assembly.

Напомним, что эту строку можно и не записывать, но тогда нам придётся перед каждым классом записывать эти пространства имён System.Reflection.

Теперь в панели Properties (для формы Form1) на вкладке Events дважды щёлкаем по имени события Load (Загрузка).

Появляется файл Form1.vb с шаблоном метода Form1_Load, который после записи нашего кода принимает следующий вид.

Листинг 6.10. Метод для загрузки и воспроизведения звуковых файлов.

'Объявляем объекты класса Sound для каждого звукового файла:

Dim moveSound As Sound

Dim winSound As Sound

'Создаём объект myAssembly класса System.Reflection.Assembly

'и присваиваем ему ссылку на исполняемую сборку приложения:

Dim myAssembly As Assembly = Assembly.GetExecutingAssembly()

'Создаём объект myAssemblyName

'класса System.Reflection.AssemblyName и присваиваем ему

'имя сборки, которое состоит из имени проекта,

'Version, Culture, PublicKeyToken:

Dim myAssemblyName As AssemblyName = myAssembly.GetName()

'Из имени сборки при помощи свойства Name

'выделяем имя проекта myName_of_project типа String:

Dim myName_of_project As String = myAssemblyName.Name

Private Sub Form1_Load(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles MyBase.Load

'Загружаем звуковые файлы:

'Вариант 1:

'moveSound = _

' New Sound(myAssembly.GetManifestResourceStream( _

' myName_of_project + "." + "move.wav"))

winSound = _

New Sound(myAssembly.GetManifestResourceStream( _

myName_of_project + "." + "win.wav"))

'Загружаем звуковые файлы:

'Вариант 2:

'moveSound = New Sound(myName_of_project + "." + "move.wav")

'winSound = New Sound(myName_of_project + "." + "win.wav")

'Воспроизведение звукового файла:

'moveSound.Play()

'Воспроизведение звукового файла:

winSound.Play()

End Sub

В режиме выполнения (Build, Build Selection; Debug, Start Without Debugging) мы услышим соответствующее (одноразовое) воспроизведение звукового файла, который мы добавили непосредственно в проект (а не в дополнительную папку Sounds проекта).

Теперь строки типа:

moveSound.Play()

winSound.Play()

мы можем записывать в тех местах любой программы, где необходимо воспроизводить соответствующий звуковой файл.

Для циклического (Loop) непрерывного воспроизведения звукового файла вместо строки:

winSound.Play()

следует записать:

winSound.PlayLoop()

Далее можно экспериментировать, как описано выше в первой методике.

Важно отметить, если в игре применяются несколько звуковых файлов, то их целесообразно разместить в одной папке с именем, например, Sounds. Для добавления в проект этой папки, в панели Solution Explorer (рис. 6.7) выполняем правый щелчок по имени проекта, в контекстном меню выбираем Add, New Folder, в поле появившегося значка папки записываем имя папки и нажимаем клавишу Enter.

Добавляем в эту папку (например, из Интернета) первый звуковой файл по стандартной схеме, а именно: выполняем правый щелчок по имени этой папки, в контекстном меню выбираем Add, Existing Item, в панели Add Existing Item в окне “Files of type” выбираем “All Files”, в центральном окне находим и выделяем имя файла и щёлкаем кнопку Add (или дважды щёлкаем по имени файла). В панели Solution Explorer мы увидим этот файл.



Рис. 6.7. Папка Sounds в панели Solution Explorer.

В панели Solution Explorer выделяем имя этого файла, а в панели Properties (для данного файла) в свойстве Build Action (Действие при построении) вместо заданного по умолчанию выбираем значение Embedded Resource (Встроенный ресурс).

Аналогично добавляем в нашу новую папку Sounds данного проекта и встраиваем в виде ресурса остальные звуковые файлы.

Один и тот же звуковой файл мы не можем добавить как непосредственно в проект, так и в папку Sounds (надо выбрать что-то одно, иначе будет ошибка). Вследствие этого весь предыдущий код для воспроизведения звуковых файлов остаётся тем же независимо от того, звуковой файл добавлен непосредственно в проект, или добавлен в наше новую папку Sounds.

Таким образом, по этой методике, добавляя в проект большое количество звуковых файлов, добавляя на форму большое количество кнопок Button (или других элементов управления) и записывая в методы-обработчики щелчков по этим кнопкам различные варианты кода для воспроизведения этих звуковых файлов в различной последовательности и с различным наложением звуков, в режиме выполнения приложения, щёлкая по кнопкам, мы будем получать множество самых разнообразных мелодий.

Отметим, что для управления воспроизведением звуковых файлов в дополнение или вместо кнопок Button (чтобы не загромождать форму Form1) можно использовать и клавиши клавиатуры, и компоненты с панели инструментов Toolbox по описанной ранее методике.

6.5. Методика приостановки и возобновления звуков на основе встроенного ресурса

Для приостановки и возобновления воспроизведения звуковых файлов во время выполнения приложения можно разработать много вариантов кода, например, воспользоваться каким-либо элементом управления или компонентом.

Так как далее для задания режимов почти всех игр мы будем применять выпадающее меню типа MenuStrip, то для решения поставленной здесь задачи применим это меню. С панели инструментов Toolbox переносим на форму элемент управления MenuStrip и щёлкаем по нему (ниже формы в режиме проектирования). На форме Form1 появляются окна с надписью Type Here (Печатайте здесь), в которые записываем команды на русском языке (по второму варианту, можно записывать в панели Properties в свойстве Text), для примера, для управления двумя звуковыми файлами: Звуки, Звук 1, Звук 2, рис. 6.8. Теперь в панели Properties в свойстве Name изменяем эти русские команды на соответствующие английские: Sounds, Sound1, Sound2. Рассмотрим первую команду Звук 1.



Рис. 6.8. Команды MenuStrip.

Щёлкаем по этой команде “Звук 1” и в панели Properties (для этой команды) значение свойства Checked задаём как True, чтобы на форме слева от этой команды появился флажок. А чтобы этот флажок можно было удалить и снова установить (после щелчка по команде мышью), в панели Properties для этой команды значение свойства CheckOnClick также задаём как True.

Дважды щёлкаем по этой команде “Звук 1” (в режиме проектирования). Появляется файл Form1.vb с автоматически сгенерированным шаблоном метода, выше которого объявляем булеву переменную, а в шаблон записываем код, как показано на следующем листинге.

Листинг 6.11. Код для приостановки и возобновления звука.

'Объявляем логическую переменную OffOn и задаём ей True:

Dim OffOn As Boolean = True

Private Sub Sound1ToolStripMenuItem_Click( _

ByVal sender As System.Object, ByVal e As System.EventArgs) _

Handles Sound1ToolStripMenuItem.Click

'Изменяем значение на противоположное:

OffOn = Not OffOn

'Выключаем Stop и включаем Play звук 1:

If (OffOn = False) Then

winSound.StopSound()

Else

winSound.PlayLoop()

End If

End Sub

Теперь в режиме выполнения (Build, Build Selection; Debug, Start Without Debugging), поочерёдно удаляя или устанавливая мышью флажок напротив этой команды “Звук 1”, мы будем выключать методом StopSound и включать методом PlayLoop циклическое (Loop) непрерывное воспроизведение звукового файла, который мы добавили в проект.

Если после каждой установки флажка нам нужно воспроизводить звуковой файл только один раз, то вместо строки:

winSound.PlayLoop()

записываем (как уже было показано выше):

winSound.Play()

Аналогично можно использовать команду “Звук 2” для управления вторым звуковым файлом. Аналогично по этой методике мы можем добавить в проект много звуковых файлов, а в меню MenuStrip – много команд для приостановки и возобновления звукового сопровождения разнообразных игр (в режиме выполнения).

6.6. Вариант воспроизведения звуковых файлов на основе встроенного ресурса

Учитывая важность методики воспроизведения звуковых файлов на основе встроенного ресурса, которую можно применять в приложениях и для настольного компьютера, и для мобильного устройства, приведём второй вариант этой методики.

Основное отличие данного варианта от предыдущего заключается в том, что вместо объявления объектов класса Sound для каждого звукового файла (по первому варианту):

Dim moveSound As Sound

Dim winSound As Sound

мы объявляем динамические массивы (array) типа Byte для каждого звукового файла (по второму варианту):

Dim array_btSoundBounce() As Byte

Dim array_btSoundExplode() As Byte

Остальные пояснения будут понятны из нового проекта.

Для создания проекта в VS щёлкаем кнопку New Project (или File, New, Project). В панели New Project в окне Project Types выбираем тип проекта Visual Basic, Windows, в окне Templates выделяем шаблон Windows Forms Application, в окне Name записываем любое имя проекта, например, Sounds6 и щёлкаем OK. Создаётся проект, появляется форма Form1 (рис. 6.9) в режиме проектирования.



Рис. 6.9. Форма Form1 в режиме выполнения.

Проектируем (или оставляем по умолчанию) эту форму, как описано в параграфе “Методика проектирования формы”.

Для добавления звукового файла bounce.wav (типа удара) в проект, в меню Project выбираем Add Existing Item, в панели Add Existing Item в окне Files of type устанавливаем All Files, в окне "Look in" находим (например, в папке с загруженным из Интернета файлом) файл и щёлкаем кнопку Add (или дважды щёлкаем по имени файла). Этот файл мы увидим в панели Solution Explorer.

В панели Solution Explorer выделяем имя этого файла, а в панели Properties (для данного файла) в свойстве Build Action (Действие при построении) вместо заданного по умолчанию выбираем значение Embedded Resource (Встроенный ресурс).