Alt"
End Select
End Sub
Два параметра в скобках заголовка процедуры — это две вещи, которые компьютер сообщает процедуре в момент события:
KeyCode — код нажатой клавиши. На клавиатуре — сто с лишним клавиш. На каждой — по две буквы или один, два, три других символа. Компьютер различает клавиши независимо от того, какие значки на них нанесены. Так мать различает сыновей независимо от того, что написано у них на майках. У каждого сына есть имя, у каждой клавиши есть код (KeyCode). Итак, попросту говоря, компьютер сообщает процедуре, какая клавиша была нажата. Полный список кодов находится в Object Browser (класс KeyCodeConstants).
Shift — были ли при этом в нажатом состоянии клавиши клавиатуры (Shift, Ctrl, Alt) и какие именно. В численном значении Shift та же система, что и в событии MouseDown. Совместное нажатие клавиш Shift, Ctrl, Alt "равно" сумме их нажатий по-одиночке (1, 2 и 4).
Запустите проект и проверьте, как работает программа. Обратите внимание, что при удержании клавиш в нажатом состоянии событие генерируется (создается компьютером) несколько раз в секунду. Положение несколько меняется, когда при нажатой Shift, Ctrl или Alt щелкается обычная клавиша. Впрочем, пока это неважно.
События, связанные с клавиатурой, имеются у многих объектов. Поместим на форму, к примеру, пару кнопок и текстовое поле. Предположим, процедуру Private Sub Form_KeyDown мы стерли, а написали три процедуры:
Private Sub Command1_KeyDown…
Private Sub Command2_KeyDown…
Private Sub Text1_KeyDown…
Запустим программу и щелкнем по какой-нибудь клавише. Какая из трех процедур сработает? Та, чей объект находится в фокусе. Для нашей игры это неудобно: если мы для программирования реакции автомобиля на нажатия клавиш выберем, например, процедуру Private Sub Command2_KeyDown, то во время гонки мы не сможем щелкать по другим кнопкам, кроме Command2, так как иначе Command2 выйдет из фокуса и автомобиль перестанет реагировать на клавиши. Не надо было стирать процедуру Private Sub Form_KeyDown, восстановим ее. Но это не помогает. По простой причине — один какой-нибудь объект на форме всегда находится в фокусе, так что до процедуры Private Sub Form_KeyDown дело никак не доходит. Против этого в Visual Basic есть специальный прием — свойство формы KeyPreview устанавливается в True. Это означает приказ компьютеру почти каждое нажатие на клавиши считать событием формы, а не другого объекта. Вдобавок к этому советую поместить в самый конец процедуры Private Sub Form_KeyDown оператор KeyCode=0. Тоже хорошо помогает (без комментариев).
Что значит "почти каждое нажатие"? Есть исключения — клавиши Enter, Esc, Tab в некоторых случаях.
Событие KeyUp работает аналогично.
Задание 112. "Светофор": Нарисуйте светофор: прямоугольник и три круга. При нажатии на клавиатуре клавиши R светофор должен загораться красным светом, G — зеленым, Y — желтым. Здесь таймер не нужен.
Задание 113. "Зенитка": Вверху справа налево медленно движется вражеский самолет. В подходящий момент вы нажатием любой клавиши запускаете снизу вверх зенитный снаряд. Здесь нужны два таймера.
ПРОЕКТ — ГОНКИ (ИГРА)
Мы с вами разобрали уже два больших проекта: "Калькулятор" и "Будильник".
Но "Калькулятор" можно не считать, на нем мы просто знакомились с Visual Basic. Выходит, "Будильник" — единственный большой проект, который написан более-менее правильно. И этого, конечно, мало. Вам нужен опыт создания проектов, в частности проектов с движением объектов по форме, да к тому же под управлением мыши и клавиатуры. Поэтому я решил разобрать с вами еще один проект (строк на 180). На этот раз это будет игра.
Постановка задачи
Вот внешний вид игры (о красотах я не заботился, красоты вы всегда сможете добавить по вкусу):
Процесс игры таков. Вы нажимаете на кнопку Начинаем сначала. На форме рисуется квадратное поле для гонки со случайно расположенными газонами. Нажатием на клавишу пробела вы даете газ и машина со старта набирает скорость. Ваша цель — любым путем побыстрее добраться до финиша. На белом асфальте вы можете газовать до любой скорости. Если же ненароком попадете на газон, то на газоне ваша скорость будет очень мала (я выбрал 15). Поэтому имеет смысл по газонам ездить пореже. Направление движения может быть только горизонтальное и вертикальное, наискосок машина не движется. Выбор направления (руль) — это клавиши со стрелками. Тормоз — клавиша В (английская). Тормозить надо по той причине, что на слишком большой скорости руль отказывает (это не потому, что проект плохой, а потому что я так придумал). В ограждение врезаться нельзя — катастрофа. Когда приедете на финиш, посмотрите на счетчик времени — это ваш результат. Снова нажимаете на кнопку Начинаем сначала. Теперь расположение газонов будет другим. Сажайте за клавиатуру приятеля и смотрите, не покажет ли он время лучшее, чем ваше. Можете посмотреть, кто из вас покажет лучшее время из 10 заездов. И тому подобное.
Не удивляйтесь, что скорость на спидометре не равна пути, деленному на время. Ведь это мгновенная (то есть настоящая скорость в данное мгновение), а не средняя скорость автомобиля (см. Физика, 9 класс).
Все эти правила я старался сделать как можно проще, чтобы не усложнять проект. Разобравшись в проекте, вы всегда сможете дописать процедуры, делающие процесс гонки более для вас привлекательным.
Для проекта я выбрал вариант игры с одним автомобилем. Я вам намекну, как модифицировать проект, чтобы получилась игра с двумя автомобилями. Однако помните, что для грамотного создания игры с несколькими автомобилями вам нужно будет подняться на новый уровень программирования — научиться создавать собственные классы объектов.
Делим проект на части
Начнем создавать проект. Прежде всего, как положено, разделим его по возможности на части. Мы уже делили проект на части, когда создавали будильник. Сейчас вам очень полезно перечитать тот материал. И проглядеть ту программу.
Сразу же бросается в глаза, что наша задача распадается на две последовательные почти независимые части:
Сначала рисование поля и всех его элементов, выкатывание машины на старт, обнуление скорости, времени и пути — в общем, все то, что должно быть сделано после нажатия на кнопку Начинаем сначала, но до начала движения. Этим будет заниматься одна группа процедур.
Затем управление машиной и событиями во время гонки. Этим будет заниматься другая группа процедур. Мы полностью задействуем идею использования таймера, так, как я ее изложил в 0. На каждом импульсе таймера автомобиль должен будет проделывать весь цикл своего функционирования.
Первая часть
Поскольку в первой части нет движения, то, в общем, все равно, что именно рисовать сначала, что