2

So I'm programming this game with Python and Pygame and tried making a menu with clickable buttons. I've wrote this code:

while running:
    click = False
    for event in pygame.event.get():
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                click = True

    window.fill((0, 0, 0))

    button = pygame.Rect(30, 45, 280, 60)
    pygame.draw.rect(window, (52, 235, 177), button1, border_radius=20)
    window.blit(
        (font.render('Start Game', True, (255, 255, 255))), (50, 50))

    if click:
        if button1.collidepoint(pygame.mouse.get_pos()):
            main()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            running = False

    pygame.display.update()

But for some reason Pygame often doesn't register clicking. Sometimes it works on the first try, sometimes I have to click a button like 20 times to make it work. Does anybody have an Idea how to fix that?

manos
  • 87
  • 7

1 Answers1

4

The issue is caused, because you have multiple event loops. See pygame.event.get() get all the messages and remove them from the queue. See the documentation:

This will get all the messages and remove them from the queue. [...]

If pygame.event.get() is called in multiple event loops, only one loop receives the events, but never all loops receive all events. As a result, some events appear to be missed.

Get the events once per frame and use them in multiple loops (or pass the list of events to functions and methods where they are handled):

while running:
    click = False

    event_list = pygame.event.get()
    for event in event_list:
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                click = True

    window.fill((0, 0, 0))

    button = pygame.Rect(30, 45, 280, 60)
    pygame.draw.rect(window, (52, 235, 177), button1, border_radius=20)
    window.blit(
        (font.render('Start Game', True, (255, 255, 255))), (50, 50))

    if click:
        if button1.collidepoint(pygame.mouse.get_pos()):
            main()

    for event in event_list:
        if event.type == pygame.QUIT:
            pygame.quit()
            running = False

    pygame.display.update()

Or handle all the events in one loop:

while running:
    click = False

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            running = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                click = True

    window.fill((0, 0, 0))

    button = pygame.Rect(30, 45, 280, 60)
    pygame.draw.rect(window, (52, 235, 177), button1, border_radius=20)
    window.blit(
        (font.render('Start Game', True, (255, 255, 255))), (50, 50))

    if click:
        if button1.collidepoint(pygame.mouse.get_pos()):
            main()

    pygame.display.update()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174