2

I'm writing a game in replit with pygame, and I want pygame to detect left and right clicks at the same time. I've looked at questions such as this and this, but they don't solve my problem. Using buttons = pygame.mouse.get_pressed(), I can only detect one click at a time. It functions properly when I left click or right click, but I cannot get both left and right click. If I hold left, I will have to double click right in order for it to detect it. I'd like it to be detected the first time.

Minimum Working Example:

import pygame, sys

screen = pygame.display.set_mode((320, 200))
left = False
right = False

while True:
  event = pygame.event.poll()
  buttons = pygame.mouse.get_pressed()
  if event.type == pygame.QUIT:
    pygame.quit()
    sys.exit()
  elif event.type == pygame.MOUSEBUTTONDOWN and buttons[0] and not left:
    print('left press')
    left = True
  elif event.type == pygame.MOUSEBUTTONUP and not buttons[0] and left:
    print('left release')
    left = False
  elif event.type == pygame.MOUSEBUTTONDOWN and buttons[2] and not right:
    print('right press')
    right = True
  elif event.type == pygame.MOUSEBUTTONUP and not buttons[2] and right:
    print('right release')
    right = False

  screen.fill((0, 0, 0))
  pygame.display.flip()

Typical Printed Output:

*left click and then release*
left press
left release

*right click and then release*
right press -- buttons = (True, False, False), left = False, right = False
right release -- buttons = (False, False, False), left = True, right = False

*left click, right click, release both*
left press -- buttons = (True, False, False), left = False, right = False
left release -- buttons = (False, False, False), left = True, right = False

*right click, left click, release both*
right press -- buttons = (False, False, True), left = False, right = False
right release -- buttons = (False, False, False), left = False, right = True

*left click, right double click, release right, release left*
left press -- buttons = (True, False, False), left = False, right = False
right press -- buttons = (True, False, True), left = True, right = False
right release -- buttons = (True, False, False), left = True, right = True
left release -- buttons = (False, False, False), left = True, right = False

*left click, right double click, release left, release right*
left press -- buttons = (True, False, False), left = False, right = False
right press -- buttons = (True, False, True), left = True, right = False
left release -- buttons = (False, False, True), left = True, right = True
right release -- buttons = (False, False, False), left = False, right = True

Same situation for the mirrored case of right click and left double click.
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Ziyan Fang
  • 21
  • 2
  • Can you show what a typical printed output looks like? Including what values `button`, `left` and `right` have at the time of each print? – Random Davis Dec 02 '21 at 23:51
  • @RandomDavis Included in the question. Is that what you want? – Ziyan Fang Dec 03 '21 at 00:26
  • it have to depends on system because on my Linux works `if buttons[0] and buttons[2]:` OR maybe it need first to get all event `for event in pygame.event.get()` and after loop check `mouse.get_pressed()` – furas Dec 03 '21 at 08:57
  • @furas I got it to work on my mac using IDLE as well. However, it is a collaborative project so I have to do it on [replit](https://replit.com). Is there any workarounds on that platform? Thanks. – Ziyan Fang Dec 06 '21 at 02:01

2 Answers2

2

You have to combine the pygame.mouse.get_pressed() and the MOUSEBUTTONDOWN event. The buttons are never clicked at the same moment. The events occur one at a time, but pygame.mouse.get_pressed() indicates when a key is held down. Detect when a button is clicked with MOUSEBUTTONDOWN and use pygame.mouse.get_pressed() to check if the other button is held:

run = True
while run:
      event = pygame.event.poll()
      buttons = pygame.mouse.get_pressed()
      if evet.type == pygame.QUIT:
          run = False 
      
      elif event.type == pygame.MOUSEBUTTONDOWN:
          
          # left clicked and right hold down
          if event.button == 1 and mouse_buttons[2]: 
          
              # [...]

          # right clicked and left hold down
          elif event.button == 3 and mouse_buttons[1]: 

              # [...]
      
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
1

I've re-factored your event handling:

import pygame, sys

screen = pygame.display.set_mode((320, 200))
left = False
right = False

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False 
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:  # LMB
                print('left press')
                left = True
            elif event.button == 3:  # RMB
                print('right press')
                right = True
        elif event.type == pygame.MOUSEBUTTONUP:
            if event.button == 1:
                print('left release')
                left = False
            elif event.button == 3:
                print('right release')
                right = False
                
    screen.fill((0, 0, 0))
    pygame.display.flip()
pygame.quit()
sys.exit()    

The test cases you've described work as expected, e.g. left-click, right-click, right-release, left-release displays:

left press
right press
right release
left release
import random
  • 3,054
  • 1
  • 17
  • 22
  • It still doesn't work for me. Can you try it on [replit](https://replit.com) because I'm working with a few other people so I can't use a local IDE. However, I did get it to work on my mac using IDLE, so is there any workarounds for replit? – Ziyan Fang Dec 06 '21 at 02:00