Pygame鼠标点击检测

18 python pygame mouseevent

我想知道如何编写能够检测鼠标点击精灵的代码.例如:

if #Function that checks for mouse clicked on Sprite:
    print ("You have opened a chest!")
Run Code Online (Sandbox Code Playgroud)

slo*_*oth 29

我假设你的游戏有一个主循环,你所有的精灵都在一个叫做的列表中sprites.

在主循环中,获取所有事件,并检查MOUSEBUTTONDOWNMOUSEBUTTONUP事件.

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...
Run Code Online (Sandbox Code Playgroud)

所以基本上你必须在主循环的每次迭代中检查精灵的点击.您将需要使用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!")
Run Code Online (Sandbox Code Playgroud)

如果你处理这种情况,你将不得不引入某种旗帜,否则这段代码将打印出"你已经打开了一个箱子!" 主循环的每次迭代.

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]
Run Code Online (Sandbox Code Playgroud)

当然你可以子类化Sprite并添加一个这样的方法is_clicked:

class MySprite(Sprite):
  ...

  def is_clicked(self):
    return pygame.mouse.get_pressed()[0] and self.rect.collidepoint(pygame.mouse.get_pos())
Run Code Online (Sandbox Code Playgroud)

所以,最好使用第一种方法恕我直言.

  • 另请注意,鼠标的位置也可以在`event.pos`下的事件中找到 (3认同)

Rab*_*d76 8

MOUSEBUTTONDOWN事件发生时,当你点击鼠标按钮一次,MOUSEBUTTONUP事件发生时,释放鼠标按键时一次。该pygame.event.Event()对象有两个属性,提供有关鼠标事件的信息。pos是一个存储被点击位置的元组。button存储被点击的按钮。每个鼠标按钮都关联一个值。例如,鼠标左键、鼠标中键、鼠标右键、鼠标滚轮向上和鼠标滚轮向下的属性值为1、2、3、4、5。当按下多个键时,会发生多个鼠标按钮事件。进一步的解释可以在模块的文档中找到pygame.event

使用对象的rect属性pygame.sprite.Spritecollidepoint方法查看Sprite是否被点击。将事件列表传递给 的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)

    # [...]
Run Code Online (Sandbox Code Playgroud)

最小的例子: 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()
Run Code Online (Sandbox Code Playgroud)

请参阅在 Pygame 中使用来自同一精灵类的不同 update() 创建多个精灵


鼠标的当前位置可以通过 确定pygame.mouse.get_pos()。返回值是一个元组,表示鼠标光标的 x 和 y 坐标。pygame.mouse.get_pressed()返回代表所有鼠标按钮状态(TrueFalse)的布尔值列表。一个按钮的状态是True只要一个按钮被按住。当按下多个按钮时,列表中的多个项目是True。列表中的第一个、第二个和第三个元素代表鼠标左键、中键和右键。

DetectUpdatepygame.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)

    # [...]
Run Code Online (Sandbox Code Playgroud)

最小的例子: 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()
Run Code Online (Sandbox Code Playgroud)


jak*_*451 6

鼠标事件的pygame文档就在这里.您可以pygame.mouse.get_pressedpygame.mouse.get_pos(如果需要)合作使用该方法.但请通过主事件循环使用鼠标单击事件.事件循环更好的原因是"短暂点击".您可能在普通计算机上没有注意到这些,但在触控板上使用点击次数的计算机的点击周期过短.使用鼠标事件将阻止这种情况.

编辑: 要执行像素完美碰撞的使用pygame.sprite.collide_rect()上找到自己的文档的精灵.


小智 5

我一直在寻找这个问题的相同答案,经过反复思考,这是我想出的答案:

#Python 3.4.3 with Pygame
import pygame

pygame.init()
pygame.display.set_caption('Crash!')
window = pygame.display.set_mode((300, 300))


# Draw Once
Rectplace = 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, pressed2, pressed3 = pygame.mouse.get_pressed()
    # Check if the rect collided with the mouse pos
    # and if the left mouse button was pressed.
    if Rectplace.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()
            quit(1)
Run Code Online (Sandbox Code Playgroud)