Мониторинг обменных курсов валют
18c0693f

Вторая часть – управляем машиной


Если с первой частью все было относительно просто, то про вторую стоит поговорить подробнее. Фактически, нам нужно будет создавать автомобиль, как раньше мы создавали будильник. Не имея программистского опыта, мы попытаемся использовать житейский опыт касательно того, как автомобиль устроен. Причем применительно к задачам проекта. Так, цвет сиденья в этом смысле нам не очень важен. А важно нам управлять скоростью и направлением движения (этим в обычном автомобиле занимаются руль и педали газа и тормоза). А еще важно, чтобы автомобиль чувствовал, «куда он въехал» (газон, ограждение, финиш) и вел себя соответственно (этим мы займемся в третьей части).

Для начала поместим на форму маленький PictureBox. Это ваша машина. Так и назовем его – Машина. Поставим задачу управлять им с клавиатуры как написано в задании на игру:

Направление движения может быть только горизонтальным и вертикальным, наискосок машина не движется. Выбор направления – это клавиши со стрелками. Тормоз – клавиша Ctrl. Газ – клавиша пробела. Щелчок по клавише газа или тормоза увеличивает или уменьшает скорость на какое-то значение.

Загляните в Задание 112. Там мы уже решали задачу движения объекта по форме. Если вы ее не решили, то решите или на худой конец загляните в ответ и разберитесь в нем.

Код второй части. Приведу код, который заведует управлением машиной. Этим кодом нужно дополнить первую часть программы, чтобы получилась работающая версия проекта. Вслед за кодом я привожу пояснения. Из процедур, входящих в первую часть, я здесь перепишу только две:  Form1_Load  и  Кнопка_начинай_сначала_Click.

Dim Цвет_фона As Color = Color.White                                       'Цвет фона при рисовании машины

Dim Исходная_машина As New Bitmap("Машина.BMP")           'Создаем исходное изображение машины

'Определяем 4 рабочих изображения машины:

Dim Машина_налево, Машина_вверх, Машина_направо, Машина_вниз As Bitmap                    

Dim x, y As Short            'Горизонтальная и вертикальная координаты автомобиля


Dim Шаг As Short           'Шаг  численно равен перемещению автомобиля по форме  на каждом такте таймера
Dim Газ As Boolean = False                                'Нажимаем ли мы на газ
Dim Тормоз As Boolean = False                         'Нажимаем ли мы на тормоз
Enum типРуль                                        'Куда едем
    вверх
    влево
    вниз
    вправо
End Enum
Dim Руль As типРуль
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
     '……………здесь расположены уже знакомые нам предыдущие строки процедуры……………
    Создаем_изображения_машины()
    Машина.BackColor = Color.Transparent
    Me.KeyPreview = True                                       'Чтобы машина отзывалась на клавиатуру
    txtВремя.ReadOnly = True
End Sub
Private Sub Кнопка_начинай_сначала_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)  _
Handles Кнопка_начинай_сначала.Click
     '……………здесь расположены уже знакомые нам предыдущие строки процедуры……………
    Ставим_машину_на_старт()
    txtВремя.Focus()
End Sub
Sub Создаем_изображения_машины()
    Создаем_изображение(Машина_налево, RotateFlipType.RotateNoneFlipNone)
    Создаем_изображение(Машина_вверх, RotateFlipType.Rotate90FlipNone)
    Создаем_изображение(Машина_направо, RotateFlipType.Rotate180FlipNone)
    Создаем_изображение(Машина_вниз, RotateFlipType.Rotate270FlipNone)
End Sub
Sub Создаем_изображение(ByRef Автомобиль As Bitmap, ByVal Поворот As RotateFlipType)
    Автомобиль = New Bitmap(Исходная_машина)     'Порождаем новый Bitmap из исходного
    Автомобиль.RotateFlip(Поворот)                            'Поворачиваем его
    Автомобиль.MakeTransparent(Цвет_фона)           'Делаем фон автомобиля прозрачным
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    Изменяем_скорость()
    Выбираем_куда_ехать_и_делаем_шаг()
    Машина.Left = x     : Машина.Top = y                'Передвигаем PictureBox


