Как отследить нажатие клавиш на клавиатуре pygame

Обновлено: 13.05.2024

Этот модуль содержит функции для работы с клавиатурой.

pygame.event queue gets pygame.KEYDOWN and pygame.KEYUP events when the keyboard buttons are pressed and released. Both events have key and mod attributes. --> pygame.event очередь получает pygame.KEYDOWN и pygame.KEYUP события , когда кнопки на клавиатуре нажата и отпущена. Оба события имеют атрибуты key и mod .

  • key : an integer ID representing every key on the keyboard --> key : целочисленный идентификатор, представляющий каждую клавишу на клавиатуре
  • mod : a bitmask of all the modifier keys that were in a pressed state when the event occurred --> mod : битовая маска всех клавиш-модификаторов, которые были в нажатом состоянии, когда произошло событие

pygame.KEYDOWN event has the additional attributes unicode and scancode . --> pygame.KEYDOWN событие имеет дополнительные атрибуты unicode и scancode .

  • unicode : a single character string that is the fully translated character entered, this takes into account the shift and composition keys --> unicode : односимвольная строка, которая является полностью переведенным введенным символом, при этом учитываются клавиши сдвига и композиции
  • scancode : the platform-specific key code, which could be different from keyboard to keyboard, but is useful for key selection of weird keys like the multimedia keys --> scancode : код клавиши, зависящий от платформы, который может отличаться от клавиатуры к клавиатуре, но полезен для выбора необычных клавиш, таких как мультимедийные клавиши.

pygame.TEXTINPUT event is preferred to the unicode attribute of pygame.KEYDOWN . The attribute text contains the input. --> Новое в pygame 2.0.0: событие pygame.TEXTINPUT предпочтительнее атрибута unicode для pygame.KEYDOWN . Атрибут text содержит ввод.

pygame.locals ) used to represent keyboard keys. --> Ниже приведен список всех констант (из pygame.locals ), используемых для представления клавиш клавиатуры.

K_a ) rather than integers directly ( 97 ) so that your key handling code works well on both pygame 1 and pygame 2. --> Примечание о переносимости: целые числа для ключевых констант различаются между pygame 1 и 2. Всегда используйте ключевые константы ( K_a ), а не целые числа напрямую ( 97 ), чтобы ваш код обработки ключей хорошо работал как в pygame 1, так и в pygame 2.

pygame.locals ) that can be assembled by bitwise-ORing them together. --> На клавиатуре также есть список состояний модификаторов (из pygame.locals ), которые могут быть собраны путем побитового ИЛИ их вместе.

mod attribute of the pygame.KEYDOWN and pygame.KEYUP events. The mod attribute is a bitmask of all the modifier keys that were in a pressed state when the event occurred. The modifier information can be decoded using a bitwise AND (except for KMOD_NONE , which should be compared using equals == ). For example: --> Информация о модификаторе содержится в атрибуте mod событий pygame.KEYDOWN и pygame.KEYUP . mod атрибут представляет собой битовую маску всех клавиш - модификаторов , которые были в прижатом состоянии , когда произошло событие. Информация о модификаторе может быть декодирована с помощью побитового И (за исключением KMOD_NONE , который следует сравнивать с помощью equals == ). Например:

true,если дисплей получает от системы ввод с клавиатуры.

True when the display window has keyboard focus from the system. If the display needs to ensure it does not lose keyboard focus, it can use pygame.event.set_grab() to grab all input. --> Возвращает True , если в окне дисплея находится системный фокус клавиатуры. Если дисплею необходимо убедиться, что он не теряет фокус клавиатуры, он может использовать pygame.event.set_grab() для захвата всего ввода.

True value means the that button is pressed. --> Возвращает последовательность логических значений, представляющих состояние каждой клавиши на клавиатуре. Используйте значения ключевых констант для индексации массива. Значение True означает, что эта кнопка нажата.

