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

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

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 по описанной далее методике.

1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28 

Другие книги автора

Все книги автора
Рейтинг@Mail.ru