События мыши

В Pygame обрабатываются три типа событий мыши:

Какая именно кнопка была нажата, записывается в другое свойство события – button. Для левой кнопки это число 1, для средней – 2, для правой – 3, для прокручивания вперед – 4, для прокручивания назад – 5. У событий MOUSEMOTION вместо button используется свойство buttons, в которое записывается состояние трех кнопок мыши (кортеж из трех элементов).

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

Таким образом, если вы нажали правую кнопку мыши точно в середине окна размером 200x200, то будет создан объект типа Event с полями event.type = pygame.MOUSEBUTTONDOWN, event.button = 3, event.pos = (100, 100).

У событий MOUSEMOTION есть еще один атрибут – rel. Он показывает относительное смещение по обоим осям. С помощью него, например, можно отслеживать скорость движения мыши.

Код ниже создает фигуры в местах клика мыши. Нажатие средней кнопки очищает поверхность.

import pygame as pg
import sys
 
WHITE = (255, 255, 255)
RED = (225, 0, 50)
GREEN = (0, 225, 0)
BLUE = (0, 0, 225)
 
sc = pg.display.set_mode((400, 300))
sc.fill(WHITE)
pg.display.update()
 
while 1:
    for i in pg.event.get():
        if i.type == pg.QUIT:
            sys.exit()
        if i.type == pg.MOUSEBUTTONDOWN:
            if i.button == 1:
                pg.draw.circle(sc, RED, i.pos, 20)
                pg.display.update()
            elif i.button == 3:
                pg.draw.circle(sc, BLUE, i.pos, 20)
                pg.draw.rect(sc, GREEN,
                             (i.pos[0] - 10,
                              i.pos[1] - 10, 20, 20))
                pg.display.update()
            elif i.button == 2:
                sc.fill(WHITE)
                pg.display.update()
 
    pg.time.delay(20)

В функции модуля draw вместо координат передается значение поля pos события. В pos хранятся координаты клика. В случае с функцией rect() извлекаются отдельные элементы кортежа pos. Вычитание числа 10 используется для того, чтобы середина квадрата, сторона которого равна 20-ти пикселям, точно соответствовала месту клика. Иначе в месте клика будет находиться верхний левый угол квадрата.

Функцию update() не обязательно вызывать три раза в ветках if-elif-elif. Ее можно вызвать в основном теле главного цикла. Однако в этом случае, когда кликов не происходит, она будет выполнять зря.

Также как в случае с клавиатурой в pygame есть свой модуль для событий мыши. Если нужно отслеживать длительное зажатие ее кнопок, следует воспользоваться функцией get_pressed() модуля pygame.mouse. Здесь же есть функция для считывания позиции курсора – get_pos(). Следующий код рисует синий круг в местах клика левой кнопкой мыши:

import pygame as pg
import sys
 
WHITE = (255, 255, 255)
BLUE = (0, 0, 225)
 
sc = pg.display.set_mode((400, 300))
sc.fill(WHITE)
pg.display.update()
 
while 1:
    for i in pg.event.get():
        if i.type == pg.QUIT:
            sys.exit()
 
    pressed = pg.mouse.get_pressed()
    pos = pg.mouse.get_pos()
    if pressed[0]:
        pg.draw.circle(sc, BLUE, pos, 5)
        pg.display.update()
 
    pg.time.delay(20)
 

Функция mouse.get_pressed() возвращает трехэлементный кортеж. Первый элемент (с индексом 0) соответствует левой кнопке мыши, второй – средней, третий – правой. Если значение элемента равно True, значит, кнопка нажата. Если False, значит – нет. Так выражение pressed[0] есть истина, если под нулевым индексом содержится True.

Чтобы скрыть курсор (например, в игре, где управление осуществляется исключительно клавиатурой), надо воспользоваться функцией pygame.mouse.set_visible(), передав в качестве аргумента False.

Так можно привязать графический объект к курсору (в данном случае привязывается квадрат):

import pygame as pg
import sys
 
WHITE = (255, 255, 255)
BLUE = (0, 0, 225)
 
pg.init()
sc = pg.display.set_mode((400, 300))
sc.fill(WHITE)
pg.display.update()
 
pg.mouse.set_visible(False)
 
while 1:
    for i in pg.event.get():
        if i.type == pg.QUIT:
            sys.exit()
 
    sc.fill(WHITE)
 
    if pg.mouse.get_focused():
        pos = pg.mouse.get_pos()
        pg.draw.rect(
            sc, BLUE, (pos[0] - 10,
                       pos[1] - 10,
                       20, 20))
 
    pg.display.update()
    pg.time.delay(20)
 

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

Функция get_focused() проверяет, находится ли курсор в фокусе окна игры. Если не делать эту проверку, то при выходе курсора за пределы окна, квадрат будет постоянно прорисовываться у края окна, где произошел выход, т. е. не будет исчезать.

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

Напишите код в котором имитируется полет снаряда (пусть его роль сыграет круг) в место клика мышью. Снаряд должен вылетать из нижнего края окна и лететь вверх, т. е. изменяться должна только координата y. Пока летит один, другой не должен появляться. Когда снаряд достигает цели, должен имитировать взрыв, например, в этом месте прорисовываться квадрат.

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


Pygame. Введение в разработку игр на Python




Все разделы сайта