Читать книгу: «Справочник Жаркова по проектированию и программированию искусственного интеллекта. Том 4: Программирование на Visual Basic искусственного интеллекта», страница 6

Шрифт:

5.5. Добавление новых объектов

Продолжаем усложнять игру за счёт добавления в неё новых объектов в виде продуктов питания, например, помидоров (tomatoes) в виде файла tomato.gif, рис. 5.6.


Рис. 5.6.

Помидор.

В начале игры несколько i-х помидоров в виде массива tomatoes[i] должны появиться в верхней части экрана в качестве мишеней (рис. 5.7), которые должны исчезать после попадания в них летающего сыра (рис. 5.8).

Попадание сыра в помидор определяется уже применяемым выше методом IntersectWith.

Исчезновение помидоров выполняется при помощи свойства visible, которому присваивается логическое значение False (в коде: tomatoes(i).visible = False).

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

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

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

Рис. 5.7. Помидоры – мишени.



Рис. 5.8. Помидоры исчезают после попадания в них сыра.

Для программной реализации рисования и уничтожения помидоров после попадания в них сыра, в классе Form1 нашего проекта записываем следующий код.

Листинг 5.4. Переменные и методы для помидоров (tomatoes).

'Объявляем объект класса System.Drawing.Image для продукта:

Dim tomatoImage As Image

'Position and state of tomato

Structure tomato

Public rectangle As Rectangle

Public visible As Boolean

End Structure

' Spacing between tomatoes. Set once for the game

Dim tomatoSpacing As Integer = 4

' Height at which the tomatoes are drawn. Will change

' as the game progresses. Starts at the top.

Dim tomatoDrawHeight As Integer = 4

' The number of tomatoes on the screen. Set at the start

' of the game by initialiseTomatoes.

Dim noOfTomatoes As Integer

' Positions of the tomato targets.

Dim tomatoes() As tomato

' called once to set up all the tomatoes.

Sub initialiseTomatoes()

noOfTomatoes = (Me.ClientSize.Width – tomatoSpacing) / _

(tomatoImage.Width + tomatoSpacing)

' create an array to hold the tomato positions

ReDim tomatoes(noOfTomatoes)

' x coordinate of each potato

Dim tomatoX As Integer = tomatoSpacing / 2

Dim i As Integer

For i = 0 To tomatoes.Length – 1

tomatoes(i).rectangle = _

New Rectangle(tomatoX, tomatoDrawHeight, _

tomatoImage.Width, tomatoImage.Height)

tomatoX = tomatoX + tomatoImage.Width + tomatoSpacing

Next

End Sub

' Called to place a row of tomatoes.

Sub placeTomatoes()

Dim i As Integer

For i = 0 To tomatoes.Length – 1

tomatoes(i).rectangle.Y = tomatoDrawHeight

tomatoes(i).visible = True

Next

End Sub

Приведённый выше код в теле метода Form1_Paint заменяем на тот, который дан на следующем листинге.

Листинг 5.5. Метод для рисования изображения.

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

ByVal e As System.Windows.Forms.PaintEventArgs) _

Handles MyBase.Paint

'Если необходимо, создаём новый буфер:

If (backBuffer Is Nothing) Then

backBuffer = New Bitmap(Me.ClientSize.Width, _

Me.ClientSize.Height)

End If

'Создаём объект класса Graphics из буфера:

Using g As Graphics = Graphics.FromImage(backBuffer)

'Очищаем форму:

g.Clear(Color.White)

'Рисуем изображение в буфере backBuffer:

g.DrawImage(cheeseImage, cx, cy)

g.DrawImage(breadImage, bx, by)

Dim i As Integer

For i = 0 To tomatoes.Length – 1

If (tomatoes(i).visible) Then

g.DrawImage(tomatoImage, _

tomatoes(i).rectangle.X, _

tomatoes(i).rectangle.Y)

End If

Next

End Using

'Рисуем изображение на форме Form1:

e.Graphics.DrawImage(backBuffer, 0, 0)

End Sub

Добавление новых объектов в игру соответственно усложняет код. В панели Properties (для Form1) на вкладке Events дважды щёлкаем по имени события Load. Появившийся шаблон метода Form1_Load после записи нашего кода принимает следующий вид.