pygame.key.get_pressed() . There is also no way to translate these pushed keys into a fully translated character value. See the pygame.KEYDOWN events on the pygame.event queue for this functionality. --> Получение списка нажатых кнопок с помощью этой функции - неправильный способ обработки ввода текста от пользователя. Невозможно узнать порядок нажатия клавиш, а быстро нажимаемые клавиши могут быть совершенно незамеченными между двумя вызовами pygame.key.get_pressed() . Также невозможно преобразовать эти нажатые клавиши в полностью переведенное символьное значение. См pygame.KEYDOWN события на pygame.event очереди для этой функции.

Возвращает одно целое число, представляющее битовую маску всех удерживаемых ключей-модификаторов. Используя побитовые операторы, вы можете проверить , нажаты ли определенные клавиши-модификаторы .

временно установить,какие клавиши модификатора нажимаются

Создайте битовую маску констант клавиш-модификаторов, которые вы хотите наложить на свою программу.

Человек может управлять объектами в игре в основном с помощь клавиатуры, мыши, джойстика. Когда на "манипуляторах" что-то двигается или нажимается, то возникают события определенных типов. Обработкой событий занимается модуль pygame.event, который включает ряд функций, наиболее важная из которых уже ранее рассмотренная pygame.event.get(), которая забирает из очереди произошедшие события.

В pygame, когда фиксируется то или иное событие, создается соответствующий ему объект от класса Event. Уже с этими объектами работает программа. Экземпляры данного класса имеют только свойства, у них нет методов. У всех экземпляров есть свойство type. Набор остальных свойств события зависит от значения type.

События клавиатуры могут быть двух типов (иметь одно из двух значений type) – клавиша была нажата, клавиша была отпущена. Если вы нажали клавишу и отпустили, то в очередь событий будут записаны оба. Какое из них обрабатывать, зависит от контекста игры. Если вы зажали клавишу и не отпускаете ее, то в очередь записывается только один вариант – клавиша нажата.

Событию типа "клавиша нажата" в поле type записывается числовое значение, совпадающее со значением константы pygame.KEYDOWN. Событию типа "клавиша отпущена" в поле type записывается значение, совпадающее со значением константы pygame.KEYUP.

У обоих типов событий клавиатуры есть атрибуты key и mod. В key записывается конкретная клавиша, которая была нажата или отжата. В mod – клавиши-модификаторы (Shift, Ctrl и др.), которые были зажаты в момент нажатия или отжатия обычной клавиши. У событий KEYDOWN также есть поле unicode, куда записывается символ нажатой клавиши (тип данных str).

Рассмотрим, как это работает. Пусть в центре окна имеется круг, который можно двигать по горизонтали клавишами стрелок клавиатуры:

В цикле обработки событий теперь проверяется не только событие выхода, но также нажатие клавиш. Сначала необходимо проверить тип, потому что не у всех событий есть атрибут key. Если сразу начать проверять key, то сгенерируется ошибка по той причине, что могло произойти множество событий. Например, движение мыши, у которого нет поля key. Соответственно, попытка взять значение из несуществующего поля (i.key) приведет к генерации исключения.

Часто проверку и типа и клавиши записывают в одно логическое выражение ( i. type == pygame. KEYDOWN and i. key == pygame. K_LEFT ). В Python так можно делать потому, что если первая часть сложного выражения возвращает ложь, то вторая часть уже не проверяется.

Если какая-либо клавиша была нажата, то проверяется, какая именно. В данном случае обрабатываются только две клавиши. В зависимости от этого меняется значение координаты x.

Проблема данного кода в том, что при выполнении программы, чтобы круг двигался, надо постоянно нажимать и отжимать клавиши. Если просто зажать их на длительный период, то объект не будет постоянно двигаться. Он сместиться только одноразово на 3 пикселя.

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

Как быть, если по логике вещей надо, чтобы шар двигался до тех пор, пока клавиша зажата? Когда же она отпускается, шар должен останавливаться. Первое, что надо сделать, – это перенести изменение координаты x в основную ветку главного цикла while. В таком случае на каждой его итерации координата будет меняться, а значит шар двигаться постоянно.

