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

Text
0
Kritiken
Leseprobe
Als gelesen kennzeichnen
Wie Sie das Buch nach dem Kauf lesen
Schriftart:Kleiner AaGrößer Aa

AddHandler myTimer.Tick, AddressOf TimerEventZoomIn

myTimer.Interval = 10

myTimer.Start()

End Sub

Private Sub TimerEventZoomIn(ByVal myObject As Object, _

ByVal myEventArgs As EventArgs)

If Me.Top > picTop And Me.Width < picWidth Then

Me.Top -= 2

Me.Left -= 2

Me.Width += 4

Me.Height += 4

Else

myTimer.Enabled = False

picState = BallState.NORMAL_BALL

RemoveHandler myTimer.Tick, AddressOf TimerEventZoomIn

End If

End Sub

Public Sub Jump()

If picState = BallState.NORMAL_BALL Then

sign = 1

picState = BallState.JUMPING_BALL

AddHandler myTimer.Tick, AddressOf TimerEventJump

myTimer.Interval = 20

myTimer.Start()

ElseIf picState = BallState.JUMPING_BALL Then

StopJump()

End If

End Sub

Public Sub StopJump()

If picState = BallState.JUMPING_BALL Then

picState = 0

myTimer.Enabled = False

RemoveHandler myTimer.Tick, AddressOf TimerEventJump

Me.Top = picTop

Me.Left = picLeft

Me.Height = picHeight

Me.Width = picWidth

End If

End Sub

Private Sub TimerEventJump(ByVal myObject As Object, _

ByVal myEventArgs As EventArgs)

Me.Height -= sign * 1

Me.Top = picTop + (Me.Height – picHeight) \ 4

If Me.Height = picHeight Or Me.Height <= 3 * picHeight / 4 Then

sign *= -1

End If

End Sub

Public Sub Destroy()

If picState = BallState.JUMPING_BALL Then

StopJump()

End If

picState = BallState.DESTROYING_BALL

AddHandler myTimer.Tick, AddressOf TimerEventDestroy

Me.Top = picTop + 1

Me.Left = picLeft + 1

Me.Width = picWidth – 2

Me.Height = picHeight – 2

myTimer.Interval = 10

myTimer.Start()

End Sub

Private Sub TimerEventDestroy(ByVal myObject As Object, _

ByVal myEventArgs As EventArgs)

If Me.Top > picTop And Me.Width > 0 Then

Me.Top += 2

Me.Left += 2

Me.Width -= 4

Me.Height -= 4

Else

Me.Image = Nothing

Me.Top = picTop

Me.Left = picLeft

Me.Width = picWidth

Me.Height = picHeight

myTimer.Enabled = False

Me.picState = BallState.NO_BALL

Me.picIndex = -1

Me.Tag = ""

RemoveHandler myTimer.Tick, AddressOf TimerEventDestroy

End If

End Sub

Public Sub Reset()

While Me.picState = BallState.DESTROYING_BALL

Application.DoEvents()

End While

If Me.picState = BallState.JUMPING_BALL Then

StopJump()

End If

While Me.picState = BallState.ZOOMING_BALL

Application.DoEvents()

End While

Me.Image = Nothing

Me.picIndex = -1

Me.picState = BallState.NO_BALL

Me.Tag = ""

End Sub

Protected Overrides Sub OnMouseMove(ByVal e As _

System.Windows.Forms.MouseEventArgs)

If picState = BallState.NORMAL_BALL Or _

picState = BallState.JUMPING_BALL Then

Me.Image = Image.FromFile(ImgList(picIndex + 1))

End If

End Sub

Protected Overrides Sub OnMouseLeave( _

ByVal e As System.EventArgs)

If picState = BallState.NORMAL_BALL Or picState = _

BallState.JUMPING_BALL Then

Me.Image = Image.FromFile(ImgList(picIndex))

End If

End Sub

End Class

После этих добавлений (DPaint.vb, mModule.vb, MotionPic.vb, open.ico, save.ico) в панели Solution Explorer должны быть файлы, показанные выше. Дважды щёлкая по имени файла, любой файл можно открыть, изучить и редактировать.

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

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