Листинг 5.6. Метод для рисования изображения.

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

ByVal e As System.EventArgs) Handles MyBase.Load

'Загружаем в объекты класса System.Drawing.Image

'добавленные в проект файлы изображения заданного формата

'при помощи потока встроенного ресурса (ResourceStream):

cheeseImage = _

New Bitmap(myAssembly.GetManifestResourceStream( _

myName_of_project + "." + "cheese.JPG"))

breadImage = _

New Bitmap(myAssembly.GetManifestResourceStream( _

myName_of_project + "." + "bread.JPG"))

'Инициализируем прямоугольники, описанные вокруг объектов:

cheeseRectangle = New Rectangle(cx, cy, _

cheeseImage.Width, cheeseImage.Height)

breadRectangle = New Rectangle(bx, by, _

breadImage.Width, breadImage.Height)

'Загружаем помидор:

tomatoImage = _

New Bitmap(myAssembly.GetManifestResourceStream( _

myName_of_project + "." + "tomato.gif"))

'Инициализируем массив помидоров и прямоугольников:

initialiseTomatoes()

'Размещаем помидоры в верхней части экрана:

placeTomatoes()

'Включаем таймер:

Timer1.Enabled = True

End Sub

И наконец, вместо приведённого выше метода updatePositions записываем следующий метод, дополненный новым кодом для изменения координат, обнаружения столкновений объектов и уничтожения помидоров.

Листинг 5.7. Метод для изменения координат и обнаружения столкновения объектов.

Sub updatePositions()

If (goingRight) Then

cx += xSpeed

Else

cx -= xSpeed

End If

If ((cx + cheeseImage.Width) >= Me.ClientSize.Width) Then

goingRight = False

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

Beep()

End If

If (cx <= 0) Then

goingRight = True

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

Beep()

End If

If (goingDown) Then

cy += ySpeed

Else

cy -= ySpeed

End If

If ((cy + cheeseImage.Height) >= Me.ClientSize.Height) Then

goingDown = False

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

Beep()

End If

If (cy <= 0) Then

goingDown = True

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

Beep()

End If

'Задаём прямоугольникам координаты объектов:

cheeseRectangle.X = cx

cheeseRectangle.Y = cy

breadRectangle.X = bx

breadRectangle.Y = by

'Проверяем столкновение объектов с учётом помидоров:

If (goingDown) Then

' only bounce if the cheese is going down

If (cheeseRectangle.IntersectsWith(breadRectangle)) Then

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

Beep()

' we have a collision

Dim rightIn As Boolean = breadRectangle.Contains( _

cheeseRectangle.Right, _

cheeseRectangle.Bottom)

Dim leftIn As Boolean = breadRectangle.Contains( _

cheeseRectangle.Left, _

cheeseRectangle.Bottom)

' now deal with the bounce

If (rightIn And leftIn) Then

' bounce up

goingDown = False

Else

' bounce up

goingDown = False

' now sort out horizontal bounce

If (rightIn) Then

goingRight = False

End If

If (leftIn) Then

goingRight = True

End If

End If

End If

Else

' only destroy tomatoes of the cheese is going up

Dim i As Integer

For i = 0 To tomatoes.Length – 1

If (Not tomatoes(i).visible) Then

Continue For

End If

If (cheeseRectangle.IntersectsWith( _

tomatoes(i).rectangle)) Then

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

Beep()

' hide the tomato

tomatoes(i).visible = False

' bounce down

goingDown = True

' only destroy one at a time

'Чтобы помидоры уничтожались не по два,

'а по одному помидору: Exit For:

Exit For

End If

Next

End If

End Sub 'Конец метода updatePositions.

В режиме выполнения (Build, Build Selection; Debug, Start Without Debugging) несколько i-х помидоров появляются в верхней части экрана в качестве мишеней (рис. 5.7), которые исчезают после попадания в них летающего сыра (рис. 5.8).

Управляя при помощи кнопок Button и мыши перемещением батона хлеба, мы можем отражать сыр вверх таким образом, чтобы уничтожить как можно больше помидоров за меньшее время, набирая при этом очки.

К разработке методики подсчёта очков в игре мы и приступаем.

5.6. Методика подсчёта очков в игре


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

