如何限制Pygame点击器游戏中按钮的长按重复触发?
Hey there! The problem you're running into is that your current code checks every frame if the mouse is held down over the button. Since pygame.mouse.get_pressed() returns True for every frame the button is held, your money variable increments nonstop during a long press. Let's fix this with two straightforward solutions:
Solution 1: Use Pygame's MOUSEBUTTONDOWN Event (Recommended)
This is the cleanest approach because Pygame's event system is designed for one-time user interactions like a single click. Instead of checking the mouse state every frame, we'll listen for the exact moment the left mouse button is pressed.
Here's the revised code with this approach:
import pygame, sys from pygame.locals import * pygame.init() light_gray=(211,211,211) black=(0,0,0) white=(255,255,255) def terminate(): pygame.quit() sys.exit() def drawText(text, font, screen, x, y, color): textobj = font.render(text, True, color) textrect = textobj.get_rect(center=(x,y)) screen.blit(textobj, textrect) class Button(object): def __init__(self, x, y, width, height, color): self.rect = pygame.Rect(x, y, width, height) # Using pygame.Rect makes collision checks easier self.color = color def is_clicked(self, mouse_pos): # Check if the mouse position is inside the button's rectangle return self.rect.collidepoint(mouse_pos) clock = pygame.time.Clock() font = pygame.font.SysFont(None, 50) screen_width = 1300 screen_height = 700 screen = pygame.display.set_mode([screen_width, screen_height]) pygame.display.set_caption('Clicker') done = False money = 0 button = Button(25, screen_height-125, 500, 100, light_gray) while not done: for event in pygame.event.get(): if event.type == QUIT: terminate() # Listen for left mouse button press events if event.type == MOUSEBUTTONDOWN and event.button == 1: if button.is_clicked(event.pos): money += 1 screen.fill(light_gray) pygame.draw.rect(screen, button.color, button.rect) pygame.draw.rect(screen, black, button.rect, 3) drawText('Click!', font, screen, button.rect.centerx, button.rect.centery, black) drawText(f'${money}', font, screen, screen_width/2, 25, black) pygame.display.flip() clock.tick(15) pygame.quit()
Solution 2: Add a Press State Flag (Minimal Changes)
If you want to keep most of your original code structure, you can add a flag to track whether the button was already pressed in the last frame. This way, we only count the first frame of the press, not every frame during a long hold.
Modified Button class:
class Button(object): def __init__(self, x, y, width, height, color): self.rect=(x,y,width,height) self.image=pygame.draw.rect(screen, color,(self.rect),) self.x=x self.y=y self.width=width self.height=height self.was_pressed = False # Tracks if the button was held last frame def check(self): mouse = pygame.mouse.get_pos() current_pressed = pygame.mouse.get_pressed()[0] in_bounds = self.x + self.width > mouse[0] > self.x and self.y + self.height > mouse[1] > self.y # Only return True if we just pressed the button (not holding it) if in_bounds and current_pressed and not self.was_pressed: self.was_pressed = True return True # Reset the flag when the mouse is released if not current_pressed: self.was_pressed = False return False
Keep your main loop the same—this change will make each click only increment money once, even if you hold the mouse down.
Why These Work:
- Solution 1 uses Pygame's built-in event system, which fires exactly once when the mouse is clicked, so we don't have to worry about repeated counts.
- Solution 2 tracks the transition from "not pressed" to "pressed", ensuring we only count the initial click, not the entire hold duration.
内容的提问来源于stack exchange,提问作者gnaw