Imports System.Drawing.Drawing2D

Imports System.Drawing.Text

Imports System.IO

Теперь в классе Form2 нашего проекта записываем следующие переменные и методы.

Листинг 21.12. Переменные и методы.

Dim gr As Graphics

Dim lbrTitle As LinearGradientBrush

Dim lbrBoard As LinearGradientBrush

Dim midPoint As Point

Dim startPoint As PointF

Dim intGradiantStep As Integer = 5

Dim intCurrentGradientShift As Integer = 0

Const colW1 As Integer = 250

Const colW2 As Integer = 150

Const rowH As Integer = 30

Dim AddedPlayer As New Player("", "-1")

Dim ArrPlayer As New ArrayList

Dim intCurrentGradientRow As Integer = 110

Public WriteOnly Property AddPlayer() As Player

Set(ByVal Value As Player)

If Value.PlayerName.Length > 14 Then

Value.PlayerName = _

Value.PlayerName.Substring(0, 14)

End If

AddedPlayer = Value

End Set

End Property

Public Sub drawTable()

Me.BackgroundImage = Nothing

Me.BackColor = Color.Moccasin

Application.DoEvents()

Dim g As Graphics = CreateGraphics()

Dim tpen1 As New Pen(Color.Red, 1)

Dim tpen2 As New Pen(Color.Black, 1)

Dim P1 As New Point(2, 80)

Dim P2 As New Point(400, 80)

For i As Integer = 0 To 11

g.DrawLine(tpen1, P1, P2)

P1.Y += 1

P2.Y += 1

g.DrawLine(tpen2, P1, P2)

P1.Y += rowH – 1

P2.Y += rowH – 1

Next

P1.Y = 80

P2.X = P1.X

P2.Y -= rowH

g.DrawLine(tpen2, P1, P2)

P1.X += 1

P2.X += 1

g.DrawLine(tpen1, P1, P2)

P1.X += colW1

P2.X += colW1

g.DrawLine(tpen2, P1, P2)

P1.X += 1

P2.X += 1

g.DrawLine(tpen1, P1, P2)

P1.X += colW2 – 3

P2.X += colW2 – 3

g.DrawLine(tpen1, P1, P2)

P1.X += 1

P2.X += 1

g.DrawLine(tpen2, P1, P2)

SaveScore()

LoadScore()

Timer1.Enabled = True

Timer2.Enabled = True

End Sub

Public Sub LoadScore()

If Not File.Exists("Score.dat") Then

GoTo newScore

End If

Dim FSR As New StreamReader("Score.dat")

Dim s As String

s = FSR.ReadLine

If Trim(s) <> "#Assignment Line#" Then

FSR.Close()

GoTo newScore

End If

For i As Integer = 0 To 9

s = FSR.ReadLine

Dim PlayerName As String = s.Split(CChar(";"))(0)

Dim PlayerScore As String = s.Split(CChar(";"))(1)

ArrPlayer.Add(New Player(PlayerName, PlayerScore))

Next

FSR.Close()

Exit Sub

newScore:

ArrPlayer.Add(New Player("AAA", "5000"))

ArrPlayer.Add(New Player("AAA", "4500"))

ArrPlayer.Add(New Player("AAA", "4000"))

ArrPlayer.Add(New Player("AAA", "3500"))

ArrPlayer.Add(New Player("AAA", "3000"))

ArrPlayer.Add(New Player("AAA", "2500"))

ArrPlayer.Add(New Player("AAA", "2000"))

ArrPlayer.Add(New Player("AAA", "1500"))

ArrPlayer.Add(New Player("AAA", "1000"))

ArrPlayer.Add(New Player("AAA", "500"))

End Sub

Public Sub SaveScore()

LoadScore()

For i As Integer = 0 To 9

If CDbl(AddedPlayer.PlayerScore) >= _

CDbl(CType(ArrPlayer(i), Player).PlayerScore) Then

ArrPlayer.Insert(i, AddedPlayer)

Exit For

End If

Next

Dim FSW As New StreamWriter("Score.dat")

