Python Pygame如何检测图像列表中的点击

Python Pygame如何检测图像列表中的点击,python,pygame,Python,Pygame,对于我的级别屏幕,我使用每个级别按钮的图像,一页上有15个。我能够使用一些迭代和数学将它们以一种很好的布局快速地显示在屏幕上,我一直在试图找到一种方法来使用点击检测来实现这一点。但我不想一页输入15次“var=get_rect” 所有图像都在迭代列表中 self.levels_p1 = [self.l1, self.l2, self.l3, self.l4, self.l5, self.l6, self.l7, self.l8, self.l9, sel

对于我的级别屏幕,我使用每个级别按钮的图像,一页上有15个。我能够使用一些迭代和数学将它们以一种很好的布局快速地显示在屏幕上,我一直在试图找到一种方法来使用点击检测来实现这一点。但我不想一页输入15次“var=get_rect”

所有图像都在迭代列表中

self.levels_p1 = [self.l1, self.l2, self.l3, self.l4, self.l5,
                     self.l6, self.l7, self.l8, self.l9, self.l10,
                     self.l11, self.l12, self.l13, self.l14, self.l15,]
并以5 x 3的形式添加到屏幕上,如下所示

            for i, lvl in enumerate(self.levels_p1, start=1):
                x = ((WIDTH - 100) * (i % 5) // 6) + 17
                y = HEIGHT // 10 + ((i // 5) * 125)
                if i % 5 == 0:
                    x = ((WIDTH - 100) * 5 // 6) + 17
                    y = HEIGHT // 10 + (((i // 5) - 1) * 125)
                self.screen.blit(lvl, (x, y))
                if self.level_unlocked < i:
                    self.screen.blit(self.level_shade, (x, y))
            mousepos = pg.mouse.get_pos()

            for event in pg.event.get():
                if event.type == pg.QUIT:
                    pg.quit()
                if event.type == pg.MOUSEBUTTONDOWN:
                    #to menu
                    if self.back_rect.collidepoint(*mousepos):
                        on_levels = False
                        self.swipe.play()
                        self.start()
                    #to levels2 page
                    if self.arrow_rect.collidepoint(*mousepos):
                        on_levels = False
                        self.swipe.play()
                        self.levels_page2()
                    #to level 1
                    if self.l1_rect.collidepoint(*mousepos):
                        on_levels = False
                        self.swipe.play()
                        self.load_level(1)
但是,如果我手动为所有按钮定义一个rect,那么这只适用于所有级别,这正是我试图避免的

我想知道是否有一种很好的方法来检测这些按钮上的点击?类似于我在第二个代码位中显示它们的方式

非常感谢。

返回包含受影响像素区域的矩形:

self.rect=self.screen.blit(self.level_shade,(x,y))
或者,您也可以通过以下方式获得矩形的边界。此矩形的位置为(0,0)。因此,必须通过关键字参数设置位置:

self.rect=self.level\u shade.get\u rect(左上=(x,y))
我不知道你在上面写什么。如果你想检测点击,我认为你应该先得到鼠标的位置。我会这样做:

for event in pg.event.get():
            if event.type == pg.QUIT:
                pg.quit()
            if event.type == pg.MOUSEBUTTONDOWN:
                #to menu
                mousepos = pg.mouse.get_pos() #Here lies the magic and no need to unpack
                if self.back_rect.collidepoint(mousepos):
                    on_levels = False
                    self.swipe.play()
                    self.start()
                #to levels2 page
                if self.arrow_rect.collidepoint(mousepos):
                    on_levels = False
                    self.swipe.play()
                    self.levels_page2()
                #to level 1
                if self.l1_rect.collidepoint(mousepos):
                    on_levels = False
                    self.swipe.play()
                    self.load_level(1) 
如果这解决了你的问题,请让我知道,它仍然不让我知道

编辑:尝试使用if/elif块,而不是仅仅使用if。

mousepos=pg.mouse.get_pos()
        mousepos = pg.mouse.get_pos()
        lvls = []

        for i, lvl in enumerate(self.levels_p1):
            #x, y topleft for 5x3 grid with easement and centered
            x = ((WIDTH - 100) * (i % 5) // 5) + 110
            y = HEIGHT // 10 + ((i // 5) * 125)
            #add to screen
            temp = self.screen.blit(lvl, (x, y))
            #if not unlocked
            if self.level_unlocked < i:
                #darken
                self.screen.blit(self.level_shade, (x, y))
            #if unlocked
            else:
                #enlarged version if hovering over and unlocked
                if temp.collidepoint(*mousepos):
                    self.screen.blit(self.levels_1l[i], (x-6, y-6))
                #rect list for click detection
                lvls.append(temp)

        #back button interactive
        if self.back_rect.collidepoint(*mousepos):
            self.screen.blit(self.t_back2, self.back_rect2)  # bigger
        else:
            self.screen.blit(self.t_back, self.back_rect)  # normal
        #arrow button interactive
        if self.arrow_rect.collidepoint(*mousepos):
            self.screen.blit(self.arrowr2, self.arrow_rect2)  # bigger
        else:
            self.screen.blit(self.arrowr, self.arrow_rect)  # normal

        pg.display.flip()
        #all button presses
        for event in pg.event.get():
            if event.type == pg.QUIT:
                pg.quit()
            if event.type == pg.MOUSEBUTTONDOWN:
                #to menu
                if self.back_rect.collidepoint(*mousepos):
                    on_levels = False
                    self.swipe.play()
                    self.start()
                #to levels2 page
                if self.arrow_rect.collidepoint(*mousepos):
                    on_levels = False
                    self.swipe.play()
                    self.levels_page2()
                #to level
                for i, val in enumerate(lvls):
                    #if clicked pos = level pos
                    if lvls[i].collidepoint(*mousepos):
                        on_levels = False
                        self.swipe.play()
                        #level to load
                        self.load_level(i+1)
lvls=[] 对于i,枚举中的lvl(自身级别\u p1): #x、 y左上角为5x3网格,带有缓和和居中 x=((宽度-100)*(i%5)//5)+110 y=高度//10+((i//5)*125) #添加到屏幕 温度=自身屏幕亮度(左,(x,y)) #如果没有解锁 如果自锁水平_解锁
还有其他东西,我可以得到鼠标的位置,而且我在循环的早期就得到了。我试图检测一个点和一个不存在的矩形之间的碰撞。我使用数学和迭代提供了如何在列表的网格中显示15个级别的代码。点击检测也可以这样做,而不必一直往下看l1=get_rect l2=get_rect等等?我注意到复制会弄乱我提供的代码中的所有缩进,现在已经修复了。网格循环现在应该更容易理解了。我倾向于忽略简单的答案,这几乎就是解决方案。我在循环之前定义了一个空列表,并将所有级别按钮的rect添加到列表中,然后在测试点击时检查列表的索引。改进:
self.levels\u p1=[getattr(self,f“l{}”)for I in range(1,16)]
for I,val in enumerate(lvls):if lvls[I]。collidatepoint(*mousepos):on_levels=False self.swipe.play()self.load_level(i+1)
        mousepos = pg.mouse.get_pos()
        lvls = []

        for i, lvl in enumerate(self.levels_p1):
            #x, y topleft for 5x3 grid with easement and centered
            x = ((WIDTH - 100) * (i % 5) // 5) + 110
            y = HEIGHT // 10 + ((i // 5) * 125)
            #add to screen
            temp = self.screen.blit(lvl, (x, y))
            #if not unlocked
            if self.level_unlocked < i:
                #darken
                self.screen.blit(self.level_shade, (x, y))
            #if unlocked
            else:
                #enlarged version if hovering over and unlocked
                if temp.collidepoint(*mousepos):
                    self.screen.blit(self.levels_1l[i], (x-6, y-6))
                #rect list for click detection
                lvls.append(temp)

        #back button interactive
        if self.back_rect.collidepoint(*mousepos):
            self.screen.blit(self.t_back2, self.back_rect2)  # bigger
        else:
            self.screen.blit(self.t_back, self.back_rect)  # normal
        #arrow button interactive
        if self.arrow_rect.collidepoint(*mousepos):
            self.screen.blit(self.arrowr2, self.arrow_rect2)  # bigger
        else:
            self.screen.blit(self.arrowr, self.arrow_rect)  # normal

        pg.display.flip()
        #all button presses
        for event in pg.event.get():
            if event.type == pg.QUIT:
                pg.quit()
            if event.type == pg.MOUSEBUTTONDOWN:
                #to menu
                if self.back_rect.collidepoint(*mousepos):
                    on_levels = False
                    self.swipe.play()
                    self.start()
                #to levels2 page
                if self.arrow_rect.collidepoint(*mousepos):
                    on_levels = False
                    self.swipe.play()
                    self.levels_page2()
                #to level
                for i, val in enumerate(lvls):
                    #if clicked pos = level pos
                    if lvls[i].collidepoint(*mousepos):
                        on_levels = False
                        self.swipe.play()
                        #level to load
                        self.load_level(i+1)