Во-вторых, в цикле обработки событий нам придется следить не только за нажатием клавиши, но и ее отжатием. Когда клавиша нажимается, какая-либо переменная, играющая роль флага, должна принимать одно значение, когда клавиша отпускается эта же переменная должна принимать другое значение.

В основном теле while надо проверять значение этой переменной и в зависимости от него менять или не менять значение координаты.

Использовать константы не обязательно, можно сразу присваивать строки или даже числа (например, motion = 1 обозначает движение вправо, -1 – влево, 0 – остановка). Однако константы позволяют легче понимать и обслуживать в дальнейшем код, делают его более информативным. Лучше привыкнуть к такому стилю.

Должно проверяться отжатие только двух клавиш. Если проверять исключительно KEYUP без последующей конкретизации, то отжатие любой клавиши приведет к остановке, даже если в это время будет по-прежнему зажиматься клавиша влево или вправо. Выражение i. key in [ pygame. K_LEFT , pygame. K_RIGHT ] обозначает, что если значение i.key совпадает с одним из значений в списке, то все выражение возвращает истину.

На самом деле существует способ по-проще. В библиотеке pygame с событиями работает не только модуль event. Так модуль pygame.key включает функции, связанные исключительно с клавиатурой. Здесь есть функция pygame.key.get_pressed(), которая возвращает кортеж двоичных значений. Индекс каждого значения соответствует своей клавиатурной константе. Само значение равно 1, если клавиша нажата, и 0 – если не нажата.

Эта функция подходит не для всех случаев обработки клавиатурных событий, но в нашем подойдет. Поэтому мы можем упростить код до такого варианта:

Можно сказать, вызов get_pressed() снимает "маску" зажатых клавиш. Мы ее снимаем на каждой итерации главного цикла. Это даже не регистрация событий как таковых.

Выражение типа keys[pygame.K_LEFT] извлекает значение из кортежа по индексу, значение которого записано в константе K_LEFT. Если извлеченное значение True, то координата меняется.

Если необходимо, чтобы событие обрабатывалось при нажатии двух и более клавиш, то работает такое логическое выражение: keys [ pygame. K_LEFT ] and keys [ pygame. K_a ] (одновременное нажатие стрелки 'влево' и буквы 'a'). Однако если нужно задействовать не обычные клавиши, а модификаторы, то данный номер не проходит.

В таком случае можно вернуться к первому варианту – перебирать события в цикле for:

Здесь при if будет True, если перед нажатием стрелки был зажат левый Shift. Причем обратная последовательность: сначала зажать стрелку, потом Shift не сработает. Видимо модификаторы обрабатываются библиотекой pygame несколько отлично от обычных клавиш. Допустим, если при зажатии обычных клавиш генерируется только одно событие, то для модификаторов они генерируются постоянно или хранятся до отпускания в другой очереди.

Таким образом, если первым зажимается K_LEFT, то событие сразу обрабатывается. При этом в i.mod записывается отсутствие модификатора. Поэтому условие не срабатывает.

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

Практическая работа

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

Курс с примерами решений практических работ:
android-приложение, pdf-версия

WHITE = ( 255 , 255 , 255 )
BLACK = ( 0 , 0 , 0 )
PURPLE = ( 156 , 39 , 176 )
INDIGO = ( 63 , 81 , 181 )
BLUE = ( 33 , 150 , 243 )
GREEN = ( 76 , 175 , 80 )
YELLOW = ( 255 , 235 , 59 )
ORANGE = ( 255 , 152 , 0 )
GREY = ( 158 , 158 , 158 )

display = pygame.display. set_mode ( ( 800 , 600 ) )

FPS = 60
clock = pygame.time. Clock ()
while True :
f or event in pygame.event. get ():
if event.type == pygame.QUIT:
pygame. quit ()
exit ()

pygame отслеживает все происходящие в игре события и позволяет нам их обрабатывать. При возникновении события создается экземпляр класса Event. Каждый экземпляр этого класса имеет определенный список свойств. Одно из этих свойств - это свойство type . Именно оно позволяет нам понять, какое событие произошло.

События клавиатуры имеют тип KEYDOWN.

Еще одно важное свойство - это свойство key . Для нас оно представляет интерес, когда мы обнаружили событие с типом KEYDOWN . С помощью свойства key мы можем узнать, какая клавиша была нажата.

import pygame
from sys import exit

WHITE = ( 255 , 255 , 255 )
BLACK = ( 0 , 0 , 0 )
PURPLE = ( 156 , 39 , 176 )
INDIGO = ( 63 , 81 , 181 )
BLUE = ( 33 , 150 , 243 )
GREEN = ( 76 , 175 , 80 )
YELLOW = ( 255 , 235 , 59 )
ORANGE = ( 255 , 152 , 0 )
GREY = ( 158 , 158 , 158 )

display = pygame.display. set_mode ( ( 800 , 600 ) )

FPS = 60
clock = pygame.time. Clock ()
while True :
f or event in pygame.event. get ():
if event.type == pygame.QUIT:
pygame. quit ()
exit ()
el if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
print ( 'Левая стрелка' )
el if event.key == pygame.K_RIGHT:
print ( 'Правая стрелка' )
el if event.key == pygame.K_UP:
print ( 'Стрелка вверх' )
el if event.key == pygame.K_DOWN:
print ( 'Стрелка вниз' )

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

Напишем код, который будет рисовать кружок

Заставим кружок двигаться. Нужно объявить две переменные - x и y . Эти переменные будут координатами нашего кружка. При нажатии клавиши мы будем изменять эти переменные. Если нажата стрелка вправо, увеличим переменную x на 10. Если - стрелка влево, уменьшим переменную x на 10. Проделаем то же самое с переменной y.

import pygame
from sys import exit

WHITE = ( 255 , 255 , 255 )
BLACK = ( 0 , 0 , 0 )
PURPLE = ( 156 , 39 , 176 )
INDIGO = ( 63 , 81 , 181 )
BLUE = ( 33 , 150 , 243 )
GREEN = ( 76 , 175 , 80 )
YELLOW = ( 255 , 235 , 59 )
ORANGE = ( 255 , 152 , 0 )
GREY = ( 158 , 158 , 158 )

display = pygame.display. set_mode ( ( 800 , 600 ) )

FPS = 60
clock = pygame.time. Clock ()

Есть один нюанс. Шарик перемещается только один раз при зажатии одной из клавиш. Немного изменим наш код для того, чтобы он обратывал зажатые клавиш.

События мыши

В pygame обрабатываются три типа событий мыши: нажатие кнопки (значение свойства type события соответствует MOUSEBUTTONDOWN ), отпускание кнопки ( MOUSEBUTTONUP ), перемещение мыши ( MOUSEMOTION ). Какая именно кнопка была нажата, записывается в другое свойство события - button . Для левой кнопки это число 1, для средней - 2, для правой - 3, для прокручивания вперед - 4, для прокручивания назад - 5.

Другим атрибутом мышиных типов событий является свойство pos , в которое записываются координаты нажатия (кортеж из двух чисел).

При нажатии левой кнопки мыши будем рисовать оранжевый кружок

Добавим появление белых кружков по нажатию правой кнопки мыши.

Добавим очищение поверхности при скролле колесика мыши

Задание:

Создайте еще один перемещающийся объект, назначьте клавиши WASD для его перемещения. Ключи клавиш: W == K_w, A == K_a, D == K_d, S == K_s. Обратите внимание, что вам понадобятся новые переменные для координат, например, x1 и y1.


Pygame использует объекты Rect для хранения и манипулирования прямоугольными областями. Rect может быть создан из комбинации значений слева, сверху, ширины и высоты. Rect также могут быть созданы из объектов python, которые уже являются Rect или имеют атрибут с именем «rect».

Методы работы с Rect

pygame.Rect.copy Возвращает новый прямоугольник, имеющий ту же позицию и размер, что и оригинал.
pygame.Rect.move Возвращает новый прямоугольник, перемещаемый данным смещением. Аргументы x и y могут быть любым целочисленным значением, положительным или отрицательным.
pygame.Rect.move_ip То же, что и метод Rect.move (), но работает на месте.
pygame.Rect.inflate увеличивать или уменьшать размер прямоугольника, на месте
pygame.Rect.inflate_ip увеличивать или уменьшать размер прямоугольника, на месте
pygame.Rect.clamp перемещает прямоугольник внутри другого
pygame.Rect.clamp_ip перемещает прямоугольник внутри другого, на месте
pygame.Rect.clip обрезает прямоугольник внутри другого
pygame.Rect.union соединяет два прямоугольника в один
pygame.Rect.union_ip соединяет два прямоугольника в один, на месте
pygame.Rect.unionall объединение многих прямоугольников
pygame.Rect.unionall_ip объединение многих прямоугольников, на месте
pygame.Rect.fit изменить размер и переместить прямоугольник учмиывая соотношение сторон
pygame.Rect.normalize корректировать отрицательные размеры
pygame.Rect.contains проверить, находится ли один прямоугольник внутри другого
pygame.Rect.collidepoint проверить, находится ли точка внутри прямоугольника
pygame.Rect.colliderect тест, пересекаются ли два прямоугольника
pygame.Rect.collidelist проверить, пересекается ли хоть один прямоугольник в списке
pygame.Rect.collidelistall пересекаются ли все прямоугольники в списке
pygame.Rect.collidedict проверить, если один прямоугольник в словаре пересекается
pygame.Rect.collidedictall пересекаются ли все прямоугольники в словаре

Обработка событий

Событие — это то, как Pygame сообщает о том, что что-то случилось за пределами кода программы. События создаются, например, при нажатии клавиш клавиатуры, мыши и размещаются в очереди, дожидаясь обработки.

Функция get в модуле pygame.event возвращает последнее событие, ожидающее в очереди и удаляет его из очереди.

Объект event

Модуль pygame.event для обработки очереди событий

pygame.event.pump Если вы не используете другие функции событий в своей игре, вы должны вызвать pygame.event.pump (), чтобы позволить pygame обрабатывать внутренние действия
pygame.event.get получает события из очереди
pygame.event.poll получить одно событие из очереди
pygame.event.wait ждёт одиночного события из очереди
pygame.event.peek проверить, ждут ли очереди события определённого типа
pygame.event.clear удалить все события из очереди
pygame.event.event_name возвращает имя для типа события. Строка находится в стиле WordCap
pygame.event.set_blocked проверяет, какие события не разрешены в очереди
pygame.event.set_allowed проверяет, какие события разрешены в очереди
pygame.event.get_blocked проверить, заблокирован ли тип события из очереди
pygame.event.set_grab проверяет совместное использование устройств ввода с другими приложениями
pygame.event.get_grab проверить, работает ли программа на устройствах ввода данных
pygame.event.post поместить новое событие в очередь
pygame.event.Event создать новый объект события
pygame.event.EventType Объект Python, представляющий событие SDL. Экземпляры пользовательских событий создаются с вызовом функции Event. Тип EventType не может быть напрямую вызван. Экземпляры EventType поддерживают назначение и удаление атрибутов.

Существует множество способов доступа к очереди событий. Просто проверять существование событий, захватывать их непосредственно из стека.

Модуль pygame.mouse для работы с мышью

pygame.mouse.get_pressed получить состояние кнопок мыши
pygame.mouse.get_pos получить позицию курсора мыши
pygame.mouse.get_rel получить количество движений мыши
pygame.mouse.set_pos установить позицию курсора мыши
pygame.mouse.set_visible скрыть или показать курсор мыши
pygame.mouse.get_focused проверяет, принимает ли дисплей ввод мыши
pygame.mouse.set_cursor установить изображение для курсора мыши
pygame.mouse.get_cursor получить изображение для курсора мыши

Функции мыши можно использовать для получения текущего состояния устройства мышь. Эти функции также могут изменять курсор мыши.

Когда режим отображения (display) установлен, очередь событий начнет принимать события мыши. Кнопки мыши генерируют события pygame.MOUSEBUTTONDOWN и pygame.MOUSEBUTTONUP , когда они нажимаются и отпускаются. Эти события содержат атрибут кнопки, указывающий, какая кнопка была нажата. Колесо мыши будет генерировать pygame.MOUSEBUTTONDOWN и pygame.MOUSEBUTTONUP события при прокрутке.

Когда колесо повернуто вверх, кнопка будет установлена на 4, вниз -5. Всякий раз, когда мышь перемещается, генерируется событие pygame.MOUSEMOTION . Движение мыши разбито на небольшие и точные события движения. По мере перемещения мыши многие события движения будут помещены в очередь. События движения мыши, которые неправильно очищены от очереди событий, являются основной причиной того, что очередь событий заполняется.

Пример. Нарисовать курсор под текущей позицией мыши.

Определить какая кнопка была нажата на мышке можно используя значение event.button:

Координаты курсора при нажатии кнопки мыши находятся в event.pos .

Пример. Перемещать картинку курсором мыши.

Клавиатура

Модуль pygame.key

Этот модуль содержит функции для работы с клавиатурой.Очередь событий получает события pygame.KEYDOWN и pygame.KEYUP при нажатии и отпускании клавиш клавиатуры.

Оба события имеют ключевой атрибут, который представляет собой целочисленный идентификатор, представляющий каждую клавишу на клавиатуре.Событие pygame.KEYDOWN имеет дополнительные атрибуты: unicode и scancode. unicode представляет собой одну символьную строку, которая соответствует введённому символу. Scancode представляет собой код для конкретной платформы.

Получить код клавиши:


Существует много клавиатурных констант, они используются для представления клавиш на клавиатуре. Ниже приведен список всех клавиатурных констант:

Направленное движение с помощью клавиш

Можно перемещать изображение на экране с клавиатуры, назначая клавиши для перемещений: вверх, вниз, влево, вправо.

Создать картинку, например:

Проверить очередь событий:

Проверить, является ли полученное событие нажатием на клавиши со стрелками:

Если — да, то получмить код нажатой клавиши и сформировать новые координаты для картинки:

И нарисовать картинку в новом месте:

Объект Surface

pygame.Surface — объект pygame для представления изображений


Наложение поверхностей, прозрачность.

Управление временем

Модуль pygame.time содержит объект Clock, который можно использовать для отслеживания
времени. Чтобы создать объект типа: время, вызывается конструктор pygame.time.Clock:
clock = pygame.time.Clock()

Когда создан объект clock, можно вызвать его функцию tick один раз за кадр,
которая возвращает время, прошедшее со времени предыдущего вызова в миллисекундах:
time_passed = clock.tick ()

Функция tick может использовать необязательный параметр для установления максимальной частоты кадров. Этот параметр нужен, если игра запущена на рабочем компьютере и необходимо контролировать, чтобы она не использовала всю его вычислительная мощность на 100%:

time_passed = clock.tick (30)

Звуки

Для управления звуком используется модуль pygame.mixer . Он отвечает за любые действия со звуками.

Загружаем звуковой файл в формате *.wav

sound = pygame.mixer.Sound("sound.wav")
(загружаем до игрового цикла, т.к. это очень долгая операция)

Столкновения (collisions)

При написании игр часто возникает необходимость проверять взаимное расположение объектов на экране, отслеживать моменты их столкновений, пересечений.

Читайте также: