You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pygame中批量检测关卡按钮图片的点击事件?

问题:Pygame中批量实现关卡按钮的点击检测

我在Pygame的关卡界面里用图片作为关卡按钮,每页15个,已经通过迭代和计算用5×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))

其中self.levels_p1是包含15张关卡图片的列表。

目前我是手动定义每个按钮的rect来检测点击,但不想重复15次var = get_rect操作。现有的点击检测代码片段如下:

mousepos = pg.mouse.get_pos()
for event in pg.event.get():
    if event.type == pg.QUIT:
        pg.quit()
    if event.type == pg.MOUSEBUTTONDOWN:
        # 返回菜单
        if self.back_rect.collidepoint(*mousepos):
            on_levels = False
            self.swipe.play()
            self.start()
        # 跳转到第二页关卡
        if self.arrow_rect.collidepoint(*mousepos):
            on_levels = False
            self.swipe.play()
            self.levels_page2()
        # 进入关卡1
        if self.l1_rect.collidepoint(*mousepos):
            on_levels = False
            self.swipe.play()
            self.load_level(1)

我希望能像批量绘制按钮那样,实现批量的点击检测,请问有什么合适的方法?


解决方案:批量管理关卡按钮的Rect与点击逻辑

这个问题很好解决,核心思路就是把每个关卡的位置信息(Rect)和对应的关卡编号绑定起来,统一存储和遍历,就能实现和绘制逻辑同步的批量检测了,具体步骤如下:

1. 同步存储关卡的Rect与编号

在绘制关卡按钮的循环里,顺便计算每个按钮的rect,并把rect和对应的关卡编号一起存入一个列表。这样就不用手动一个个定义l1_rect、l2_rect这类变量了:

# 先初始化一个空列表,用来存储每个关卡的(rect, 关卡编号)
self.level_rects = []

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)
    # 计算当前关卡图片的rect,用topleft定位更准确
    lvl_rect = lvl.get_rect(topleft=(x, y))
    # 将rect和关卡编号存入列表
    self.level_rects.append( (lvl_rect, i) )
    # 绘制关卡按钮
    self.screen.blit(lvl, lvl_rect)
    # 绘制锁层遮罩(直接用lvl_rect,不用再传x,y)
    if self.level_unlocked < i:
        self.screen.blit(self.level_shade, lvl_rect)

2. 批量检测关卡点击事件

在点击检测的逻辑里,遍历刚才存储的level_rects列表,就能批量判断点击是否命中某个关卡按钮了,还能顺便判断关卡是否解锁:

mousepos = pg.mouse.get_pos()
for event in pg.event.get():
    if event.type == pg.QUIT:
        pg.quit()
    if event.type == pg.MOUSEBUTTONDOWN:
        # 保留原有返回菜单、翻页的逻辑
        if self.back_rect.collidepoint(*mousepos):
            on_levels = False
            self.swipe.play()
            self.start()
        if self.arrow_rect.collidepoint(*mousepos):
            on_levels = False
            self.swipe.play()
            self.levels_page2()
        
        # 批量检测关卡按钮点击
        for lvl_rect, level_num in self.level_rects:
            # 先判断关卡是否解锁,再判断是否点击命中
            if self.level_unlocked >= level_num and lvl_rect.collidepoint(*mousepos):
                on_levels = False
                self.swipe.play()
                self.load_level(level_num)
                break  # 一次点击只触发一个关卡,找到后就退出循环,避免重复触发

额外小优化

  • 绘制遮罩时直接用lvl_rect代替(x,y),代码更简洁,也避免坐标不一致的问题;
  • 遍历检测时加上break,因为点击位置只会命中一个按钮,找到后就停止遍历,提升一点效率。

内容的提问来源于stack exchange,提问作者Grave

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 00:17:53