Dim s As String = "#Assignment Line#"

s += Chr(13) + Chr(10)

For i As Integer = 0 To 9

s += CType(ArrPlayer(i), Player).PlayerName + ";" + _

CType(ArrPlayer(i), Player).PlayerScore

s += Chr(13) + Chr(10)

Next

FSW.Write(s)

FSW.Close()

End Sub

Public Sub PlashScreen()

Me.BackgroundImage = Image.FromFile("GameOver.gif")

Application.DoEvents()

Threading.Thread.Sleep(2000)

End Sub

Ниже формы Form2 дважды щёлкаем по значку первого таймера Timer. Появляется шаблон метода, который после записи нашего кода принимает следующий вид.

Листинг 21.13. Метод-обработчик события Tick.

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

ByVal e As System.EventArgs) Handles Timer1.Tick

gr = CreateGraphics()

midPoint = New Point(Me.Width \ 2, 10)

Dim strText As String = "Score Board"

Dim fnt As New Font("Microsoft Sans Serif", 30, _

FontStyle.Bold, GraphicsUnit.Point)

Dim strSize As New SizeF(gr.MeasureString(strText, fnt))

Dim ptfGradientStart As New _

PointF(intCurrentGradientShift, 0)

Dim ptfGradientEnd As New PointF(0, intCurrentGradientRow)

lbrTitle = New LinearGradientBrush(ptfGradientStart, _

ptfGradientEnd, Color.SteelBlue, Color.Brown)

startPoint = New PointF(midPoint.X – _

CInt(strSize.Width / 2), midPoint.Y)

gr.DrawString(strText, fnt, lbrTitle, startPoint)

ptfGradientStart = New PointF(0, intCurrentGradientShift)

ptfGradientEnd = New PointF(intCurrentGradientRow, 0)

lbrTitle = New LinearGradientBrush(ptfGradientEnd, _

ptfGradientStart, Color.MediumSlateBlue, _

Color.GhostWhite)

gr.DrawString(strText, fnt, lbrTitle, startPoint.X – 2, _

startPoint.Y + 2)

intCurrentGradientShift += intGradiantStep

If intCurrentGradientShift = 400 Then

intGradiantStep = -5

ElseIf intCurrentGradientShift = -400 Then

intGradiantStep = 5

End If

End Sub

Ниже формы Form2 дважды щёлкаем по значку второго таймера Timer. Появляется шаблон метода, который после записи нашего кода принимает следующий вид.

Листинг 21.14. Метод-обработчик события Tick.

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

ByVal e As System.EventArgs) Handles Timer2.Tick

'showScore()

Dim g As Graphics = CreateGraphics()

Dim fnt As New Font("Courier New", 20, FontStyle.Bold, _

 

GraphicsUnit.Point)

Dim startPoint As PointF = New PointF(20, 80)

Dim nextPoint As PointF = _

New PointF(startPoint.X + colW1, 80)

Dim ptfGradientStart As New PointF(intCurrentGradientRow, _

startPoint.X)

Dim ptfGradientEnd As New PointF(nextPoint.Y, _

intCurrentGradientRow)

lbrBoard = New LinearGradientBrush(ptfGradientStart, _

ptfGradientEnd, Color.GreenYellow, Color.SlateGray)

Dim PlayerNames As String = "Name" + Chr(13) + Chr(10)

Dim PlayerScores As String = "Score" + Chr(13) + Chr(10)

For i As Integer = 0 To 9

PlayerNames += CType(ArrPlayer(i), Player).PlayerName _

+ Chr(13) + Chr(10)

PlayerScores += CType(ArrPlayer(i), Player).PlayerScore _

+ Chr(13) + Chr(10)

Next

g.DrawString(PlayerNames, fnt, lbrBoard, startPoint)

g.DrawString(PlayerScores, fnt, lbrBoard, nextPoint)

intCurrentGradientRow += intGradiantStep

End Sub

В случае необходимости, методика добавления в проект звукового сигнала Beep (по-русски: Бип) описана ранее.

21.5. Запуск игры

Строим и запускаем программу на выполнение обычным образом:

