Как проверить работу pygame
Перейти к содержимому

Как проверить работу pygame

  • автор:

python pygame.get_pressed() проверка нажатой клавиши дает два срабатывания

При работе программы после нажатия клавиши SPACE появляются два сообщения о нажатии клавиши SPACE. Вот, собственно и вопрос: что надо добавить/изменить? Заранее благодарен.

Отслеживать
задан 24 мар 2022 в 8:51
51 5 5 бронзовых знаков
два раза срабатывает, потому что учитывается нажатие клавиши и отжатие.
24 мар 2022 в 9:12
Спасибо! Буду фильровать события.
24 мар 2022 в 11:29
@Boris Как в итоге изменили код, чтобы всё работало как надо? Не пойму как лучше отфильтровать
7 фев 2023 в 14:36

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Вот как вариант:

from pynput.keyboard import Listener as Kl, Key import datetime rand = '' def key_pressed(key): global rand, path a = str(key).replace("Key.", "") if a.find("'") == -1: a = "'" + a + "'" time = str(datetime.datetime.today())[11:-4] time = time.replace(":", ".") string = f' - pressed ' print(string) if key == Key.esc: return False def key_released(key): pass with Kl(on_press=key_pressed, on_released=key_released) as listener: listener.join() 

Отслеживать
ответ дан 24 мар 2022 в 9:19
1,261 1 1 золотой знак 4 4 серебряных знака 17 17 бронзовых знаков
Спасибо, унесу в норку; но, поскольку у меня pygame, буду фильтровать события.
24 мар 2022 в 11:27

  • python
  • pygame
    Важное на Мете
Похожие

Подписаться на ленту

Лента вопроса

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.4.30.8412

Библиотека Pygame / Часть 1. Введение

Это первая часть серии руководств «Разработка игр с помощью Pygame». Она предназначена для программистов начального и среднего уровней, которые заинтересованы в создании игр и улучшении собственных навыков кодирования на Python.

Код в уроках был написан на Python 3.7 и Pygame 1.9.6

Что такое Pygame?

Pygame — это «игровая библиотека», набор инструментов, помогающих программистам создавать игры. К ним относятся:

  • Графика и анимация
  • Звук (включая музыку)
  • Управление (мышь, клавиатура, геймпад и так далее)

Игровой цикл

В сердце каждой игры лежит цикл, который принято называть «игровым циклом». Он запускается снова и снова, делая все, чтобы работала игра. Каждый цикл в игре называется кадром.

В каждом кадре происходит масса вещей, но их можно разбить на три категории:

Речь идет обо всем, что происходит вне игры — тех событиях, на которые она должна реагировать. Это могут быть нажатия клавиш на клавиатуре, клики мышью и так далее.

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

В этом шаге все выводится на экран: фоны, персонажи, меню. Все, что игрок должен видеть, появляется на экране в нужном месте.

Время

Еще один важный аспект игрового цикла — скорость его работы. Многие наверняка знакомы с термином FPS, который расшифровывается как Frames Per Second (или кадры в секунду). Он указывает на то, сколько раз цикл должен повториться за одну секунду. Это важно, чтобы игра не была слишком медленной или быстрой. Важно и то, чтобы игра не работала с разной скоростью на разных ПК. Если персонажу необходимо 10 секунд на то, чтобы пересечь экран, эти 10 секунд должны быть неизменными для всех компьютеров.

Создание шаблона Pygame

Теперь, зная из каких элементов состоит игра, можно переходить к процессу написания кода. Начать стоит с создания простейшей программы pygame, которая всего лишь открывает окно и запускает игровой цикл. Это отправная точка для любого проекта pygame.

В начале программы нужно импортировать необходимые библиотеки и задать базовые переменные настроек игры:

# Pygame шаблон - скелет для нового проекта Pygame import pygame import random WIDTH = 360 # ширина игрового окна HEIGHT = 480 # высота игрового окна FPS = 30 # частота кадров в секунду 

Дальше необходимо открыть окно игры:

# создаем игру и окно pygame.init() pygame.mixer.init() # для звука screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("My Game") clock = pygame.time.Clock() 

pygame.init() — это команда, которая запускает pygame. screen — окно программы, которое создается, когда мы задаем его размер в настройках. Дальше необходимо создать clock , чтобы убедиться, что игра работает с заданной частотой кадров.

Теперь необходимо создать игровой цикл:

# Цикл игры running = True while running: # Ввод процесса (события) # Обновление # Визуализация (сборка) 

Игровой цикл — это цикл while , контролируемый переменной running . Если нужно завершить игру, необходимо всего лишь поменять значение running на False . В результате цикл завершится. Теперь можно заполнить каждый раздел базовым кодом.

Раздел рендеринга (отрисовки)

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

Таблица цветов RGB

Экраны компьютеров сделаны из пикселей, каждый из которых содержит 3 элемента: красный, зеленый и синий. Цвет пикселя определяется тем, как горит каждый из элементов:

