События клавиатуры
Человек может управлять объектами в игре в основном с помощь клавиатуры, мыши, джойстика. Когда на «манипуляторах» что-то двигается или нажимается, то возникают события определенных типов. Обработкой событий занимается модуль 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 ).
Рассмотрим, как это работает. Пусть в центре окна имеется круг, который можно двигать по горизонтали клавишами стрелок клавиатуры:
import pygame import sys FPS = 60 W = 700 # ширина экрана H = 300 # высота экрана WHITE = (255, 255, 255) BLUE = (0, 70, 225) sc = pygame.display.set_mode((W, H)) clock = pygame.time.Clock() # координаты и радиус круга x = W // 2 y = H // 2 r = 50 while 1: for i in pygame.event.get(): if i.type == pygame.QUIT: sys.exit() elif i.type == pygame.KEYDOWN: if i.key == pygame.K_LEFT: x -= 3 elif i.key == pygame.K_RIGHT: x += 3 sc.fill(WHITE) pygame.draw.circle(sc, BLUE, (x, y), r) pygame.display.update() clock.tick(FPS)
В цикле обработки событий теперь проверяется не только событие выхода, но также нажатие клавиш. Сначала необходимо проверить тип, потому что не у всех событий есть атрибут key . Если сразу начать проверять key , то сгенерируется ошибка по той причине, что могло произойти множество событий. Например, движение мыши, у которого нет поля key . Соответственно, попытка взять значение из несуществующего поля ( i.key ) приведет к генерации исключения.
Часто проверку и типа и клавиши записывают в одно логическое выражение ( i.type == pygame.KEYDOWN and i.key == pygame.K_LEFT ). В Python так можно делать потому, что если первая часть сложного выражения возвращает ложь, то вторая часть уже не проверяется.
Если какая-либо клавиша была нажата, то проверяется, какая именно. В данном случае обрабатываются только две клавиши. В зависимости от этого меняется значение координаты x .
Проблема данного кода в том, что при выполнении программы, чтобы круг двигался, надо постоянно нажимать и отжимать клавиши. Если просто зажать их на длительный период, то объект не будет постоянно двигаться. Он сместиться только один раз на 3 пикселя.
Так происходит потому, что событие нажатия на клавишу происходит один раз, сколь долго бы ее не держали. Это событие было забрано из очереди функцией get() и обработано. Его больше нет. Поэтому приходится генерировать новое событие, еще раз нажимая на клавишу.
Как быть, если по логике вещей надо, чтобы шар двигался до тех пор, пока клавиша зажата? Когда же она отпускается, шар должен останавливаться. Первое, что надо сделать, – это перенести изменение координаты x в основную ветку главного цикла while . В таком случае на каждой его итерации координата будет меняться, а значит шар двигаться постоянно.
Во-вторых, в цикле обработки событий нам придется следить не только за нажатием клавиши, но и ее отжатием. Когда клавиша нажимается, какая-либо переменная, играющая роль флага, должна принимать одно значение, когда клавиша отпускается эта же переменная должна принимать другое значение.
В основном теле while надо проверять значение этой переменной и в зависимости от него менять или не менять значение координаты.
import pygame import sys FPS = 60 W = 700 # ширина экрана H = 300 # высота экрана WHITE = (255, 255, 255) BLUE = (0, 70, 225) RIGHT = "to the right" LEFT = "to the left" STOP = "stop" sc = pygame.display.set_mode((W, H)) clock = pygame.time.Clock() # координаты и радиус круга x = W // 2 y = H // 2 r = 50 motion = STOP while 1: for i in pygame.event.get(): if i.type == pygame.QUIT: sys.exit() elif i.type == pygame.KEYDOWN: if i.key == pygame.K_LEFT: motion = LEFT elif i.key == pygame.K_RIGHT: motion = RIGHT elif i.type == pygame.KEYUP: if i.key in [pygame.K_LEFT, pygame.K_RIGHT]: motion = STOP sc.fill(WHITE) pygame.draw.circle(sc, BLUE, (x, y), r) pygame.display.update() if motion == LEFT: x -= 3 elif motion == RIGHT: x += 3 clock.tick(FPS)
Использовать константы не обязательно, можно сразу присваивать строки или даже числа (например, 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 – если не нажата.
Эта функция подходит не для всех случаев обработки клавиатурных событий, но в нашем подойдет. Поэтому мы можем упростить код до такого варианта:
import pygame import sys FPS = 60 W = 700 # ширина экрана H = 300 # высота экрана WHITE = (255, 255, 255) BLUE = (0, 70, 225) sc = pygame.display.set_mode((W, H)) clock = pygame.time.Clock() # координаты и радиус круга x = W // 2 y = H // 2 r = 50 while 1: for i in pygame.event.get(): if i.type == pygame.QUIT: sys.exit() sc.fill(WHITE) pygame.draw.circle(sc, BLUE, (x, y), r) pygame.display.update() keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: x -= 3 elif keys[pygame.K_RIGHT]: x += 3 clock.tick(FPS)
Можно сказать, вызов get_pressed() снимает «маску» зажатых клавиш. Мы ее снимаем на каждой итерации главного цикла. Это даже не регистрация событий как таковых.
Выражение типа keys[pygame.K_LEFT] извлекает значение из кортежа по индексу, значение которого записано в константе K_LEFT . Если извлеченное значение True , то координата меняется.
Если необходимо, чтобы событие обрабатывалось при нажатии двух и более клавиш, то работает такое логическое выражение: keys[pygame.K_LEFT] and keys[pygame.K_a] (одновременное нажатие стрелки ‘влево’ и буквы ‘a’). Однако если нужно задействовать не обычные клавиши, а модификаторы, то данный номер не проходит.
В таком случае можно вернуться к первому варианту – перебирать события в цикле for :
. elif i.type == pygame.KEYDOWN: if i.key == pygame.K_LEFT and\ (i.mod & pygame.KMOD_SHIFT): motion = LEFT .
Здесь при if будет True , если перед нажатием стрелки был зажат левый Shift . Причем обратная последовательность: сначала зажать стрелку, потом Shift не сработает. Видимо модификаторы обрабатываются библиотекой pygame несколько отлично от обычных клавиш. Допустим, если при зажатии обычных клавиш генерируется только одно событие, то для модификаторов они генерируются постоянно или хранятся до отпускания в другой очереди.
Таким образом, если первым зажимается K_LEFT , то событие сразу обрабатывается. При этом в i.mod записывается отсутствие модификатора. Поэтому условие не срабатывает.
Если же первым зажимается модификатор, то это событие не теряется и позволяет условию при if выполнится в случае нажатия при этом обычной клавиши.
Весь перечень констант pygame, соответствующих клавишам клавиатуры, смотрите в документации: https://www.pygame.org/docs/ref/key.html
Практическая работа
Измените приведенную в уроке программу так, чтобы круг с той же скоростью, т. е. постепенно, возвращался назад в исходную точку, когда клавиша отпускается.
Курс с примерами решений практических работ:
pdf-версия
X Скрыть Наверх
Pygame. Введение в разработку игр на Python
Как считать нажатие клавиши в Python программе?
Мне нужна замена input(), чтобы при нажатии клавиш W и S изменялось значение selected. Я знаю, как изменить значение переменной, но не знаю как считать нажатие на клавишу. Можете ли вы подсказать, как это сделать?
Отслеживать
justfollowyourdreams
задан 21 июл 2022 в 23:35
justfollowyourdreams justfollowyourdreams
34 4 4 бронзовых знака
Пожалуйста, исправьте вопрос, чтобы он отражал конкретную проблему с достаточным количеством деталей для возможности дать адекватный ответ.
Как определить нажатия клавиш на клавиатуре с помощью Python
В Python можно использовать библиотеку keyboard для определения нажатий клавиш на клавиатуре.
Для начала нужно установить эту библиотеку, используя команду в терминале:

Затем можно использовать следующий код для определения нажатий клавиш:

В этом примере, когда пользователь нажимает клавишу, вызывается функция on_press(), которая выводит имя нажатой клавиши на консоль. Когда пользователь отпускает клавишу, вызывается функция on_release(), которая также выводит имя отпущенной клавиши на консоль.
Функции on_press() и on_release() можно изменить так, чтобы они выполняли другие действия вместо вывода на консоль.
Вот ещё несколько примеров того, как можно использовать библиотеку keyboard для обработки нажатий клавиш:
— Симуляция нажатия клавиши:

— Обработка определённых клавиш:

— Остановка программы при нажатии определённой комбинации клавиш:

Эти примеры демонстрируют лишь небольшую часть возможностей библиотеки keyboard. Более подробную информацию можно найти в официальной документации: https://github.com/boppreh/keyboard.
Поддержать


203 поста 2.6K подписчиков
Подписаться Добавить пост
Правила сообщества
Просьба уважать друг друга.
8 месяцев назад
А на питоне еще никто не написал бибилотеку для hello world?
8 месяцев назад
Я так понимаю, это такой «маленький» намек на возможности создания кейлогера.
раскрыть ветку
7 месяцев назад
@SupportCommunity, разблокируй пожалуйста сообщество @haccking, аккаунт администратора разблокирован.
8 месяцев назад
Скажите, я правильно понимаю, что в страничку можно встроить код который будет отслеживать нажатия клавиш пользователя без его ведома даже будучи открытым в неактивной сейчас вкладке браузера?
раскрыть ветку
8 месяцев назад
Лет 17 дадут. Если использовать .
раскрыть ветку
ещё комментарий
Похожие посты
1 день назад

Так станет проще работать

1 день назад

Как проклятие невидимой стены ждало меня 20 лет
- Автор:kesn
- Больше интересных фото и комментариев воригинале материала

Когда на меня накатывает хандра, я бросаю всё и пилю свой игровой движок. Это неблагодарное занятие, но меня прёт.
В самом начале у меня были такие планы: вжух-вжух, щас возьму ведро, накидаю туда всяких библиотек для графики, физики и звуков, добавлю сетевую библиотеку по вкусу, перемешаю всё с какой-нибудь системой сообщений, и готово. Приключение на 15 минут.
И вот я тут спустя 5 лет.
Ладно, если быть честным, то я почти не уделял времени разработке, потому что постоянно спотыкался на всяких бесящих меня ошибках: то сериализация не работает с наследованием, то потоки не хотят нормально разделять память, то обновление языка ломало совместимость… Я могу, блин, целую Камасутру написать про соитие с игровым движком. Все эти ошибки сильно демотивируют, потому что хочется уже наконец-то заняться делом, а не ковыряться с байтиками.
Это не моё видео, но оно очень точно передаёт, как у меня происходит разработка:
С другой стороны, конечно, когда эти проблемы решаешь, чувствуешь себя богом и королём жизни, и после этого ты вроде как опять хочешь программировать. И даже кажется, что это была последняя трудность. Ха-ха, наивный. Но мне это нравится. Типа как альпинисты идут в гору и страдают, когда можно пойти в бар с друзьями и попить пивко. Каждому своё.
Ну и вот про одну такую ошибку я хотел поговорить. Есть такой движок — ODE (Open Dynamics Engine). Он появился где-то в палеолите, динозавры его накодили, от документации остались только царапины на скалах. Но он работает, он простой в использовании, и у него есть сишные заголовки, поэтому я мог просто написать враппер на Nim и использовать его в своём движке. В Nim вообще ни хрена нету, поэтому канонический способ — это взять какую-нибудь библиотеку из Си, научиться её вызывать, а потом говорить всем, что ты написал крутую программу на Nim.
Итак, сначала я просто добавил кубики на сцену и отрисовал их. Физический движок был в полной гармонии с графическим, и когда мне графика отрисовывала, что я приближаюсь к кубу и толкаю его, кубик действительно отлетал и вращался. Короче говоря, всё шло так, как я и планировал.
Разумеется, если вы не планируете делать Minecraft, то вам может понадобиться что-то поинтересней, чем кубик. В ODE есть специальный класс Trimesh, который как раз позволяет вам сделать сложную геометрию. Фактически, вы можете создать любое тело из набора треугольников. Типа такого:

Машина глупая, поэтому мы не можем ей сказать «нарисуй зайца», мы можем ей сказать «вот такие есть вершины, соедини их вот так-то, и это будет называться зайцем». Я, естественно, не стал рубить с плеча и решил вместо зайца сделать простой треугольник и проверить, что всё корректно с ним работает.

Я создал треугольник, он успешно отрисовался на сцене, я начал ходить по миру… и обнаружил, что треугольник не в том месте, где нарисован, а где-то непонятно где.
Так и появилась эта дурацкая невидимая стена.
Фактически, я мог ходить по сцене, и где-то я упирался в тот самый треугольник, который вообще-то должен был быть там, где нарисован. Я в принципе даже что-то такое и ожидал, потому что, как я уже где-то писал, только три раза в своей жизни я написал код, который заработал с первого раза. Наверняка я где-то перепутал координату — вместо X передал Y, или наоборот, ну что-нибудь такое. Эти программисты, вы знаете!
Отрисовать этот треугольник я не мог, потому что координаты были правильные, графический движок всё отрисовывал правильно, но вот физический движок как-то неправильно интерпретировал мои правильные данные. Поэтому я стал ходить по миру и пытаться определить очертания этой невидимой стены. В конце концов я её нашёл (она была достаточно странной), и я решил немного подвигать треугольник, чтобы посмотреть, как он влияет на эту стену. Казалось бы, если я просто где-то перепутал координаты, то подвинув треугольник, я немножко подвину эту стену. Но хрен мне там! Стена исчезала и появлялась совершенно случайно, прыгала далеко даже от малейшего изменения координат, и я не мог понять, почему.
И тут я вспомнил эту недалёкую женщину из заЩИТников! Если кто не знает, она сделалась невидимой и решила спрятаться в дожде. Отличный план, надёжный, как швейцарские часы:

Я подумал, что это прям мой случай, и решил полить свою стену дождём, чтобы увидеть её. Дождя у меня не было, зато были кубики, поэтому я создал штук 50 и стал кидать их вниз. При касании стены они к ней прилипали, и я мог видеть её очертания. А когда что-то видишь — отлаживать в разы легче!

Что ж… Это была хорошая попытка понять, по какому закону стена появляется в том месте, где она появляется, но это мне ничего не дало. Даже видя эту стену, я не находил никакой закономерности.
Если нужно где-то найти таких же неудачников, как я, то самое лучшее место для этого — интернет. И я нашёл его — единственного человека, который отстрадал своё и рассказал об этом. Представляете, в 2006 году у какого-то чувака из Германии пятая точка горела точно так же, как у меня сейчас! Не знаю, что он выкурил (похоже, что исходники), но, ОКАЗЫВЕТСЯ, физический движок ожидает от вас трёхмерные точки, но передавать их надо как четырёхмерный вектор, просто в четвертой координате надо поставить мусор, типа так: [x1, y1, z1, 0, x2, y2, z2, 0, . ]. Скажите, как по const dReal* Vertices я должен понять, что там ждут в гости четырёхмерные вершины?

За что я люблю опенсорс — можно всегда докопаться до истоков всего. Я полез в исходники, и вот что обнаружил.
В 2003 году пришёл Russel Smith и добавил всю эту функциональность с trimesh collisions, в том числе интересующую меня строчку:

Тут всё понятно, потому что в определении чётко говорится, что dVector3 — это четырёхмерный вектор (есть некий шарм в этой логике).
А потом через пару месяцев врывается Erwin Coumans и переписывает так, чтобы тип был непонятен:


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

Вообще этот пост был задуман как развлекательный, типа «смотрите, погромист опять страдает, хахаха». Но мне кажется, что он поднимает достаточно глубокую проблему: как только вы выкладываете код, он начинает свой долгий путь сквозь время. Никто не знает, когда и кто его будет читать — может, вы или ваш коллега через пару месяцев, может, тысячи независимых разработчиков через пару лет, может, какой-то парень с горящим продом.
Получается такой вот эффект бабочки, как с этой невидимой стеной. Поэтому когда вы в следующий раз сядете писать код, представьте, что какой-то разраб через 20 лет будет в нём разбираться, и, пожалуйста, постарайтесь сделать жизнь этого чувака хоть чутоку легче. Ведь однажды этим кем-то можете оказаться вы сами.
Не только лишь все могут смотреть в будущее, но вы сможете, если подпишетесь на мой уютненький канал Блог Погромиста.
А ещё я держу все свои яйца в одной корзине (в смысле, все проекты у одного облачного провайдера) — Timeweb. Поэтому нагло рекламирую то, чем сам пользуюсь — вэлкам.
Показать полностью 9 1
2 дня назад

Если ты ростом ниже 185, то даже знание плюсов тебе не поможет

4 дня назад

Интересно, а сколько разработчиков в мире используют только свой код?

Показать полностью 1
10 дней назад

Гилфойл ерунды не скажет

Показать полностью 1
10 дней назад

Что заставляет программистов писать вирусы
Материал был взят и переведен с Рэддита. Приятного прочтения!
1. В 7 классе я ходил на кружок программирования, который фактически превратился в кружок по созданию вредоносных программ. Мы с другом написали программу, которая постоянно открывала на компьютере один сайт для взрослых и врубала звук на полную мощность. У нескольких человек этот сайт открылся прямо на уроке. Было весело.
2. Я написал эту программу ради азарта. Это был аддон для Воркрафта. Он запускался, когда персонаж входил в игру. А потом персонаж получал приглашение в гильдию от игрока с заряженным аккаунтом и сам становился главой гильдии. После этого можно было идти в игровой банк и забрать оттуда все ценное. Написать код было просто, но вот протестировать его работу с помощью приемов социальной инженерии очень сложно. Но мне повезло с первого раза. Прилив адреналина был колоссальным, но я также понимал, что меня, скорее всего, забанят в этой игре. Моей следующей целью была высшая рейдерская гильдия на сервере. Чтобы убедить лидера гильдии участвовать в моем тестировании, понадобился час разговоров по скайпу. Он попался на крючок, и все почти получилось. Я знал, что у этой гильдии игровых ценностей на сотни тысяч долларов. Глава установил аддон, но потом я понял, что он вошел через альтернативного персонажа, не имевшего доступ к богатству гильдии. Так у меня все провалилось. Меня выгнали из гильдии и забанили. Позже мне удалось вернуть свой аккаунт, но без тех ценностей, которые я награбил раньше.
3. В юности я создал несколько троянов удаленного доступа. С их помощью воровал аккаунты в разных играх и продавал их в интернете. Когда я впервые запустил троян, было 200 загрузок и 90 заражений. Половину угнанных аккаунтов я отдал другу, который помогал писать программу. Потом продал два акка и купил попугая, потому что люблю птиц. А потом старший брат объяснил, что все это плохо и незаконно, и я остановился.
4. Раньше вирусы создавались ради демонстрации крутости и были не особо вредными, это во времена Дос и вплоть до Виндовс XP. Потом появились черви для кражи паролей. Потом ботнеты, а они уже только ради денег. Они крадут данные, пароли, откровенные фотки, все подряд, для последующей продажи. Потом киберпреступники научились использовать сторонние компьютеры для майнинга, взлома сайтов и прочего дерьма.
5. У меня есть друг, который мошенничал с кредитками, крал личные данные, информацию с компьютеров, используя для этого кейлоггер, замаскированный под ссылку для скачивания. В школе он начал продавать вещи и одежду всем, включая меня. А через два года за ним приехали из ФБР и увезли, хотя он и был несовершеннолетним. Ему пришлось заключить сделку и вернуть товаров на 50 тысяч долларов. А еще он взломал главу отдела безопасности Xbox, про это есть видео на ютубе.
6. Когда-то я любила троллить людей в чатах, рассказывая, что у меня есть постеры с Бритни Спирс, но для их закачки надо открыть файл, который я пришлю. Так я получала доступ к компьютерам жертв. Могла полностью просматривать жесткий диск, скачивать, что мне надо, удалять с компьютера файлы. Однажды я стала удалять кучу всего с компьютера парня, с которым в это время общалась в чате, и он заплакал. Мне стало жаль его, и я прекратила, и больше никогда этим не занималась.
7. Я занимался этим ради денег. Уже в старших классах я занимался черным СЕО и восстановлением сайтов. Потом я познакомился с парнем, который придумал, как через песню из альбома вшить ссылку. Эта программа случайным образом одну из песен на компьютере превращала в ссылку. Когда человек хотел прослушать ее, всплывала надпись, что надо скачать кодек. Он скачивал, и я получал 10 центов. Свою ссылку мы размещали на торрентах, скачиваний было много, денег хватало. Позже я стал нанимать индусов, чтобы они распространяли по торрентам файл с этой ссылкой. Мне тогда было 16, и я за месяц заработал 4 тысячи долларов. Это было круто, учитывая, что на черном СЕО и сайтах у меня выходило около тысячи в месяц. А через несколько месяцев все пошло наперекосяк, и я стал заниматься другими делами.
Как считывать нажатие клавиш java
Cчитать нажатие клавиш можно с помощью интерфейса KeyListener :
import javax.swing.*; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; public class App public static void main(String[] args) KeyListener listener = new KeyListener() @Override public void keyTyped(KeyEvent keyEvent) char key = keyEvent.getKeyChar(); System.out.println("Нажата и отпущена клавиша - " + key); > @Override public void keyPressed(KeyEvent keyEvent) char key = keyEvent.getKeyChar(); System.out.println("Нажата клавиша - " + key); > @Override public void keyReleased(KeyEvent keyEvent) char key = keyEvent.getKeyChar(); System.out.println("Отпущена клавиша - " + key); > >; JTextField textField = new JTextField(20); textField.addKeyListener(listener); JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(textField, BorderLayout.CENTER); frame.pack(); frame.setVisible(true); > >