Build, Build Selection; Debug, Start Without Debugging.

В ответ Visual Studio выводит показанную выше форму, на которой в отдельных квадратах сетки, например, 9 x 9 сначала произвольным образом (при помощи генератора случайных чисел – г.с.ч. класса Random) искусственный интеллект выводит определённое количество, в данной игре 3, разноцветных объекта, например, 3 больших мяча, которые игрок может перемещать при помощи мыши, и 3 маленьких разноцветных мяча, которые размещает искусственный интеллект, чтобы помешать игроку построить прямую линию из мячей (так как в клетку с маленьким мячом большой мяч уже нельзя разместить).

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

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

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

Часть X. Методология программирования искусственного интеллекта в ролевых сюжетных играх

Глава 22. Методика программирования искусственного интеллекта в сюжетных играх на примере сюжета о пещерных людях Адаме и Еве

22.1. Общие сведения

Опишем методику проектирования и программирования типичной и распространённой ролевой (Role-playing game – RPG) сюжетной игры и использованием искусственного интеллекта, когда игрок в роли пещерного человека Адама собирает на земле горящие факелы для Евы (чтобы согреть её в пещере).

Данную игру мы будем разрабатывать, следуя проекту в заархивированном виде CaveManHank.zip (Пещерный человек Хэнк) автора Ivo Salmre от 27.6.2002 с сайта gotdotnet.com для устаревшей версии Visual Studio, причём, для карманного компьютера (КПК), но с нашими усовершенствованиями для современной версии Visual Studio, причём для настольного компьютера или планшета.

В панели Solution Explorer (нашего будущего проекта) или в папке с именем проекта дважды щёлкаем по имени графического файла Hank_FacingForward1.bmp (загруженного, например, из Интернета) для изображения пещерного мужчины с именем Хэнк (у нас он будет зваться, как Адам). Появляется собственный графический редактор Visual Studio с изображением этого мужчины, причём инструментами этого редактора можно редактировать это изображение (рис. 22.1) применительно к нашим задачам.

Аналогично в панели Solution Explorer дважды щёлкаем по имени графического файла Jane_FacingForward1a.bmp для изображения пещерной женщины с именем Джейн (у нас она будет зваться, как Ева). Появляется редактор Visual Studio с изображением этой женщины (рис. 22.2). Аналогично можно открыть и редактировать остальные графические файлы проекта.




Рис. 22.1. Пещерный мужчина Адам. Рис. 22.2. Пещерная женщина Ева.

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

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

На среднем слое находятся статические изображения, которые не перемещаются (в данной игре – это настилы и лестницы). Они не должны рисоваться каждый раз от кадра к кадру, когда изображение обновляется; они изменяют состояние только при переходе от одного уровня (level) игры к другому.

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

Другие пояснения этой игры можно найти (если необходимо) в книгах с сайта ZharkovPress.ru.

22.2. Правила игры

1. После запуска игры на экране появляется форма с пользовательским интерфейсом игры (рис. 22.3).



Рис. 22.3. Начало игры.

Слева в верхней части экрана мы видим индикатор энергии Адама, которая уменьшается по мере течения времени.

Правее находятся надпись “Очки: 0” и Бонус в виде начального времени, которое стремительно уменьшается.

Ниже расположен рисунок, на котором Ева кричит Адаму: “Bring me fire!!!” (Принеси мне огонь).

Левее находится рисунок Адама с озабоченным видом.

Ниже мы видим указание игроку, управляющему изображением Адама: “Соберите факелы и принесите Еве”.

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

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

Очки засчитываются за каждый собранный факел данного уровня, за оставшееся время бонуса и за энергию игрока, оставшуюся в конце каждого уровня.

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

Звучит мелодия начала игры.

2. Через несколько секунд поясняющая надпись “Соберите факелы и принесите Еве” исчезает (чтобы не заслонять игровое поле).

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

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



Рис. 22.4. Игроку начислено 200 очков.

4. К другим факелам подойти не так просто, так как мешают настилы. И Адам может пройти к факелам только через промежутки в настилах и по лестницам.

