【问题标题】:Can't get Mouse down event on a color to trigger无法在颜色上触发鼠标按下事件
【发布时间】:2020-03-26 11:08:46
【问题描述】:

我正在为一个学校项目创建一个避免游戏,我遇到了一个奇怪的错误,即当光标单击绿色时 MOUSEBUTTONDOWN 事件不会触发(“获胜颜色”),即使版本几乎相同相同的代码确实工作,但颜色不同。

我当前的颜色事件代码是:

        pos = pygame.mouse.get_pos()
    color_at_cursor = screen.get_at(pos)

    if event.type == pygame.MOUSEBUTTONDOWN and color_at_cursor == (0, 0, 255, 255):
        print("Game Start")
        start_clicked = True
    if start_clicked and color_at_cursor == (0, 228, 255, 255):
        died = True
    if died:
        screen.blit(ded, ded_rect)
        if event.type == pygame.MOUSEBUTTONDOWN:
            is_alive = False

  if start_clicked and event.type == pygame.MOUSEBUTTONDOWN and color_at_cursor == (0, 255, 0, 255):
      screen.blit(win_screen, win_rect)
      if event.type == pygame.MOUSEBUTTONDOWN:
          is_alive = False

其中前 3 个 if 语句检查是否单击了蓝色开始按钮,以及光标是否触及青色/浅蓝色死亡颜色。这些语句按预期工作,但使用几乎完全相同概念的最终语句不起作用。单击绿色时,没有任何反应。我得出的结论是它不起作用的原因是因为有问题的绿色位于与背景不同的对象上。但这仍然很奇怪,因为当光标悬停在平台上时,上面的第二个 IF 语句并没有导致立即死亡,(其颜色与背景的青色死亡颜色不同)

无论如何,我尝试编写代码来检测对象顶部的某种颜色的鼠标单击事件。如下图:

if event.type == pygame.MOUSEBUTTONDOWN and start_clicked:
    x, y = event.pos
    if platform1.get_rect().collidepoint(x,y) and platform1.get_at((x, y)) == (0, 255, 0, 255):
        print("win button clicked")
        screen.blit(win_screen, win_rect)
        if event.type == pygame.MOUSEBUTTONDOWN:
            is_alive = False

这仍然没有导致任何事情发生。有谁知道我为什么会遇到这个问题,以及如何解决它?

【问题讨论】:

  • 每一步都能打印出光标处的颜色吗? print(platform1.get_at((x, y))) 是否匹配所需的颜色?
  • 您还可以将颜色存储在全局常量中,如 WIN_COLOR、WALL_COLOR 等,这样您只需在一处更改。
  • 你能检查一下你的缩进吗?第一个 sn-p 中的最后一个 if 缩进较少。你的代码中也是这样吗?如果是这样,第一个块从哪里开始?
  • 在你的第二次 sn-p...platform1win_screenwin_rect 是什么?
  • @Valentino 实际代码中的缩进很好,粘贴到网站可能看起来很奇怪。 platform1 是用户应该将鼠标保持在顶部的部分,基本上它是位于背景顶部的图像(因为我有平台在游戏本身中旋转)。 win_screen 是当点击绿色时应该显示的 .png 文件,win_rect 是那个 .png 文件,但它是一个矩形,以便它可以正确显示。

标签: python colors pygame mouseevent


【解决方案1】:

在您的第二次 sn-p 中,我不能 100% 确定 platform1 是什么,但我猜它是一个充满绿色的 Surface。

如果是这种情况,错误很可能是坐标的偏移量。让我用下面的MCVE 来说明这一点,这是你的第二个 sn-p 的简化版本:

pygame.init()
screen = pygame.display.set_mode((800, 800))

platform1 = pygame.Surface((200, 200))
platform1.fill((0, 255, 0))
screen.blit(platform1, (300, 300))
pygame.display.update()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            x, y = event.pos
            if platform1.get_rect().collidepoint(x,y) and platform1.get_at((x, y)) == (0, 255, 0):
                print("win button clicked")

现在这会在屏幕中间创建一个绿色方块,但是当您单击它时,不会打印"win button clicked"(重现您描述的错误)。

原因是event.pos返回了鼠标在屏幕坐标系中的坐标:即(0, 0)的位置是屏幕窗口的左上角。
但是,您从platform1.get_rect() 获得的矩形不知道矩形的实际绘制位置,因此它的原点被假定为(0, 0) 而不是它的原点(在这种情况下为(300, 300))。所以在检测点碰撞时会出错。

如果您将最后一个 if 块替换为:

    if event.type == pygame.MOUSEBUTTONDOWN:
        x, y = event.pos
        x -= 300
        y -= 300
        if platform1.get_rect().collidepoint(x,y) and platform1.get_at((x, y)) == (0, 255, 0):
            print("win button clicked")

它按预期工作,因为我们考虑了(300, 300) 的偏移量。

这说明了问题,但当然不是解决问题的好方法,因为偏移量是硬编码的,并且不会对所有对象都相同。面对这种情况的最好方法是使用Sprite 而不仅仅是Surfaces,它可以用于以一致的方式跟踪对象在屏幕中的位置。

【讨论】:

  • 我添加了一个在单击绿色时设置为 true 的变量,以及一个单独的 if 语句,当该变量为 true 时显示 win 屏幕,它终于起作用了。我也像你说的那样把胜利圈做成了一个精灵,我不知道这是否真的影响了结果,但至少现在可以了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-23
  • 2011-08-22
  • 1970-01-01
  • 1970-01-01
  • 2013-04-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多