Методика подсчёта очков (score) в игре подразумевает наличие в программе счётчика (scorer) очков и вывода очков на экран (например, методом DrawString) в строке:

g.DrawString(messageString, messageFont, messageBrush,

messageRectangle)

Видно, что в этом методе DrawString мы дожны определить параметры в виде шрифта messageFont, кисти messageBrush и зарезервированного прятоугольника для записи очков messageRectangle, причём в этот прямоугольник летающие объекты не должны залетать. На рис. 5.9 мы получили 20 очков за 2 сбитых помидора, а на 5.10 – 50 очков за 5 сбитых помидоров.

За каждый сбитый помидор мы можем начислить игроку любое количество очков, например, 10 очков в строке:

scoreValue = scoreValue + 10

Новые очки сразу же выводятся на экран, информируя игрока.

Приступим к программной реализации методики подсчёта очков в игре в нашем базовом учебном проекте.

Сначала мы должны опустить ряд помидоров пониже, чтобы освободить место вверху для записи очков, поэтому вместо 4 записываем ординату, равную, например, 20:

Dim tomatoDrawHeight As Integer = 20

В любом месте класса Form1 добавляем новые переменные для счётчика очков.



Рис. 5.9. Получили 20 очков за 2 сбитых помидора.



Рис. 5.10. Получили 50 очков.

Листинг 5.8. Новые переменные.

' Font for score messages.

Dim messageFont As Font = Nothing

' Rectangle for score display.

Dim messageRectangle As Rectangle

' Height of the score panel.

Dim scoreHeight As Integer = 20 '= заданной выше tomatoDrawHeight.

' Brush used to draw the messages.

Dim messageBrush As SolidBrush

' The string which is drawn as the user message.

Dim messageString As String = "Очки: 0"

' Score in a game.

Dim scoreValue As Integer = 0

Приведённый выше код в теле метода Form1_Paint заменяем на тот, который дан на следующем листинге.

Листинг 5.9. Метод для рисования изображения.

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

ByVal e As System.Windows.Forms.PaintEventArgs) _

Handles MyBase.Paint

'Если буфер пустой, создаём новый буфер:

If (backBuffer Is Nothing) Then

backBuffer = New Bitmap(Me.ClientSize.Width, _

Me.ClientSize.Height)

End If

'Создаём объект класса Graphics из буфера:

Using g As Graphics = Graphics.FromImage(backBuffer)

'Очищаем форму:

g.Clear(Color.White)

'Рисуем изображения объектов в буфере backBuffer:

g.DrawImage(cheeseImage, cx, cy)

g.DrawImage(breadImage, bx, by)

Dim i As Integer

For i = 0 To tomatoes.Length – 1

If (tomatoes(i).visible) Then

g.DrawImage(tomatoImage, _

tomatoes(i).rectangle.X, _

tomatoes(i).rectangle.Y)

End If

Next

'Записываем очки игрока:

g.DrawString(messageString, messageFont, _

messageBrush, messageRectangle)

End Using

'Рисуем изображение на форме Form1:

e.Graphics.DrawImage(backBuffer, 0, 0)

End Sub

Приведённый выше код в теле метода Form1_Load (для загрузки файлов изображений игровых объектов) заменяем на тот, который дан на следующем листинге.

Листинг 5.10. Метод для загрузки файлов изображений.

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

ByVal e As System.EventArgs) Handles MyBase.Load

'Загружаем в объекты класса System.Drawing.Image

'добавленные в проект файлы изображений заданного формата

'при помощи потока встроенного ресурса (ResourceStream):

cheeseImage = _

New Bitmap(myAssembly.GetManifestResourceStream( _

myName_of_project + "." + "cheese.JPG"))

breadImage = _

New Bitmap(myAssembly.GetManifestResourceStream( _

myName_of_project + "." + "bread.JPG"))

'Инициализируем прямоугольники, описанные вокруг объектов:

cheeseRectangle = New Rectangle(cx, cy, _

cheeseImage.Width, cheeseImage.Height)

breadRectangle = New Rectangle(bx, by, _

breadImage.Width, breadImage.Height)

'Загружаем файл изображения нового объекта:

tomatoImage = _