Щёлкаем указателем мыши в промежутках между настилами и по лестницам, указывая Адаму путь к факелам.

Мы взяли ещё один факел и получили 500 очков (рис. 22.5).



Рис. 22.5. Игроку начислено 500 очков.

5. Напомним, что, чтобы Адам подпрыгнул от падающих валунов (которые извергают вулканы) или от пролетающей огромной птицы эпохи динозавров, следует нажать клавишу пробела.

Мы не успели нажать клавишу пробела, Адам не подпрыгнул и был сбит валуном. Энергия у Адама закончилась (на индикаторе вверху), и игра тоже закончилась (рис. 22.6).

Звучит мелодия окончания игры.

6. Для начала новой игры следует нажать кнопку “Новая игра”.

7. Если нам нужна справка о правилах игры, то щёлкаем кнопку Помощь. Последовательно появляются несколько библиотечных панелей MsgBox с записанными нами в программу текстами (рис. 22.7 – 22.9).

8. Если в игре участвует несколько человек, то победителем считается тот, кто набрал большее количество очков.

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

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



Рис. 22.6. Игра закончена.



Рис. 22.7. Первая часть справки.



Рис. 22.8. Вторая часть справки.



Рис. 22.9. Третья часть справки.

22.3. Создание проекта


Создаём проект по обычной схеме: в VS в панели New Project в окне Project types выбираем тип проекта Visual Basic, Windows, в окне Templates выделяем шаблон Windows Forms Application, в окне Name записываем имя проекта HankTheCaveMan и щёлкаем OK.

Так как, в отличие от указанного выше оригинала, в нашем проекте при загрузке графических файлов имя проекта будет определяться в программе, то сейчас в окне Name можно записать любое имя. Создаётся проект, появляется форма Form1 в режиме проектирования (рис. 22.10). Оставляем по умолчанию или проектируем форму, как подробно описано в параграфе “Методика проектирования формы”. Например, в панели Properties (для Form1) в свойстве Font увеличиваем размер шрифта до 10. За маркеры увеличиваем размеры формы таким образом, чтобы в свойстве Size были, например, такие величины: 405; 456.

С панели инструментов Toolbox переносим в нижнюю часть формы элемент управления типа окна текста TextBox.

Ниже размещаем кнопку Button с номером 1. В панели Properties (для этого элемента) в свойстве Text записываем “Новая игра”.

Правее размещаем кнопку Button. В панели Properties (для этого элемента) в свойстве Name записываем ButtonNextLevel, а в свойстве Text записываем Уровень.

Правее размещаем кнопку Button. В панели Properties (для этого элемента) в свойстве Name записываем buttonInstructions, а в свойстве Text записываем Помощь.

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

Переносим таймер Timer. В панели Properties (для этого невидимого на форме компонента) в свойстве Name записываем timerGame, в свойстве Enabled выбираем True, а свойству Interval задаём значение 40 миллисекунд, что соответствует 25 кадрам в секунду по стандарту телевещания России.

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

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

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

 

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





Рис. 22.10. Форма Form1 в режиме проектирования. Рис. 22.11. Панель Solution Explorer.

22.4. Код и запуск программы


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

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

В классе Form1 нашего проекта записываем следующие переменные и методы.

Листинг 22.1. Переменные и методы.

'–

'Offsets on form where we should draw the playfield

'–

Const GAME_SCREEN_DX = 2

Const GAME_SCREEN_DY = 1

'Current playfield

Private m_playfieldManager As PlayFieldManager

'Gfx object of the form that we will render the playfield to

Dim m_myFormsGraphics As Graphics

'–

'Does the things we need to get get a round running

'–

Sub InitializeNewLevel()

'Add a game event handler to get updates on the game

AddHandler m_playfieldManager.GameStateChanged, _

AddressOf GameEventOccured

'Start the game

timerGame.Enabled = True

ButtonNextLevel.Visible = False

'–

'Give the text-box focus so we can get keyboard events

'–

TextBox1.Focus()

End Sub

'–

'Starts a new game

'–

Sub StartGame()

'Мелодия начала игры с ожиданием окончания мелодии:

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

' AudioPlayMode.WaitToComplete)

'Мелодия начала игры без ожидания её окончания:

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

'–

'Create Graphics object and cache it

'–

If (m_myFormsGraphics Is Nothing) Then

m_myFormsGraphics = Me.CreateGraphics

End If

'–

'Create the playfield level we want to start on

'–

m_playfieldManager = New Playfield_Level2()

'–

'Start the level running

'–

InitializeNewLevel()

End Sub

Sub PictureBoxPlayField_MouseDown( _

ByVal sender As System.Object, _

ByVal e As System.Windows.Forms.MouseEventArgs)

'If Hank's around, give him a new destination

'If Not (m_HankTheWonderCaveMan Is Nothing) Then

If Not (m_playfieldManager Is Nothing) Then

m_playfieldManager.HankTheWonderCaveman. _

setHanksDestination(e.X, e.Y)

End If

End Sub

'–

'This event-sink is to get called when a game event occurs

'–

Sub GameEventOccured(ByVal gameUpdateMessage As _

PlayFieldManager.GameUpdate)

'The level was completed succesfully

If (gameUpdateMessage = PlayFieldManager.GameUpdate. _

levelSuccesfullyCompleted) Then

ButtonNextLevel.Visible = True

End If

End Sub

'Загружаем в проект файлы изображений по такой схеме:

'Создаём объект myAssembly класса Assembly и присваиваем ему

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

Public myAssembly As Assembly = Assembly.GetExecutingAssembly()

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

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

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

'Version, Culture, PublicKeyToken:

Public myAssemblyName As AssemblyName = myAssembly.GetName()

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

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

Public myName_of_project As String = myAssemblyName.Name

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

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

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

ByVal e As System.EventArgs) Handles MyBase.Load

Me.Visible = False

'–

'Load and cache the global object we need

'–

g_InitializeGlobals()

Me.Visible = True

'–

'Place the textbox off the screen

'–

TextBox1.Width = 4

TextBox1.Multiline = True

TextBox1.Left = -20

'Start the game

StartGame()

End Sub

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

Листинг 22.3. Метод для закрытия формы.

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

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

Handles MyBase.FormClosing

' '–

' 'Cleanup

' '–

'–

'Free up the form based objects

'–

m_playfieldManager = Nothing

If Not (m_myFormsGraphics Is Nothing) Then

m_myFormsGraphics.Dispose()

m_myFormsGraphics = Nothing

End If

'–

'Free up all the global objects

'–

g_DisposeAndFreeGlobals()

End Sub

На форме дважды щёлкаем по кнопке Button с номером 1 и текстом “Новая игра” (или в панели Properties, для этого элемента, на вкладке Events дважды щёлкаем по имени соответствующего события). Появившийся шаблон после записи нашего кода принимает следующий вид.

Листинг 22.4. Метод-обработчик щелчка кнопки.

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

ByVal e As System.EventArgs) Handles Button2.Click

StartGame()

End Sub

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

Листинг 22.5. Метод-обработчик щелчка кнопки.

