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

Pygame地图点击重复触发问题求助:clicked变量失效

Grid Wars INDEV点击事件重复触发问题修复

问题根源

  • 主循环每帧调用isClicked(),而pygame.mouse.get_pressed()在鼠标按住时会持续返回True,导致每帧都触发点击逻辑,出现重复注册。
  • isClicked()遍历所有tile时,每个碰撞的tile都会修改self.clicked和self.action,逻辑混乱;且最后返回的tile[2]是遍历的最后一个tile类型,并非实际点击的tile。
  • 没有利用Pygame的事件系统处理单次点击,而是用状态轮询,这是重复触发的核心原因。

修复方案

1. 修改主代码,用事件系统处理点击

把点击检测移到事件循环里,利用MOUSEBUTTONDOWN事件确保每次点击只触发一次:

import pygame
from world import World

pygame.init()

screen_width = 1500
screen_height = 650

screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Grid Wars INDEV')

world = World(screen)
tile_size = 50
lineAmount = 1300/50

def draw_grid():
    for line in range(1,25):
        pygame.draw.line(screen, (218,165,32), (200, line * tile_size), (1350, line * tile_size), 2)
        keyline = line + 3
        pygame.draw.line(screen, (218,165,32), (keyline * tile_size, 0), (keyline * tile_size, 650), 2)

run = True
while run:
    screen.fill("red")
    world.draw()
    draw_grid()
    pygame.draw.line(screen, (218,165,32), (200,5), (1350,5), 10)
    pygame.draw.line(screen, (218,165,32), (200,645), (1350, 645), 10)
    pygame.draw.line(screen, (218,165,32), (200,0), (200, 650), 10)
    pygame.draw.line(screen, (218,165,32), (1350,0), (1350, 650), 10)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        # 处理鼠标左键点击事件
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            tile_type = world.check_clicked_tile(event.pos)
            if tile_type:
                print('Hello World')
                print(tile_type)

    pygame.display.update()

pygame.quit()

2. 修改World类,添加单次点击检测方法

移除原来的isClicked(),替换为check_clicked_tile(),仅在点击事件触发时调用,返回被点击的tile类型:

import pygame
from button import Button

class World:
    def __init__(self, screen) -> None:
        self.name_list = []
        self.screen = screen
        map_data = [
       [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
       [1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1],
       [1,0,0,0,0,1,0,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,1],
       [1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1],
       [1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
       [1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
       [1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
       [1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
       [1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
       [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
       [1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
       [0,1,1,1,1,1,0,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,1],
       [1,1,1,1,1,1,1,0,1,1,1,0,0,1,1,1,1,1,1,1,0,1,1]
        ]
        ocean_img = pygame.image.load('ocean.png')
        grass_img = pygame.image.load('grass.png')
        row_count = 0
        for row in map_data:
            column_count = 0
            for tile in row:
                if tile == 1:
                    img = pygame.transform.scale(ocean_img, (50,50))
                    img_rect = img.get_rect()
                    img_rect.x = column_count * 50 + 200
                    img_rect.y = row_count * 50 
                    tile_data = (img, img_rect,'ocean')
                    self.name_list.append(tile_data)
                    
                if tile == 0:
                    img = pygame.transform.scale(grass_img, (50,50))
                    img_rect = img.get_rect()
                    img_rect.x = column_count * 50 + 200
                    img_rect.y = row_count * 50 
                    tile_data = (img, img_rect,'grass')
                    self.name_list.append(tile_data)
                
                column_count += 1
            row_count += 1

    def draw(self):
        for tile in self.name_list:
            self.screen.blit(tile[0], tile[1])

    def check_clicked_tile(self, pos):
        # 遍历所有tile,检测点击位置是否碰撞
        for tile in self.name_list:
            if tile[1].collidepoint(pos):
                return tile[2]
        # 没点击到任何tile返回None
        return None

关键修改说明

  • 改用MOUSEBUTTONDOWN事件:该事件仅在鼠标按键按下的瞬间触发一次,彻底解决重复注册问题。
  • 移除冗余状态变量:不再需要维护clicked和action,事件驱动逻辑更可靠。
  • 修复tile类型返回错误:现在返回的是实际被点击的tile类型,而非遍历的最后一个。
  • 分离点击检测逻辑:将点击检测放在事件处理流程中,避免每帧轮询导致的重复触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 14:50:37