End Sub
Sub Ставим_машину_на_старт()
    x = X_старта      : y = Y_старта     ' Координаты машины приравниваются координатам точки старта
    Шаг = 0                                           'На старте стоим, а не едем
    Руль = типРуль.влево                   'Это чтобы машина знала, что когда стартуем, нужно ехать влево
    Машина.Image = Машина_налево                        'Ориентируем машину налево
End Sub
Sub Изменяем_скорость()
    If Газ Then Шаг = Шаг + 1
    If Тормоз Then
        Шаг = Шаг – 2                       'Потому, что тормоз действует быстрее газа
        'В результате быстрого торможения скорость может стать отрицательной, что и предотвращается:
        If Шаг < 0 Then Шаг = 0
    End If
    'Чтобы во время набора скорости и торможения приходилось без перерыва жать на педаль:
    Газ = False    : Тормоз = False
End Sub
Sub Выбираем_куда_ехать_и_делаем_шаг()
    Select Case Руль
        Case типРуль.вверх    : Машина.Image = Машина_вверх         : y = y - Шаг
        Case типРуль.вниз            : Машина.Image = Машина_вниз           : y = y + Шаг
        Case типРуль.влево    : Машина.Image = Машина_налево             : x = x - Шаг
        Case типРуль.вправо : Машина.Image = Машина_направо            : x = x + Шаг
    End Select
End Sub
'Обработка события - нажатия клавиши на клавиатуре для управления автомобилем:
Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs)  _
Handles MyBase.KeyDown
    Select Case e.KeyCode
        Case Keys.Left                   : Руль = типРуль.влево
        Case Keys.Right          : Руль = типРуль.вправо
        Case Keys.Up              : Руль = типРуль.вверх
        Case Keys.Down          : Руль = типРуль.вниз
        Case Keys.Space        : Газ = True
        Case Keys.ControlKey        : Тормоз = True
    End Select
End Sub
Создаем изображения машины. Пустой PictureBox передвигать по форме неинтересно, поэтому рисуем в каком-нибудь графическом редакторе маленькую машинку (вид сверху) точно так же, как мы рисовали летающую тарелку для мультфильма. Сохраняем ее.


Во время гонок машина может ехать в 4 направлениях: влево, вправо, вверх, вниз. Значит, для придания естественности игре (чтобы машина не ехала «боком»), мы должны иметь 4 ориентации машины, между которыми будем в нужные моменты переключаться. Поэтому нам нужны 4 одинаковых изображения машины, повернутые в разные стороны. Для этого вовсе не нужно рисовать 4 рисунка и сохранять 4 файла (хотя и это можно, конечно). Вспомним, что метод RotateFlip умеет поворачивать картинки под прямыми углами. Его и используем.
Обращение к процедуре Создаем_изображения_машины мы находим, естественно, в процедуре Form1_Load, так как создать эти изображения достаточно один раз. Здесь же мы видим, как следующая строка делает прозрачным фон элемента управления Машина. Тело процедуры Создаем_изображения_машины, как видите, состоит из 4 операторов, каждый из которых создает одно из 4 изображений. Каждый из этих операторов есть в свою очередь обращение к процедуре Создаем_изображение. Рассмотрим ее получше.
В верхней части окна кода мы видим строки:
Dim Исходная_машина As New Bitmap("Машина.BMP")           'Создаем исходное изображение машины
'Определяем 4 рабочих изображения машины:
Dim Машина_налево, Машина_вверх, Машина_направо, Машина_вниз As Bitmap                    
Первая из них на основе нарисованной нами машины создает объект Исходная_машина типа Bitmap, который послужит исходным материалом для упомянутых 4 изображений. Каждое из них в дальнейшем получится поворотом картинки Исходная_машина на нужный угол. Тут же объявляются (но не создаются) объекты типа Bitmap для этих 4 изображений.
У процедуры Создаем_изображение два параметра: Первый из них (Автомобиль) как раз и является тем изображением, которое создает процедура. Он имеет тип Bitmap и обозначен словом ByRef, а не ByVal, так как в процессе работы изображение и создается и меняется. Второй параметр (Поворот) имеет тип перечисления RotateFlipType, которое как раз и используется при повороте картинок. Когда я рисовал машину, я нарисовал ее глядящей влево, отсюда становятся понятны значения второго параметра в обращении к процедурам.


Для формирования требуемого изображения машины нужно проделать 3 вещи: