Обнаружение щелчка мыши Pygame
Мне было интересно, как написать код, который обнаруживал бы щелчок мышью по спрайту. Например:
if #Function that checks for mouse clicked on Sprite:
print ("You have opened a chest!")
Переведено автоматически
Ответ 1
Я предполагаю, что в вашей игре есть основной цикл, и все ваши спрайты находятся в списке с именем sprites
.
В вашем основном цикле получите все события и проверьте наличие события MOUSEBUTTONDOWN
or MOUSEBUTTONUP
.
while ... # your main loop
# get all events
ev = pygame.event.get()
# proceed events
for event in ev:
# handle MOUSEBUTTONUP
if event.type == pygame.MOUSEBUTTONUP:
pos = pygame.mouse.get_pos()
# get a list of all sprites that are under the mouse cursor
clicked_sprites = [s for s in sprites if s.rect.collidepoint(pos)]
# do something with the clicked sprites...
Таким образом, в основном вам приходится самостоятельно проверять наличие щелчка по спрайту на каждой итерации основного цикла. Вам нужно будет использовать mouse.get_pos() и rect.collidepoint().
Pygame не предлагает программирование, управляемое событиями, как, например, cocos2d.
Другим способом было бы проверить положение курсора мыши и состояние нажатых кнопок, но у этого подхода есть некоторые проблемы.
if pygame.mouse.get_pressed()[0] and mysprite.rect.collidepoint(pygame.mouse.get_pos()):
print ("You have opened a chest!")
Вам придется ввести какой-то флаг, если вы рассматривали этот случай, поскольку в противном случае этот код будет печатать "Вы открыли сундук!" на каждой итерации основного цикла.
handled = False
while ... // your loop
if pygame.mouse.get_pressed()[0] and mysprite.rect.collidepoint(pygame.mouse.get_pos()) and not handled:
print ("You have opened a chest!")
handled = pygame.mouse.get_pressed()[0]
Конечно, вы можете создать подкласс Sprite
и добавить метод, вызываемый is_clicked
следующим образом:
class MySprite(Sprite):
...
def is_clicked(self):
return pygame.mouse.get_pressed()[0] and self.rect.collidepoint(pygame.mouse.get_pos())
Итак, ИМХО, лучше использовать первый подход.
Ответ 2
MOUSEBUTTONDOWN
Событие происходит один раз, когда вы нажимаете кнопку мыши, и MOUSEBUTTONUP
событие происходит один раз, когда кнопка мыши отпущена. У pygame.event.Event()
объекта есть два атрибута, которые предоставляют информацию о событии мыши. pos
это кортеж, который хранит позицию, по которой был произведен щелчок. button
хранит кнопку, по которой был произведен щелчок. С каждой кнопкой мыши связано значение. Например, значение атрибутов равно 1, 2, 3, 4, 5 для левой кнопки мыши, средней кнопки мыши, правой кнопки мыши, колесика мыши вверх соответственно, колесика мыши вниз. При нажатии нескольких клавиш происходит несколько событий нажатия кнопок мыши. Дополнительные пояснения можно найти в документации модуля pygame.event
.
Используйте rect
атрибут pygame.sprite.Sprite
объекта и collidepoint
метод, чтобы определить, был ли нажат спрайт. Передайте список событий update
методуpygame.sprite.Group
, чтобы вы могли обрабатывать события в классе Sprite:
class SpriteObject(pygame.sprite.Sprite):
# [...]
def update(self, event_list):
for event in event_list:
if event.type == pygame.MOUSEBUTTONDOWN:
if self.rect.collidepoint(event.pos):
# [...]
my_sprite = SpriteObject()
group = pygame.sprite.Group(my_sprite)
# [...]
run = True
while run:
event_list = pygame.event.get()
for event in event_list:
if event.type == pygame.QUIT:
run = False
group.update(event_list)
# [...]
Минимальный пример: repl.it/@Rabbid76/PyGame-MouseClick
import pygame
class SpriteObject(pygame.sprite.Sprite):
def __init__(self, x, y, color):
super().__init__()
self.original_image = pygame.Surface((50, 50), pygame.SRCALPHA)
pygame.draw.circle(self.original_image, color, (25, 25), 25)
self.click_image = pygame.Surface((50, 50), pygame.SRCALPHA)
pygame.draw.circle(self.click_image, color, (25, 25), 25)
pygame.draw.circle(self.click_image, (255, 255, 255), (25, 25), 25, 4)
self.image = self.original_image
self.rect = self.image.get_rect(center = (x, y))
self.clicked = False
def update(self, event_list):
for event in event_list:
if event.type == pygame.MOUSEBUTTONDOWN:
if self.rect.collidepoint(event.pos):
self.clicked = not self.clicked
self.image = self.click_image if self.clicked else self.original_image
pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
sprite_object = SpriteObject(*window.get_rect().center, (128, 128, 0))
group = pygame.sprite.Group([
SpriteObject(window.get_width() // 3, window.get_height() // 3, (128, 0, 0)),
SpriteObject(window.get_width() * 2 // 3, window.get_height() // 3, (0, 128, 0)),
SpriteObject(window.get_width() // 3, window.get_height() * 2 // 3, (0, 0, 128)),
SpriteObject(window.get_width() * 2// 3, window.get_height() * 2 // 3, (128, 128, 0)),
])
run = True
while run:
clock.tick(60)
event_list = pygame.event.get()
for event in event_list:
if event.type == pygame.QUIT:
run = False
group.update(event_list)
window.fill(0)
group.draw(window)
pygame.display.flip()
pygame.quit()
exit()
Смотрите далее Создание нескольких спрайтов с разными функциями update() из одного и того же класса спрайтов в Pygame
Текущее положение мыши можно определить с помощью pygame.mouse.get_pos()
. Возвращаемое значение представляет собой кортеж, представляющий координаты x и y курсора мыши. pygame.mouse.get_pressed()
возвращает список логических значений, которые представляют состояние (True
или False
) всех кнопок мыши. Состояние кнопки - True
пока кнопка удерживается нажатой. При нажатии нескольких кнопок отображается несколько элементов в списке True
. 1-й, 2-й и 3-й элементы в списке представляют левую, среднюю и правую кнопки мыши.
Обнаруживать и оценивать состояния мыши в Update
методе pygame.sprite.Sprite
объекта:
class SpriteObject(pygame.sprite.Sprite):
# [...]
def update(self, event_list):
mouse_pos = pygame.mouse.get_pos()
mouse_buttons = pygame.mouse.get_pressed()
if self.rect.collidepoint(mouse_pos) and any(mouse_buttons):
# [...]
my_sprite = SpriteObject()
group = pygame.sprite.Group(my_sprite)
# [...]
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
group.update(event_list)
# [...]
Минимальный пример: repl.it/@Rabbid76/PyGame-MouseHover
import pygame
class SpriteObject(pygame.sprite.Sprite):
def __init__(self, x, y, color):
super().__init__()
self.original_image = pygame.Surface((50, 50), pygame.SRCALPHA)
pygame.draw.circle(self.original_image, color, (25, 25), 25)
self.hover_image = pygame.Surface((50, 50), pygame.SRCALPHA)
pygame.draw.circle(self.hover_image, color, (25, 25), 25)
pygame.draw.circle(self.hover_image, (255, 255, 255), (25, 25), 25, 4)
self.image = self.original_image
self.rect = self.image.get_rect(center = (x, y))
self.hover = False
def update(self):
mouse_pos = pygame.mouse.get_pos()
mouse_buttons = pygame.mouse.get_pressed()
#self.hover = self.rect.collidepoint(mouse_pos)
self.hover = self.rect.collidepoint(mouse_pos) and any(mouse_buttons)
self.image = self.hover_image if self.hover else self.original_image
pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
sprite_object = SpriteObject(*window.get_rect().center, (128, 128, 0))
group = pygame.sprite.Group([
SpriteObject(window.get_width() // 3, window.get_height() // 3, (128, 0, 0)),
SpriteObject(window.get_width() * 2 // 3, window.get_height() // 3, (0, 128, 0)),
SpriteObject(window.get_width() // 3, window.get_height() * 2 // 3, (0, 0, 128)),
SpriteObject(window.get_width() * 2// 3, window.get_height() * 2 // 3, (128, 128, 0)),
])
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
group.update()
window.fill(0)
group.draw(window)
pygame.display.flip()
pygame.quit()
exit()
Ответ 3
Документация pygame по событиям мыши находится здесь.
Вы можете использовать pygame.mouse.get_pressed
метод совместно с pygame.mouse.get_pos
(при необходимости).
Не забывайте использовать событие щелчка мыши через цикл основного события. Причина, по которой цикл событий лучше, заключается в "коротких щелчках". Вы можете не заметить этого на обычных компьютерах, но у компьютеров, использующих щелчки мышью на трекпадах, периоды щелчков слишком малы. Использование событий мыши предотвратит это.
РЕДАКТИРОВАТЬ: Для выполнения пиксельных столкновений используйте pygame.sprite.collide_rect()
найденные в их документах для спрайтов.
Ответ 4
Я искал такой же ответ на этот вопрос, и после долгих размышлений над этим ответом я пришел к:
# Python 3.4.3 with Pygame
from sys import exit
import pygame
pygame.init()
WIDTH = HEIGHT = 300
window = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Crash!')
# Draw Once
rectangle = pygame.draw.rect(window, (255, 0, 0), (100, 100, 100, 100))
pygame.display.update()
# Main Loop
while True:
# Mouse position and button clicking
pos = pygame.mouse.get_pos()
pressed1 = pygame.mouse.get_pressed()[0]
# Check if rectangle collided with pos and if the left mouse button was pressed
if rectangle.collidepoint(pos) and pressed1:
print("You have opened a chest!")
# Quit pygame
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()