Reputation: 152
I use python-2.7 and pygame to build a minesweeper. It's almost done, only one important function left to implement. When both left and right mouse buttons are pressed, it'll scan the blocks around and do something. But I couldn't figure out how to detect both clicks at the same time. On pygame's website, there is
Note, that on X11 some XServers use middle button emulation. When you click both buttons 1 and 3 at the same time a 2 button event can be emitted.
But it doesn't work out for me.
Upvotes: 2
Views: 3624
Reputation: 3899
you can code for the scenario that is outlined in the docs (a button 2 middle mouse gets triggered on button 1 and 3 press).
mouse_pressed = pygame.mouse.get_pressed()
if (mouse_pressed[0] and mouse_pressed[2]) or mouse_pressed[1]:
print("left and right clicked")
keep in mind, using pygame.mouse.get_pressed() will often trigger very fast, meaning any code that you have in the if statement will happen a few times before you can release the mouse key. This is because get_pressed() returns the state of all mouse buttons at all times. This method is good if you want to track buttons that are being held down.
I would code the solution into pygame.event.get(). This will only trigger when an event happens, and therefore only once:
left_mouse_down = False
right_mouse_down = False
while True:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
left_mouse_down = True
if right_mouse_down:
print("perform action")
else:
print("action for single left click")
if event.button == 3:
right_mouse_down = True
if left_mouse_down:
print("perform action")
else:
print("action for single right click")
elif event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
left_mouse_down = False
if event.button == 3:
right_mouse_down = False
UPDATE - Simulate a third mouse click on a two button mouse
the above code works but only if you accept the fact that the single right or left action will trigger as well, but before the combo(left/right) action. If this works for your game design, have at it. If this is not acceptable, then the following will work (although a little more in depth):
left_mouse_down = False
right_mouse_down = False
left_click_frame = 0 # keeps track of how long the left button has been down
right_click_frame = 0 # keeps track of how long the right button has been down
left_right_action_once = True # perform the combo action only once
left_action_once = True # perform the left action only once
right_action_once = True # perform the right action only once
max_frame = 2 # The frames to wait to see if the other mouse button is pressed (can be tinkered with)
performing_left_right_action = False # prevents the off chance one of the single button actions running on top of the combo action
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
mouse_pressed = pygame.mouse.get_pressed()
if mouse_pressed[0]: # left click
left_click_frame += 1
left_mouse_down = True
else:
left_action_once = True
left_mouse_down = False
left_click_frame = 0
if mouse_pressed[2]: # right click
right_click_frame += 1
right_mouse_down = True
else:
right_action_once = True
right_mouse_down = False
right_click_frame = 0
if not mouse_pressed[0] and not mouse_pressed[2]:
left_right_action_once = True
performing_left_right_action = False
if left_mouse_down and right_mouse_down and abs(left_click_frame - right_click_frame) <= max_frame:
if left_right_action_once:
print("performing right/left action")
left_right_action_once = False
performing_left_right_action = True
elif left_mouse_down and left_click_frame > max_frame and not performing_left_right_action and not right_mouse_down:
if left_action_once:
print("perform single left click action")
left_action_once = False
elif right_mouse_down and right_click_frame > max_frame and not performing_left_right_action and not left_mouse_down:
if right_action_once:
print("perform single right click action")
right_action_once = False
The hard part about this problem is only one event can happen at a time so you have to have a way of knowing the left click was pressed, not evaluate it until you are sure right click will also not be pressed. You can accomplish this by keeping track of the frames and if the left and right happen within a certain number of frames (max_frames), then you have a right/left click. Otherwise you have either a left or right.
the action_once variables are important because since pygame.mouse.get_pressed() checks the state of each mouse button every time through the game loop, you need a flag to prevent your actions from running more than once while the button is held down (even during the short duration of a click). The game loop is faster than a mouse click.
So all three scenarios are covered: left single, right single, left right combo. In other words it simulates a "third" mouse click on a two button mouse....Although the solution is rather clunky
Upvotes: 4
Reputation: 327
You should test values of pygame.mouse.get_pressed()[0]
(left mouse button) and pygame.mouse.get_pressed()[2]
(rigth mouse button) at the same time.
http://www.pygame.org/docs/ref/mouse.html#pygame.mouse.get_pressed
This test should be at the same level of the pygame.event.get()
for loop and not included in this loop. You can test this script to see what I mean:
import pygame
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((800, 500), RESIZABLE)
running = True
while(running):
mousebuttons = pygame.mouse.get_pressed()
if mousebuttons[0] == 1 and mousebuttons[2] == 1:
print("Both left and rigth mouse buttons are pressed.")
for event in pygame.event.get():
if event.type == QUIT:
running = False
Upvotes: 0
Reputation: 131
If you only want your code to execute once after pressing both buttons just set right_mouse_down
and left_mouse_down
to False
after you run your code.
left_mouse_down = False
right_mouse_down = False
while True:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
left_mouse_down = True
if right_mouse_down:
print("perform action")
right_mouse_down = False
left_mouse_down = True
if event.button == 3:
right_mouse_down = False
if left_mouse_down:
print("perform action")
right_mouse_down = False
left_mouse_down = False
elif event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
left_mouse_down = False
if event.button == 3:
right_mouse_down = False
Now this code will never run again until you remove and reclick both mouse buttons. I would recommend using pygame.mouse.get_pressed()
to check the state of the buttons at any point, so that if you only want the code to happen the first time you can set a flag.
done_the_thing = False
while not done: # Main game loop
buttons = pygame.mouse.get_pressed()
if buttons[0] and buttons[2] and not done_the_thing:
do_the_thing() # This is just your function
done_the_thing = True
if not buttons[0] and not buttons[2]:
done_the_thing = False
This will allow more flexibility so if you want to add in more mouse events that do occur every frame or change what you are currently doing, you can keep all of them together and clean.
Upvotes: 0