2

I'm trying to make tic tac toe with pygame. If you click in any one of the squares, an x will be displayed. The problem is that it takes a lot of clicks to display the x. here's the code:

while True:
    for event in pygame.event.get():
        if event == pygame.QUIT:
            pygame.quit()
            sys.exit()
        mouse_pos = pygame.mouse.get_pos()
        event = pygame.event.wait()
        screen.fill(bg_color)
        if event.type == pygame.MOUSEBUTTONDOWN and 250 < mouse_pos[0] < 300 and 250 > mouse_pos[1] > 199:
            mouse_clicked1 = True
        if event.type == pygame.MOUSEBUTTONDOWN and 301 < mouse_pos[0] < 351 and 249 > mouse_pos[1] > 201:
            mouse_clicked2 = True
    if mouse_clicked1:
        screen.blit(x, object_top_left)
    if mouse_clicked2:
        screen.blit(x, object_top)
  • Are you perhaps starving the event handler of resources by running in a tight loop? – gspr Sep 14 '20 at 11:42
  • I didn't understand what you said – sneaky dude Sep 14 '20 at 11:46
  • 1
    Your code is running in a tight loop. It is possible that that means that the Python runtime and/or the Pygame code that is responsible for collecting mouse clicks from the operating system often have no time to run. You can confirm or rule out this theory by adding a delay to the end of your `while True` loop. [Here's an example](https://stackoverflow.com/questions/377454/how-do-i-get-my-python-program-to-sleep-for-50-milliseconds). If that causes the behavior you describe to go away, then resource starvation of the event handler was indeed the culprit. – gspr Sep 14 '20 at 11:49
  • How much of a delay should I give – sneaky dude Sep 14 '20 at 11:52
  • It's not important for the sake of the experiment. 10 ms, 100 ms, whatever. – gspr Sep 14 '20 at 11:52
  • It's better than before, but it still takes a few clicks. How can I fix that? – sneaky dude Sep 14 '20 at 12:00
  • And you're sure that it not just the case now that you click and then have to wait for the delay you added to pass? If that's not it, I can't help you any further. – gspr Sep 14 '20 at 12:04
  • Please post your full (runnable) game code. I don't think the code above is the root of the problem. – Mike67 Sep 14 '20 at 16:37

1 Answers1

1

pygame.event.wait() waits for a single event from the queue. Remove the function a use the events which you get from pygame.event.get().
If the event type is MOUSEBUTTONDOWN (or MOUSEBUTTONUP), then the mouse position is stored in the pos attribute of the pygame.event.Event() object:

while True:
    for event in pygame.event.get():
        if event == pygame.QUIT:
            pygame.quit()
            sys.exit()
        
        if event.type == pygame.MOUSEBUTTONDOWN and 250 < event.pos[0] < 300 and 250 > event.pos[1] > 199:
            mouse_clicked1 = True
        if event.type == pygame.MOUSEBUTTONDOWN and 301 < event.pos[0] < 351 and 249 > event.pos[1] > 201:
            mouse_clicked2 = True
    
    screen.fill(bg_color)
    if mouse_clicked1:
        screen.blit(x, object_top_left)
    if mouse_clicked2:
        screen.blit(x, object_top)

Note, pygame.event.get() get and removes all the events from the queue. Hence the call to pygame.event.wait() in the loop, will rarely return any event.


Furthermore, I recommend to use pygame.Rect objects and collidepoint():

while True:
    for event in pygame.event.get():
        if event == pygame.QUIT:
            pygame.quit()
            sys.exit()
        
        if event.type == pygame.MOUSEBUTTONDOWN:
            rect1 = pygameRect(250, 200, 50, 50)
            if rect1.collidepoint(event.pos):
                mouse_clicked1 = True
            rect2 = pygameRect(300, 200, 50, 50)
            if rect2.collidepoint(event.pos):
                mouse_clicked2 = True
    
    screen.fill(bg_color)
    if mouse_clicked1:
        screen.blit(x, object_top_left)
    if mouse_clicked2:
        screen.blit(x, object_top)
Rabbid76
  • 202,892
  • 27
  • 131
  • 174