Private Sub ButtonNextLevel_Click( _

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

Handles ButtonNextLevel.Click

'–

'Starts a new level of play

'–

'Ask the current level what it's next level is

m_playfieldManager = m_playfieldManager.GetNextLevel()

'Start the level running

InitializeNewLevel()

End Sub

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

Листинг 22.6. Метод-обработчик щелчка кнопки.

Private Sub buttonInstructions_Click( _

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

Handles buttonInstructions.Click

MsgBox("Правила игры: Соберите все факелы и " + _

"принесите их Еве. Очки засчитываются " + _

"за каждый факел данного уровня, " + _

"за оставшееся время бонуса и за энергию игрока, " _

+ "оставшуюся в конце каждого уровня.")

MsgBox("Адам потеряет энергию, если он будет поражён " + _

"валуном или птицей. Адам будет подскакивать, " + _

"чтобы не быть поражённым этими объектами. " + _

"Адам также потеряет энергию, " + _

"если он упадёт с большой высоты.")

MsgBox("Управление Адамом состоит в том, " + _

"чтобы щёлкать по экрану. После каждого щелчка " + _

"появляется пунктирная линия, показывающая, " + _

"куда пойдёт Адам. Чтобы Адам подпрыгнул " + _

"от валуна или птицы, " + _

"следует нажать клавишу пробела.")

'Bring the focus back to the textbox

'so it gets the keyboard input

TextBox1.Focus()

End Sub

В панели Properties, для элемента TextBox, на вкладке Events дважды щёлкаем по имени события KeyDown. Появившийся шаблон после записи нашего кода принимает следующий вид.

Листинг 22.7. Метод-обработчик события.

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

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

Handles TextBox1.KeyDown

'–

'This textbox is a way to get the keyboard input

'for the game becuase:

' 1. When you hit the "START" button, it get's the focus

'(so the form no longer gets keydown events)

' 2. The Start Button does not get key-down events

'–

If (m_playfieldManager Is Nothing) Then

Return

End If

Dim i As Integer

i = e.KeyValue

Const PocketPC_BUTTON_PUSHED = 134

Const Keyboard_SPACE_PUSHED = 32

Const PocketPC_UP = 38

Const PocketPC_DOWN = 40

Const PocketPC_LEFT = 37

Const PocketPC_RIGHT = 39

Dim hank As HankTheWonderCaveman = _

m_playfieldManager.HankTheWonderCaveman

Const D_MOVEMENT = 14

Const D_MOVEMENT_UP = 70

If (i = PocketPC_BUTTON_PUSHED) Or _

(i = Keyboard_SPACE_PUSHED) Then

hank.MakeHankJump()

e.Handled = True

ElseIf (i = PocketPC_RIGHT) Then

hank.NudgeHanksDirection(D_MOVEMENT, 0)

ElseIf (i = PocketPC_LEFT) Then

hank.NudgeHanksDirection(-D_MOVEMENT, 0)

ElseIf (i = PocketPC_UP) Then

hank.NudgeHanksDirection(0, -D_MOVEMENT_UP)

ElseIf (i = PocketPC_DOWN) Then

hank.NudgeHanksDirection(0, D_MOVEMENT)

End If

TextBox1.Text = ""

End Sub

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

Листинг 22.8. Метод, вызываемый таймером через каждый интервал Interval времени.

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

ByVal e As System.EventArgs) Handles timerGame.Tick

' '–

' 'This timer is the heartbeat if the game.

' 'Every time it gets called we

' 'allow all of the game characters to move,

' 'we check for collisions beween objects,

' 'and we render the board to the screen.

' '–

'–

'If we are not running, exit the sub

'–

If (m_playfieldManager Is Nothing) Then Exit Sub

'–

'Give all the characters a chance to move

'–

m_playfieldManager.MoveCharactersOnPlayfield()

'–

'Render the playfield and all of the objects onto the form

'–

m_myFormsGraphics.DrawImage(m_playfieldManager. _

RenderPlayField(), GAME_SCREEN_DX, GAME_SCREEN_DY)

End Sub

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

Листинг 22.9. Метод-обработчик события.

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

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

Handles MyBase.MouseDown

'Make sure there is a game we are playing

If Not (m_playfieldManager Is Nothing) Then

If e.Button = MouseButtons.Right Then

m_playfieldManager.HankTheWonderCaveman. _

MakeHankJump()

Else

'–

'Figure out where on the game playfield we clicked

'–

Dim x_GAME As Integer

Dim y_GAME As Integer

x_GAME = e.X – GAME_SCREEN_DX

y_GAME = e.Y – GAME_SCREEN_DY

'Let Hank figure out what to do

m_playfieldManager.HankTheWonderCaveman. _

setHanksDestination(x_GAME, y_GAME)

End If

End If

End Sub

Мы закончили написание программы в главный класс Form1 (для формы Form1 с пользовательским интерфейсом игры).

Теперь в наш проект добавляем новые файлы (для программирования соответствующих игровых действий). Добавить в проект файл можно по двум вариантам.

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

Sie haben die kostenlose Leseprobe beendet. Möchten Sie mehr lesen?

Weitere Bücher von diesem Autor