Pygame 鼠标点击检测

2024-11-22 08:47:00
admin
原创
194
摘要:问题描述:我想知道如何编写代码来检测鼠标点击精灵。例如:if #Function that checks for mouse clicked on Sprite: print ("You have opened a chest!") 解决方案 1:我假设你的游戏有一个主循环,并且你...

问题描述:

我想知道如何编写代码来检测鼠标点击精灵。例如:

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

解决方案 1:

我假设你的游戏有一个主循环,并且你所有的精灵都在一个名为的列表中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...

因此,基本上,您必须在主循环的每次迭代中亲自检查精灵是否被点击。您需要使用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.Spritecollidepoint方法来查看Sprite是否被点击。将事件列表传递给update方法,以便您可以在Spritepygame.sprite.Group类中处理事件:

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)

    # [...]

最小示例:![IT科技](https://i.sstatic.net/5jD0C.png) repl.it/@Rabbid76/PyGame-MouseClick

IT科技

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()

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


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

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)

    # [...]

最小示例:![IT科技](https://i.sstatic.net/5jD0C.png) repl.it/@Rabbid76/PyGame-MouseHover

IT科技

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()
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3878  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2714  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   49  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   49  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   49  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用