New Bitmap(myAssembly.GetManifestResourceStream( _

myName_of_project + "." + "tomato.gif"))

'Инициализируем массив новых объектов и прямоугольников,

'описанные вокруг этих объектов:

initialiseTomatoes()

'Размещаем новые объекты в верхней части экрана:

placeTomatoes()

'Создаём и инициализируем шрифт для записи очков:

messageFont = New Font(FontFamily.GenericSansSerif, 10, _

FontStyle.Regular)

'Резервируем прямоугольник на экране для записи очков:

messageRectangle = New Rectangle(0, 0, _

Me.ClientSize.Width, scoreHeight)

'Задаём цвет кисти для записи очков:

messageBrush = New SolidBrush(Color.Black)

'Включаем таймер:

Timer1.Enabled = True

End Sub

И наконец, вместо приведённого выше метода updatePositions записываем следующий метод, дополненный новым кодом для изменения координат, обнаружения столкновений объектов, уничтожения помидоров и подсчёта очков.

Листинг 5.11. Метод для изменения координат и обнаружения столкновения объектов.

Sub updatePositions()

If (goingRight) Then

cx += xSpeed

Else

cx -= xSpeed

End If

If ((cx + cheeseImage.Width) >= Me.ClientSize.Width) Then

goingRight = False

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

Beep()

End If

If (cx <= 0) Then

goingRight = True

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

Beep()

End If

If (goingDown) Then

cy += ySpeed

Else

cy -= ySpeed

End If

If ((cy + cheeseImage.Height) >= Me.ClientSize.Height) Then

goingDown = False

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

Beep()

End If

If (cy <= 0) Then

goingDown = True

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

Beep()

End If

'Задаём прямоугольникам координаты объектов:

cheeseRectangle.X = cx

cheeseRectangle.Y = cy

breadRectangle.X = bx

breadRectangle.Y = by

' check for collisions.

If (goingDown) Then

' only bounce if the cheese is going down

If (cheeseRectangle.IntersectsWith(breadRectangle)) Then

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

Beep()

' we have a collision

Dim rightIn As Boolean = breadRectangle.Contains( _

cheeseRectangle.Right, _

cheeseRectangle.Bottom)

Dim leftIn As Boolean = breadRectangle.Contains( _

cheeseRectangle.Left, _

cheeseRectangle.Bottom)

' now deal with the bounce

If (rightIn And leftIn) Then

' bounce up

goingDown = False

Else

' bounce up

goingDown = False

' now sort out horizontal bounce

If (rightIn) Then

goingRight = False

End If

If (leftIn) Then

goingRight = True

End If

End If

End If

Else

' only destroy tomatoes of the cheese is going up

Dim i As Integer

For i = 0 To tomatoes.Length – 1

If (Not tomatoes(i).visible) Then

Continue For

End If

If (cheeseRectangle.IntersectsWith( _

tomatoes(i).rectangle)) Then

'В момент столкновения подаем сигнал Beep:

Beep()

' hide the tomato

tomatoes(i).visible = False

' bounce down

goingDown = True

' update the score

scoreValue = scoreValue + 10

'Конвертируем очки scoreValue в тип String

'и выводим на экран:

messageString = "Очки: " & _

Convert.ToString(scoreValue)

' only destroy one at a time

'Чтобы помидоры уничтожались не по два,

'а по одному помидору: Exit For:

Exit For

End If

Next

End If

End Sub 'Конец метода updatePositions.

В режиме выполнения (Build, Build Selection; Debug, Start Without Debugging), управляя летающим сыром при помощи батона хлеба, кнопок Button и мыши, мы получили 20 очков за 2 сбитых помидора (рис. 5.9) и 50 очков за 5 сбитых помидоров (рис. 5.10).

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

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

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

6.1. Основные методики звукового сопровождения приложений

Выше мы уже применяли воспроизведение звуковых файлов по упрощённому варианту и звуковой эффект в виде звукового сигнала Beep (по-русски: Бип). Напомним, что этот сигнал появляется, когда выполнение программы дойдёт до строки: Beep(). Записывая эту строку в соответствующих местах программы, мы подаем звуковой сигнал Beep в различные моменты анимации, например, в момент каждого удара объектов о границу (внутри которой перемещаются объекты) или друг о друга.

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

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

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

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

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

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

