Учим Python, делая крутые игры 2018. Invent your owncomputer gameswith python
Скачать 6.56 Mb.
|
MOUSEBUTTONDOWN Генерируется при нажатии кнопки мыши внутри окна. Это событие имеет атрибут pos, который является кортежем (x, y ) для координат местоположения мыши непосредственно при нажа- тии кнопки. Есть также атрибут button, представляющий собой целое число от 1 до 5. Он сообщает, какая кнопка мыши была нажата, как описано в таблице 19.1. • MOUSEBUTTONUP . Генерируется при отпускании кнопки мыши. Имеет те же атрибуты, что и MOUSEBUTTONDOWN. Когда генерируется событие MOUSEBUTTONDOWN, оно имеет атрибут button . Атрибут button — это значение, связанное с различными типами кнопок, ко- торые могут быть у мыши. Например, левая кнопка имеет значение 1, а пра- вая — значение 3. В таблице 19.1 перечислены все атрибуты button для собы- тий мыши, но обратите внимание, что к мыши могут быть применены не все значения button, указанные здесь. Значения атрибутов button Значение button Кнопка (или колесико) мыши 1 Левая кнопка 2 Средняя кнопка 3 Правая кнопка 4 Колесо прокрутки прокручено вверх 5 Колесо прокрутки прокручено вниз Мы будем использовать эти события, чтобы позволить игроку управлять блоком с помощью событий KEYDOWN и щелчков мышью. Обнаружение столкновений 361 Обработка события KEYDOWN Код для обработки событий нажатия и отпускания клавиш начинается в строке 44. Он включает в себя тип события KEYDOWN. 44. if event.type == KEYDOWN: Если тип события — KEYDOWN, тогда объект Event содержит атрибут key, указы- вающий, какая клавиша была нажата. Когда игрок нажимает клавишу со стрел- кой или клавишу W, A, S или D (эти клавиши расположены таким же образом, что и клавиши со стрелками, но в левой части клавиатуры), нужно, чтобы блок перемещался. Мы будем использовать инструкции if для проверки нажатой клавиши, чтобы указать, в каком направлении должен двигаться блок. Код в строке 46 сравнивает этот атрибут key с K_LEFT и K_a, константами pygame.locals , представляющими на клавиатуре клавиши ← и A, соответ- ственно. Код в строках 46–57 выполняет проверку для каждой из клавиш со стрелкой и W, A, S или D: 45. # Изменение переменных клавиатуры. 46. if event.key == K_LEFT or event.key == K_a: 47. moveRight = False 48. moveLeft = True 49. if event.key == K_RIGHT or event.key == K_d: 50. moveLeft = False 51. moveRight = True 52. if event.key == K_UP or event.key == K_w: 53. moveDown = False 54. moveUp = True 55. if event.key == K_DOWN or event.key == K_s: 56. moveUp = False 57. moveDown = True Когда нажата одна из этих клавиш, код сообщает Python, что нужно при- своить значение True соответствующей переменной перемещения. Python также присвоит значение False переменной перемещения для обратного на- правления. Например, при нажатии клавиши ←программа выполняет код в стро- ках 47 и 48. В этом случае Python присвоит переменной moveLeft значение True, а переменной moveRight — False (несмотря на то, что переменной moveRight уже 362 Глава 19 может быть присвоено значение False, Python снова сделает его False, просто для пущей уверенности). В строке 46 переменная event.key может равняться либо K_LEFT, либо K_a. Значение event.key устанавливается равным тому же значению, что и K_LEFT, если нажата клавиша ←, или тому же значению, что и K_a, если нажата кла- виша A. Благодаря выполнению кода в строках 47 и 48, если нажатие клавиши — K_LEFT или K_a, клавиши ←и A выполняют одно и то же действие. Клавиши W, A, S и D используются в качестве альтернативы для изменения переменных перемещения, позволяя игроку использовать по желанию левую руку вместо правой. Оба набора клавиш изображены на рис. 19.3. Рис. 19.3. Клавиши W, A, S или D можно запрограммировать выполнять те же операции, что выполняют клавиши ←, ↑, ↓ и → Константы для клавиш с буквами и цифрами интуитивно понятны: кон- станта клавиши с буквой «A» — это K_a, константа клавиши с буквой «B» — K_b и так далее. Константа клавиши с цифрой 3 — K_3. В таблице 19.2 перечис- лены часто используемые константы для других клавиш на клавиатуре. Таблица 19.2. Константы для клавиш на клавиатуре Константа pygame Клавиша на клавиатуре K_LEFT Стрелка влево K_RIGHT Стрелка вправо K_UP Стрелка вверх K_DOWN Стрелка вниз K_ESCAPE Esc K_BACKSPACE Backspace K_TAB Tab K_RETURN Return или Enter K_SPACE Пробел K_DELETE Del K_LSHIFT Левая клавиша Shift K_RSHIFT Правая клавиша Shift K_LCTRL Левая клавиша Ctrl K_RCTRL Правая клавиша Ctrl Обнаружение столкновений 363 Константа pygame Клавиша на клавиатуре K_LALT Левая клавиша Alt K_RALT Правая клавиша Alt K_HOME Home K_END End K_PAGEUP PgUp K_PAGEDOWN PgDn K_F1 F1 K_F2 F2 K_F3 F3 K_F4 F4 K_F5 F5 K_F6 F6 K_F7 F7 K_F8 F8 K_F9 F9 K_F10 F10 K_F11 F11 K_F12 F12 Обработка события KEYUP Когда игрок отпускает клавишу, генерируется событие KEYUP. 58. if event.type == KEYUP: Если клавиша, которую отпустили, была Esc, тогда Python должен завер- шить программу. Помните, что в модуле pygame вы должны вызвать функцию pygame.quit() перед вызовом функции sys.exit(), что мы и делаем в стро- ках 59–61. 59. if event.key == K_ESCAPE: 60. pygame.quit() 61. sys.exit() Код в строках 62–69 присваивает переменной перемещения значение False , если была отпущена клавиша соответствующего направления. 364 Глава 19 62. if event.key == K_LEFT or event.key == K_a: 63. moveLeft = False 64. if event.key == K_RIGHT or event.key == K_d: 65. moveRight = False 66. if event.key == K_UP or event.key == K_w: 67. moveUp = False 68. if event.key == K_DOWN or event.key == K_s: 69. moveDown = False Присваивание переменной перемещения значения False посредством со- бытия KEYUP приводит к тому, что блок прекращает перемещение. Телепортация игрока Вы также можете добавить в игру возможность телепортации. Если игрок нажимает клавишу X, код в строках 71 и 72 помещает блок игрока в случай- ную позицию в окне. 70. if event.key == K_x: 71. player.top = random.randint(0, WINDOWHEIGHT - player.height) 72. player.left = random.randint(0, WINDOWWIDTH - player.width) Код в строке 70 проверяет, нажал ли игрок клавишу X. Затем код в стро- ке 71 устанавливает значение случайной координаты x, в которую телепо- ртируется игрок, в промежутке между 0 и высотой окна минус высота блока игрока. Код в строке 72 выполняет аналогичный код для координаты y. Это позволяет игроку перемещаться по окну, нажимая клавишу X, но он не смо- жет выбирать, куда телепортироваться, — это место выбирается полностью случайным образом. Добавление новых блоков «еды» Существуют два способа, с помощью которых игрок может добавить на экран новые блоки «еды». Он может щелкнуть мышью в позиции, где хочет создать новый блок «еды», или подождать, пока игровой цикл не повторит NEWFOOD количество раз, и тогда в окне будет случайно создан новый блок «еды». Сначала рассмотрим, как «еда» добавляется с помощью мыши. Обнаружение столкновений 365 74. if event.type == MOUSEBUTTONUP: 75. foods.append(pygame.Rect(event.pos[0], event.pos[1], FOODSIZE, FOODSIZE)) Ввод с мыши управляется событиями точно так же, как ввод с клавиату- ры. Событие MOUSEBUTTONUP происходит, когда игрок отпускает кнопку мыши после того, как нажал ее. В строке 75 координата x сохраняется в переменной event.pos[0], а коор- дината y — в переменной event.pos[1]. Код в строке 75 создает новый объект Rect для представления нового блока «еды» и помещает его там, где произо- шло событие MOUSEBUTTONUP. При добавлении нового объекта Rect в список foods , код отображает на экране новый блок «еды». Помимо добавления вручную на усмотрение игрока, блоки «еды» генери- руются автоматически с помощью кода в строках 77–81. 77. foodCounter += 1 78. if foodCounter >= NEWFOOD: 79. # Добавление новой "еды". 80. foodCounter = 0 81. foods.append(pygame.Rect(random.randint(0, WINDOWWIDTH - FOODSIZE), random.randint(0, WINDOWHEIGHT - FOODSIZE), FOODSIZE, FOODSIZE)) Переменная foodCounter отслеживает, как часто следует добавлять «еду». При каждой итерации игрового цикла значение переменной foodCounter в строке 77 увеличивается на 1. Когда значение переменной foodCounter становится больше или равно константе NEWFOOD, оно сбрасывается, и кодом в строке 81 создается новый блок «еды». Вы можете изменить скорость, с которой добавляются новые бло- ки «еды», путем настройки NEWFOOD ранее в строке 21. Код в строке 84 просто заполняет поверхность окна белым цветом, о чем мы говорили в разделе «Обработка решения игрока завершить игру» преды- дущей главы, поэтому сейчас перейдем к обсуждению того, как игрок пере- мещается по экрану. Перемещение игрока по окну Мы присвоили переменным перемещения (moveDown, moveUp, moveLeft и moveRight) значения True или False в зависимости от того, какие клавиши на- жал игрок. Теперь нам нужно переместить блок игрока, а он представлен объ- ектом pygame.Rect, хранящимся в переменной player. Мы сделаем это, устано- вив координаты x и y объекта player. 366 Глава 19 86. # Перемещение игрока. 87. if moveDown and player.bottom < WINDOWHEIGHT: 88. player.top += MOVESPEED 89. if moveUp and player.top > 0: 90. player.top -= MOVESPEED 91. if moveLeft and player.left > 0: 92. player.left -= MOVESPEED 93. if moveRight and player.right < WINDOWWIDTH: 94. player.right += MOVESPEED Если переменной moveDown присвоено значение True (а нижняя часть бло- ка игрока не вышла за пределы нижней границы окна), тогда код в строке 88 перемещает блок игрока вниз, добавляя значение MOVESPEED к текущему атри- буту игрока top. Код в строках 89–94 делает то же самое для трех других на- правлений. Отображение блока игрока в окне Код в строке 97 отображает блок игрока в окне. 96. # Отображение игрока на поверхности. 97. pygame.draw.rect(windowSurface, BLACK, player) После перемещения блока код в строке 97 отображает его в новом поло- жении. Переменная WindowSurface, переданная в качестве первого параметра, сообщает Python, на каком из объектов Surface отобразить прямоугольник. Переменная BLACK, в которой хранится значение (0, 0, 0), сообщает Python, что нужно отобразить черный прямоугольник. Объект Rect, хранящийся в переменной player, указывает Python положение и размер прямоугольника, который нужно отобразить. Проверка на столкновения Прежде чем отображать блоки «еды», программе необходимо проверить, не пересекся ли блок игрока каким-либо из блоков «еды». Если пересекся, то этот блок «еды» следует удалить из списка foods. Таким образом, Python не будет отображать блоки «еды», которые игрок уже «съел». Мы будем использовать colliderect() — метод обнаружения столкнове- ний, который содержат все объекты Rect в строке 101. Обнаружение столкновений 367 99. # Проверка, не пересекся ли игрок с какими-либо блоками "еды". 100. for food in foods[:]: 101. if player.colliderect(food): 102. foods.remove(food) При каждой итерации цикла for текущий блок «еды» из списка foods (множественное число) помещается в переменную food (единственное чис- ло). Метод colliderect() для объектов pygame.Rect передается объекту pygame. Rect блока игрока в качестве аргумента и возвращает True, если два прямоу- гольника сталкиваются, и False — если не сталкиваются. В случае значения True код в строке 102 удаляет перекрывающийся блок «еды» из списка foods. НЕ ИЗМЕНЯЙТЕ СПИСОК ПРИ ЕГО ПЕРЕБОРЕ Обратите внимание, что этот цикл for немного отличается от циклов for , которые мы встречали раньше. Если вы внимательно взглянете на строку 100, то заметите, что на самом деле цикл перебирает не foods, а foods[:]. Давайте вспомним, как работают срезы. foods[:2] — копия списка с элементами от начала и до (но не включая) элемента с индексом 2. foods[:] даст вам копию списка с элементами с самого начала и до кон- ца. В принципе, foods[:] создает новый список с копией всех элементов в списке foods. Это более короткий способ создать копию списка, чем, скажем, тот, что основан на использовании функции getBoardCopy() в игре «Крестики-нолики» из главы 10. Вы не можете добавлять или удалять элементы из списка во время перебора. Если размер списка foods постоянно меняется, Python может потерять информацию о том, каким должно быть следующее значение переменной food. Представьте, как трудно было бы подсчитать количе- ство конфет в банке, если бы в это время кто-то их оттуда забирал или подкидывал новые. Но если вы перебираете копию списка (а копия никогда не изменя- ется), добавление или удаление элементов из исходного списка не будет проблемой. Отображение блоков «еды» Код в строках 105 и 106 аналогичен тому, который мы использовали для отображения черного блока игрока. 104. # Отображение "еды". 105. for i in range(len(foods)): 106. pygame.draw.rect(windowSurface, GREEN, foods[i]) Код в строке 105 перебирает каждый блок «еды» в списке foods, а код в строке 106 отображает блок «еды» на windowSurface. Теперь, когда блок игрока и блоки «еды» отображены на экране, окно го- тово к обновлению, поэтому мы вызываем метод update() в строке 109 и за- вершаем программу, вызывая метод tick() в объекте Clock, который мы соз- дали ранее. 108. # Вывод окна на экран. 109. pygame.display.update() 110. mainClock.tick(40 ) Программа продолжит выполняться через игровой цикл и будет обнов- ляться до тех пор, пока игрок не решит закончить игру. Заключение В этой главе была решена проблема обнаружения столкновений. В гра- фических играх обнаружение столкновений между двумя прямоугольниками настолько распространено, что модуль pygame предоставляет свой собствен- ный метод обнаружения столкновений для объектов pygame.Rect под назва- нием colliderect(). Первые несколько игр в этой книге были текстовыми. Вывод данных про- граммы на экран имел текстовую форму, ввод данных осуществлялся игро- ком путем набора текста с клавиатуры. Графические программы позволяют вам принимать ввод с мыши. Также эти программы могут реагировать на одиночные нажатия клавиш, когда игрок нажимает или отпускает ту или иную клавишу. Игроку не нужно вводить полный ответ и нажимать клавишу Enter. Это позволяет получать мгновенную обратную связь и делает игры гораздо более интерактивными. Наша первая интерактивная графическая программа оказалась довольно занятной, но давайте пойдем дальше. В главе 20 вы узнаете, как с помощью pygame загружать изображения и воспроизводить звуковые эффекты. Использование звуков и изображений 369 20 ИСПОЛЬЗОВАНИЕ ЗВУКОВ И ИЗОБРАЖЕНИЙ Из глав 18 и 19 вы узнали, как создавать графический интерфейс программ с поддержкой ввода данных с клавиату- ры и мыши. Вы также научились ото- бражать различные фигуры. В этой главе вы узнаете, как добавлять в свои игры зву- ки, музыку, а также изображения. В ЭТОЙ ГЛАВЕ РАССМАТРИВАЮТСЯ СЛЕДУЮЩИЕ ТЕМЫ: • Файлы звуков и изображений • Отображение и масштабирование спрайтов • Добавление музыки и звуков • Включение и отключение звука Добавление изображений с помощью спрайтов Спрайт — это отдельное двумерное изображение, которое использует- ся на экране как часть графики. На рис. 20.1 показаны некоторые примеры спрайтов. Спрайты отображаются поверх фона. Вы можете отразить спрайт по го- ризонтали, чтобы он выглядел иначе, можете также отобразить один и тот же спрайт в одном окне несколько раз, и можете увеличивать или уменьшать размер спрайтов. Фоновое изображение тоже можно рассматривать как один большой спрайт. На рис. 20.2 показаны спрайты, используемые вместе. Следующая программа продемонстрирует, как воспроизводить звуки и отображать спрайты с помощью pygame. 370 Глава 20 Рис. 20.1. Некоторые примеры спрайтов Рис. 20.2. Целая сцена со спрайтами, отображенными поверх фона Графические и звуковые файлы Спрайты хранятся в файлах изображений на вашем компьютере. Су- ществует несколько форматов изображений, которые поддерживает pygame. Чтобы узнать формат файла изображения, посмотрите на конец его имени (после последней точки). То, что вы увидите, называется расширением файла. Например, файл player.png имеет формат PNG. Модуль pygame поддерживает форматы изображений BMP , PNG, JPG и GIF . Вы можете загружать изображения из веб-браузера. В большинстве слу- чаев это делается путем щелчка правой кнопкой мыши на изображении на веб-странице и последующего выбора пункта Сохранить изображение (Save Image) в появившемся меню. Запомните, куда именно на жестком диске со- хранился файл изображения, потому что вам нужно будет скопировать его в ту же папку, где находится файл .py вашей программы Python. Вы также можете создавать свои собственные изображения с помощью графического редактора наподобие Microsoft Paint или Tux Paint. К форматам звуковых файлов, поддерживаемых модулем pygame, относят- ся MIDI, WAV и MP3. Звуковые эффекты можно загружать из Интернета так Использование звуков и изображений 371 же, как файлы изображений, но звуковые файлы должны быть в одном из трех перечисленных форматов. Если на вашем компьютере есть микрофон, вы также можете записывать звуки и создавать собственные файлы WAV для использования в своих играх. |