Каждый из трех основных цветов может иметь значение от 0 (выключен) до 255 (включен на 100%), так что для каждого элемента есть 256 вариантов.

Узнать общее количество отображаемых компьютером цветов можно, умножив:

>>> 256 * 256 * 256 16,777,216 

Теперь, зная, как работают цвета, можно задать их в начале программ:

# Цвета (R, G, B) BLACK = (0, 0, 0) WHITE = (255, 255, 255) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) 

А после этого — заполнить весь экран.

 # Рендеринг screen.fill(BLACK) 

Но этого недостаточно. Дисплей компьютера работает не так. Изменить пиксель — значит передать команду видеокарте, чтобы она передала соответствующую команду экрану. По компьютерным меркам это очень медленный процесс. Если нужно нарисовать на экране много всего, это займет много времени. Исправить это можно оригинальным способом, который называется — двойная буферизация. Звучит необычно, но вот что это такое.

Представьте, что у вас есть двусторонняя доска, которую можно поворачивать, показывая то одну, то вторую сторону. Одна будет дисплеем (то, что видит игрок), а вторая — оставаться скрытой, ее сможет «видеть» только компьютер. С каждым кадром рендеринг будет происходить на задней части доски. Когда отрисовка завершается, доска поворачивается и ее содержимое демонстрируется игроку.

А это значит, что процесс отрисовки происходит один раз за кадр, а не при добавлении каждого элемента.

В pygame это происходит автоматически. Нужно всего лишь сказать доске, чтобы она перевернулась, когда отрисовка завершена. Эта команда называется flip() :

 # Рендеринг screen.fill(BLACK) # после отрисовки всего, переворачиваем экран pygame.display.flip() 

Главное — сделать так, чтобы функция flip() была в конце. Если попытаться отрисовать что-то после поворота, это содержимое не отобразится на экране.

Раздел ввода (событий)

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

События происходят постоянно. Что, если игрок нажимает кнопку прыжка во время отрисовки? Это нельзя игнорировать, иначе игрок будет разочарован. Для этого pygame сохраняет все события, произошедшие с момента последнего кадра. Даже если игрок будет лупить по кнопкам, вы не пропустите ни одну из них. Создается список, и с помощью цикла for можно пройтись по всем из них.

 for event in pygame.event.get(): # проверить закрытие окна if event.type == pygame.QUIT: running = False 

В pygame много событий, на которые он способен реагировать. pygame.QUIT — событие, которое стартует после нажатия крестика и передает значение False переменной running , в результате чего игровой цикл заканчивается.

Контроль FPS

Пока что нечего поместить в раздел Update (обновление), но нужно убедиться, что настройка FPS контролирует скорость игры. Это можно сделать следующим образом:

while running: # держим цикл на правильной скорости clock.tick(FPS) 

Команда tick() просит pygame определить, сколько занимает цикл, а затем сделать паузу, чтобы цикл (целый кадр) длился нужно время. Если задать значение FPS 30, это значит, что длина одного кадра — 1/30, то есть 0,03 секунды. Если цикл кода (обновление, рендеринг и прочее) занимает 0,01 секунды, тогда pygame сделает паузу на 0,02 секунды.

Итог

Наконец, нужно убедиться, что когда игровой цикл завершается, окно игры закрывается. Для этого нужно поместить функцию pygame.quit() в конце кода. Финальный шаблон pygame будет выглядеть вот так:

# Pygame шаблон - скелет для нового проекта Pygame import pygame import random WIDTH = 360 HEIGHT = 480 FPS = 30 # Задаем цвета WHITE = (255, 255, 255) BLACK = (0, 0, 0) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) # Создаем игру и окно pygame.init() pygame.mixer.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("My Game") clock = pygame.time.Clock() # Цикл игры running = True while running: # Держим цикл на правильной скорости clock.tick(FPS) # Ввод процесса (события) for event in pygame.event.get(): # check for closing window if event.type == pygame.QUIT: running = False # Обновление # Рендеринг screen.fill(BLACK) # После отрисовки всего, переворачиваем экран pygame.display.flip() pygame.quit() 

Ура! У вас есть рабочий шаблон Pygame. Сохраните его в файле с понятным названием, например, pygame_template.py , чтобы можно было использовать его каждый раз при создании нового проекта pygame.

В следующем руководстве этот шаблон будет использован как отправная точка для изучения процесса отрисовки объектов на экране и их движения.

Как проверить работу pygame

pygame.mouse

# Взято из PR-темы husano896 (слегка изменено) import pygame from pygame.locals import * pygame.init() screen = pygame.display.set_mode((640, 480)) clock = pygame.time.Clock() def main(): while True: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() return elif event.type == MOUSEWHEEL: print(event) print(event.x, event.y) print(event.flipped) print(event.which) # может получить доступ к свойствам с помощью # правильное обозначение (например: event.y) clock.tick(60) # Запускаем игру: main()