6.2. Методика воспроизведения звуковых файлов на основе пространства имён My

Сначала для воспроизведения звуков в приложениях и играх для настольных компьютеров, ноутбуков и планшетов мы опишем наиболее популярную методику воспроизведения звуковых файлов на основе пространства имён My (без использования и технологии DirectX, и схемы встроенного (Embedded) ресурса). Приступим к программной реализации этой методики, для общности, в новом проекте.

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



Рис. 6.1.

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

Проектируем (или оставляем по умолчанию) эту форму, как описано в параграфе “Методика проектирования формы”. Например, в панели Properties в свойстве Font можно оставить по умолчанию или установить новый шрифт и его размер (Size). Чтобы изменить заголовок формы, в панели Properties в свойстве Text записываем (или вставляем из буфера обмена: правый щелчок, Paste) текст.

С панели инструментов Toolbox переносим на форму, для примера, две кнопки Button (Sound 1 и Sound 2). В панели Properties в свойстве Text записываем название каждой кнопки Sound&1 и Sound&2 с оператором &, который подчёркивает следующий за ним символ текста, что позволяет нам задействовать кнопку не только мышью, но и, удерживая нажатой клавишу Alt, нажатием клавиши с подчёркнутой буквой английского алфавита или цифрой (например, Alt+1).

На форме в режиме выполнения по умолчанию выделена первая кнопка. Но если мы желаем, чтобы в режиме выполнения на форме была выделена другая кнопка (чтобы нажимать её не только мышью, но и клавишей Enter), то в панели Properties (для Form1) в свойстве AcceptButton выбираем имя этой кнопки.

По варианту 1, для добавления звукового файла drumpad-crash.wav в проект, в меню Project выбираем Add Existing Item, в панели Add Existing Item в окне Files of type устанавливаем All Files, в окне "Look in" находим (в системной папке компьютера C, WINDOWS, Media или в папке с загруженным из Интернета файлом) файл и щёлкаем кнопку Add (или дважды щёлкаем по имени файла). Этот файл мы увидим в панели Solution Explorer. Если мы дважды щёлкнем по этому файлу drumpad-crash.wav, то откроется проигрыватель Windows Media Player, и мы услышим в течение нескольких секунд звучание типа шуршания оркестровых металлических тарелок при воздействии на них металлической метелки.

Аналогично добавляем в проект второй файл drumpad-bass_drum.wav типа удара барабана.

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

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

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

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

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

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

ByVal e As System.EventArgs) Handles MyBase.Load

'Загружаем звуковые файлы формата (.wav)

'по 1-му варианту непосредственно из проекта:

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


'Загружаем звуковые файлы формата (.wav)

'по 2-му варианту из внешней папки:

'My.Computer.Audio.Play( _

'"D:\MyDocs\Sounds\drumpad-bass_drum.wav")

End Sub

Видно, что в строке:

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

мы используем пространство имён My, свойство Computer, свойство Audio и метод Play (рис. 6.2).

Оператор “..\..\” называется relative path – путь относительно (внутри) проекта.



Рис. 6.2. Подсказка с методом Play.

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

Если в приведённый выше шаблон метода Form1_Load мы загрузим подряд два файла, как показано ниже:

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

ByVal e As System.EventArgs) Handles MyBase.Load

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

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

End Sub

то в режиме выполнения мы услышим только второй звуковой файл.

Чтобы мы услышали сначала полностью первый звуковой файл, а затем второй звуковой файл, мы должны в методе Play в качестве второго параметра использовать константу WaitToComplete из перечисления режимов AudioPlayMode, как показано в следующем коде.

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

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

ByVal e As System.EventArgs) Handles MyBase.Load

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

AudioPlayMode.WaitToComplete)

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

End Sub

Подчеркнём следующее. Чтобы все игровые действия прекратились на время исполнения мелодии, мы должны в методе Play в качестве второго параметра использовать уже применённую выше константу WaitToComplete из перечисления режимов AudioPlayMode, как показано в следующем коде.

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

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

ByVal e As System.EventArgs) Handles MyBase.Load

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

AudioPlayMode.WaitToComplete)

End Sub

Чтобы мы услышали непрерывное циклическое (Loop) воспроизведение звукового файла, мы должны в методе Play в качестве второго параметра использовать константу BackgroundLoop из перечисления режимов AudioPlayMode, как показано в следующем коде.

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

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

ByVal e As System.EventArgs) Handles MyBase.Load

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

AudioPlayMode.BackgroundLoop)

End Sub

Чтобы остановить (Stop) воспроизведение звука, необходимо в каком либо методе, например, в обработчике щелчка кнопки записать строку:

My.Computer.Audio.Stop()

Теперь после щелчка кнопки звучание прекратится.

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



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

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

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

Напомним, что добавлять в проект все файлы можно как по одному, так и все сразу (после их выделения или только одной мышью, или мышью с нажатой клавишей Shift – для выделения всех соседних файлов, или мышью с нажатой клавишей Ctrl – для выделения всех файлов в различных местах).

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

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

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

ByVal e As System.EventArgs) Handles MyBase.Load

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

AudioPlayMode.WaitToComplete)

End Sub

Однако чаще требуется записывать строку типа:

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

не в методе Form1_Load, а в других методах, которые управляют игровыми объектами.

Для примера, покажем, как управлять звуками при помощи двух кнопок Button, которые мы разместили на форме. В режиме проектирования дважды щёлкаем первую кнопку (или в панели Properties для этой выделенной щелчком кнопки на вкладке Events дважды щёлкаем по имени события Click). Появляется файл Form1.vb с шаблоном (обработчика щелчка по этой кнопке), который после записи нашего кода принимает вид следующего метода.

Листинг 6.6. Метод для кнопки.

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

ByVal e As System.EventArgs) Handles Button1.Click

'Загружаем звуковые файлы формата (.wav)

'по 1-му варианту непосредственно из проекта:

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

AudioPlayMode.BackgroundLoop)


'Загружаем звуковые файлы формата (.wav)

'по 2-му варианту из внешней папки:

'My.Computer.Audio.Play( _

'"D:\MyDocs\Sounds\drumpad-bass_drum.wav")

End Sub

В режиме проектирования дважды щёлкаем вторую кнопку (или в панели Properties для этой выделенной щелчком кнопки на вкладке Events дважды щёлкаем по имени события Click). Появляется файл Form1.vb с шаблоном (обработчика щелчка по этой кнопке), который после записи нашего кода принимает вид следующего метода.

Листинг 6.7. Метод для кнопки.

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

ByVal e As System.EventArgs) Handles Button2.Click

'Загружаем звуковые файлы формата (.wav)

'по 1-му варианту непосредственно из проекта:

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

'Загружаем звуковые файлы формата (.wav)

'по 2-му варианту из внешней папки:

'My.Computer.Audio.Play( _

'"D:\MyDocs\Sounds\drumpad-crash.wav")

End Sub

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

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

AudioPlayMode.BackgroundLoop)

мы услышим непрерывное циклическое (Loop) воспроизведение звукового файла drumpad-crash.wav типа шуршания оркестровых металлических тарелок после воздействия на них металлической метелкой. А после каждого нашего щелчка второй кнопки и выполнения кода:

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

мы будем слышать одиночное воспроизведение звукового файла drumpad-bass_drum.wav типа удара по барабану. Нажимая вторую кнопку с различной частотой, мы будем импровизировать и создавать различную мелодию из добавленных в проект двух звуковых файлов.

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

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

Бесплатный фрагмент закончился.

Возрастное ограничение:
12+
Дата выхода на Литрес:
11 февраля 2023
Дата написания:
2022
Объем:
538 стр. 164 иллюстрации
Правообладатель:
Автор
Формат скачивания:
Аудио
Средний рейтинг 4,2 на основе 976 оценок
Текст, доступен аудиоформат
Средний рейтинг 4,7 на основе 1773 оценок
Текст
Средний рейтинг 5 на основе 89 оценок
Черновик
Средний рейтинг 4,9 на основе 383 оценок
Аудио
Средний рейтинг 4,8 на основе 692 оценок
Текст
Средний рейтинг 4,9 на основе 79 оценок
Черновик, доступен аудиоформат
Средний рейтинг 4,7 на основе 158 оценок
Текст
Средний рейтинг 4,9 на основе 87 оценок