pygame.mouse.get_pressed()

pygame.mouse.get_pos()

get_pos() -> (x, y)

get_rel() -> (x, y)

set_pos([x, y]) -> None

set_visible( bool ) -> bool

get_visible() -> bool

pygame.mouse.get_focused()

get_focused() -> bool

set_cursor(pygame.cursors.Cursor) -> None

set_cursor(константа) -> None

pygame.mouse.get_cursor()

get_cursor() -> pygame.cursors.Cursor

Как обрабатывать события от мыши

То в консоли мы увидим кортеж из координат положения мыши относительно клиентской области окна. То есть, свойство pos хранит координаты мыши и мы ими всегда можем воспользоваться. Если вместо атрибута pos записать атрибут rel:

print("Смещение мыши: ", event.rel)

то увидим относительные смещения курсора мыши (относительно положения в предыдущем событии MOUSEMOTION). Причем, свойство rel существует только для события pygame.MOUSEMOTION. Давайте теперь рассмотрим программу, которая позволяет рисовать в окне прямоугольник с помощью мыши. Она будет следующей:

flStartDraw = False sp = ep = None sc.fill(WHITE) pygame.display.update() while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: exit() elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: flStartDraw = True sp = event.pos elif event.type == pygame.MOUSEMOTION: if flStartDraw: pos = event.pos width = pos[0] - sp[0] height = pos[1] - sp[1] sc.fill(WHITE) pygame.draw.rect(sc, RED, pygame.Rect(sp[0], sp[1], width, height)) pygame.display.update() elif event.type == pygame.MOUSEBUTTONUP and event.button == 1: flStartDraw = False clock.tick(FPS)

Ее работа вполне очевидна. При нажатии на левую кнопку мыши мы устанавливаем флаг flStartDraw в значение True, т.е. включаем режим рисования при перемещении мыши. Соответственно, при событии MOUSEMOTION срабатывает условие и рисуется прямоугольник от начальной координаты sp до текущей позиции pos. При отпускании левой кнопки мыши, переменная flStartDraw становится равной False. Однако, обратите внимание, события MOUSEBUTTONDOWN и MOUSEBUTTONUP срабатывают только один раз. То есть, если все время держать нажатой кнопку мыши, то произойдет только одно событие MOUSEBUTTONDOWN. А вот событие MOUSEMOTION происходит постоянно при каждом перемещении курсора мыши в клиентской области окна. Если на каждой итерации главного цикла нужно определять: нажата ли какая-либо кнопка мыши, то следует использовать модуль pygame.mouse в котором, в частности, имеется функция: pygame.mouse.get_pressed() Она работает аналогично функции pygame.key.get_pressed() – определения нажатия клавиш, о которой мы говорили на прошлом занятии. Здесь все то же самое, только с кнопками мыши. На выходе pygame.mouse.get_pressed() выдает кортеж с тремя значениями: Единица соответствует нажатой кнопке в соответствии с ее индексом:

  • 0 – левая кнопка;
  • 1 – центральная;
  • 2 – правая кнопка.

Перепишем предыдущую программу с использованием этой функции:

sp = None sc.fill(WHITE) pygame.display.update() while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: exit() pressed = pygame.mouse.get_pressed() if pressed[0]: pos = pygame.mouse.get_pos() if sp is None: sp = pos width = pos[0] - sp[0] height = pos[1] - sp[1] sc.fill(WHITE) pygame.draw.rect(sc, RED, pygame.Rect(sp[0], sp[1], width, height)) pygame.display.update() else: sp = None clock.tick(FPS)

Смотрите, мы здесь вначале проверяем нажатие левой кнопки мыши (индекс 0) и если величина sp равна None, то начальной позиции для рисования прямоугольника еще нет и ее нужно приравнять текущей позиции курсора. Текущая позиция определяется с помощью функции get_pos(). Затем, удерживая нажатой левую кнопку и перемещая мышь, мы будем получать другие значения pos, но начальная позиция sp будет неизменной. В результате выполняется рисование прямоугольника. При отпускании левой кнопки, значение sp вновь становится равным None. Наконец, можно скрыть курсор мыши с помощью функции: pygame.mouse.set_visible(False) И отобразить свой собственный, например, так:

pygame.mouse.set_visible(False) while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: exit() sc.fill(WHITE) pos = pygame.mouse.get_pos() if pygame.mouse.get_focused(): pygame.draw.circle(sc, BLUE, pos, 7) pressed = pygame.mouse.get_pressed() if pressed[0]: if sp is None: sp = pos width = pos[0] - sp[0] height = pos[1] - sp[1] pygame.draw.rect(sc, RED, pygame.Rect(sp[0], sp[1], width, height)) else: sp = None pygame.display.update() clock.tick(FPS)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *