Image Closing when Moving Mouse - python

I'm trying to make a menu show up when you press a button. When you press the button, it appears. However, when I move my cursor, the menu disappears.
if event.type == pygame.MOUSEBUTTONUP:
if self.ui.menuUI.get_rect(topright = (1850, 0)).collidepoint(pygame.mouse.get_pos()):
self.ui.show_menu()
Here's the show_menu()
def show_menu(self):
self.display_surface.blit(self.menuUII,self.MenuUII_rect)
Thanks for helping!

You must draw the image in the application loop. Set a state when the button is clicked. And draw the image depending on the state:
Constructor:
self.show_ui = False
Event handling:
# event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONUP:
if self.ui.menuUI.get_rect(topright = (1850, 0)).collidepoint(pygame.mouse.get_pos()):
self.show_ui = True
when drawing the scene
if self.show_ui:
self.ui.show_menu()

Related

Pygame: How to display a new box when user clicks an area, and close the box when the user clicks again

I am new to python and pygame and I am developing a weather app as a project to learn both.
I want to display a new rectangle when a user is clicking an area (=button) of the screen. The new rectangle should be visible until the user clicks again, this time anywhere on the screen.
I have my main loop where the screen is drawn, and then checking for event MOUSEBUTTONUP and with collidepoint checking if the mouse was on the button and then updating variable newscreen to True
Then I have a new loop that should be running until the user is clicking again, anywhere on the screen.
The problem is that the new while loop is breaking as soon as the mouse is moved. It also looks like the first condition, checking if the user is clicking the button, is returning true in every iteration until the mouse is moved. Why is this not only returning true one time?
Can this be done without having a second while loop?
import pygame
import pygame.freetype
from pygame.locals import *
pygame.init()
SIZE = 500, 200
RED = (75, 0, 0)
NOTGREY = (75, 150, 150)
#set up the screen
screen = pygame.display.set_mode([800, 480])
# create rectangle
#Rect(position from left, position from top, width in pixels, height in pixels)
rect = Rect(50, 20, 200, 80)
rect2 = Rect(50,200, 200, 300)
running = True
newscreen = False
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
running = False
screen.fill(NOTGREY)
pygame.draw.rect(screen, RED, rect)
# If user is clicking (on release of click) on the rectangle area update newscreen to true
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1: # Left mouse button.
if rect.collidepoint(event.pos):
newscreen = True
print("Clicking area")
while newscreen == True:
pygame.draw.rect(screen, RED, rect2)
pygame.display.flip()
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1: # Left mouse button.
print("now you clicked again")
newscreen = False
pygame.display.flip()
You have to draw the rectangles depending on the state of newscreen:
if newscreen:
pygame.draw.rect(screen, RED, rect2)
else:
pygame.draw.rect(screen, RED, rect)
All the events need to be handled in one event loop. Toggle the state of newscreen when the button is clicked (newscreen = not newscreen):
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1: # Left mouse button.
if newscreen or rect.collidepoint(event.pos):
newscreen = not newscreen
Complete example:
import pygame
import pygame.freetype
from pygame.locals import *
pygame.init()
SIZE = 500, 200
RED = (75, 0, 0)
NOTGREY = (75, 150, 150)
#set up the screen
screen = pygame.display.set_mode([800, 480])
# create rectangle
#Rect(position from left, position from top, width in pixels, height in pixels)
rect = Rect(50, 20, 200, 80)
rect2 = Rect(50,200, 200, 300)
running = True
newscreen = False
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
running = False
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1: # Left mouse button.
if newscreen or rect.collidepoint(event.pos):
newscreen = not newscreen
screen.fill(NOTGREY)
if newscreen:
pygame.draw.rect(screen, RED, rect2)
else:
pygame.draw.rect(screen, RED, rect)
pygame.display.flip()
The typical PyGame application loop has to:
limit the frames per second to limit CPU usage with pygame.time.Clock.tick
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()
I might not use the second while loop:
while running:
# keep loop running at the right speed
clock.tick(30) // Frame per second
screen.fill(BLACK) // never forget this line of code, especially when you work with animation
pos = pygame.mouse.get_pos()
# Process input (events)
for event in pygame.event.get():
# check for closing window
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
click = True
if click:
show_new_screen()
click = False
Solved with adding all events into one event loop as mentioned above. I still wanted the second box to be closed when clicking anywher on the screen. Solved by adding another event check, for MOUSEBUTTONDOWN. It did not work to have another MOUSEBUTTONUP event.
running = True
newscreen = False
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
running = False
# If user is clicking (on release of click) on the rectangle area update newscreen to true
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1: # Left mouse button.
if rect.collidepoint(event.pos):
newscreen = True
print("Clicking area")
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # Left mouse button.
newscreen = False
print("now you clicked again")
screen.fill(NOTGREY)
pygame.draw.rect(screen, RED, rect)
if newscreen:
pygame.draw.rect(screen, RED, rect2)
pygame.display.flip()

Mouse click event pygame

If you hold the mouse button, it counts that you are still clicking. I want to fix it so that when you click once, it counts once.
import pygame, sys, time
from pygame.locals import *
pygame.init()
ev = pygame.event.get()
clock = pygame.time.Clock()
w = 800
h = 600
ScreenDisplay = pygame.display.set_mode((w,h))
pygame.display.set_caption('Tap Simulator')
while True: # main game loop
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
clock.tick(30)
handled = False
if pygame.mouse.get_pressed()[0] and not handled:
print("click!")
handled = pygame.mouse.get_pressed()[0]
pygame.display.flip()
You have to use the MOUSEBUTTONDOWN event instead of pygame.mouse.get_pressed():
run = True
while run: # main game loop
for event in pygame.event.get():
if event.type == QUIT:
run = False
if event.type == MOUSEBUTTONDOWN:
if event.button == 1: # 1 == left button
print("click!")
pygame.display.flip()
clock.tick(30)
pygame.quit()
sys.exit()
pygame.mouse.get_pressed() returns a list of Boolean values ​​that represent the state (True or False) of all mouse buttons. The state of a button is True as long as a button is held down.
The MOUSEBUTTONDOWN event occurs once when you click the mouse button and the MOUSEBUTTONUP event occurs once when the mouse button is released.
The pygame.event.Event() object has two attributes that provide information about the mouse event. pos is a tuple that stores the position that was clicked. button stores the button that was clicked. Each mouse button is associated a value. For instance the value of the attributes is 1, 2, 3, 4, 5 for the left mouse button, middle mouse button, right mouse button, mouse wheel up respectively mouse wheel down. When multiple keys are pressed, multiple mouse button events occur. Further explanations can be found in the documentation of the module pygame.event.
You can't check for a mouse click explicitly, but you can check for the mouse button being pressed down (event.type == pygame.MOUSEBUTTONDOWN) or released (event.type == pygame.MOUSEBUTTONUP).
click_count = 0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONUP:
click_count += 1
Since event.type == pygame.MOUSEBUTTONUP evaluates to True only when the mouse button is released, holding the mouse button down will not increment click_count.

Pygame start menu working, but not Pause menu

I'm trying to integrate a "pause" menu and "main" menu in pygame, along with a screen that will show during the game. My code first loads the intro, or main menu, which works fine, and then handles a button click to call the main game loop function. The problem arises when, within that loop, I try to call the function for the pause menu. I use the same loops to do this so I'm not sure why one works and the other doesn't. Below I've added code snippets for reference.
The main menu (which is called first in the program):
def intro_screen():
intro = True
while intro:
# Event listeners
for event in pygame.event.get():
main_window.fill(tan)
...
I also have other buttons etc. which are unimportant, but to get out of the intro, a mouse event sets intro to false and calls the function game_loop:
# Handle the click event
if click[0] == 1:
intro = False
game_loop()
The game_loop function has a similar while loop:
def game_loop():
playing = True
paused = False
while playing:
# This is the main loop
# Load in the play screens...
main_window.fill(white)
play_screen = PlayScreen(main_window)
And buttons etc...
But when I set playing to False and paused to True, which calls the pause_screen() function, it doesn't pull up any new screen. It just stays on the game menu as if no event was received.
for event in pygame.event.get():
if event.type == pygame.QUIT:
playing = False
# Listen for the escape key and bring up the pause menu
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
playing = False
paused = True
pygame.display.update()
while paused:
pause_menu()
For reference, these are all contained in functions. The last line of my code simply calls intro_screen(), which works fine.
I can provide the rest of the code if that would be helpful. The only thing I could think of is that the mouse event works and the keydown event doesn't, but my syntax looks to be correct from what I can tell.
Looks like your while loop for the pause menu is out of the game loop. Try this:
def game_loop():
playing = True
paused = False
while playing:
# This is the main loop
# Load in the play screens...
main_window.fill(white)
play_screen = PlayScreen(main_window)
for event in pygame.event.get():
if event.type == pygame.QUIT:
playing = False
# Listen for the escape key and bring up the pause menu
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
playing = False
paused = True
pygame.display.update()
while paused:
pause_menu()
Why don't you create a separate function for your pause menu? This will be easier as you can then call it properly.
For example:
pause = True
while pause:
# Event listeners
for event in pygame.event.get():
main_window.fill(tan)```

Stop multiple keyboard entries in Pygame

I have some python code that uses a pygame window to establish which key is being pressed. When a key is pressed, the code heads off and does things before coming back to see what the next key pressed might be.
The problem I have is that if the user presses a key repeatedly, even while the 'code heads off and does things', pygame seems to remember what has been pressed rather than waiting for the next keypress. What I want is for the code to ignore any keypresses while the 'go and do stuff' is done then once that's finished, get the next keypress. Hope this makes sense!
import pygame
import time
pygame.init()
screen = pygame.display.set_mode((450,282))
screen.fill((0,0,0))
pygame.display.flip()
clock = pygame.time.Clock()
done = False
def go_and_do_things():
print("doing things")
time.sleep(2)
print("things done")
# Loop as long as done == False
while not done:
for event in pygame.event.get(): # User did something
if event.type == pygame.KEYDOWN:
keypressedcode = event.key # This is the ASCII code
print("keypressedcode is " + str(keypressedcode))
go_and_do_things()
elif event.type == pygame.QUIT: # If user clicked close
done = True # Flag that we are done so we exit this loop
clock.tick(60)
time.sleep(4)
pygame.quit()
You could use pygame.event.clear. As written below, it will discard any keypresses during go_and_do_things().
while not done:
for event in pygame.event.get(): # User did something
# Any key down
if event.type == pygame.KEYDOWN:
keypressedcode = event.key # This is the ASCII code
print("keypressedcode is " + str(keypressedcode))
go_and_do_things()
pygame.event.clear(eventtype=[pygame.KEYDOWN,
pygame.KEYUP)
elif event.type == pygame.QUIT: # If user clicked close
done = True # Flag that we are done so we exit this loop
clock.tick(60)
This is a fairly simple problem, you just need to add another
event.type for keyup. You also need to add a variable to make it stop
running which I will label as stopV if event.type == pygame.KEYUP:
stopV = True This should let you instantly stop it when you want to. edit because I want to reword this:
Re-doing this to make it more clear.
import pygame
import time
pygame.init()
screen = pygame.display.set_mode((450,282))
screen.fill((0,0,0))
pygame.display.flip()
clock = pygame.time.Clock()
done = False
unClick = False
def go_and_do_things():
if unClick == False
print("hello")
# do anything you want in the function here
else
return
while not done:
for event in pygame.event.get(): # User did something
# Any key down
if event.type == pygame.KEYDOWN:
keypressedcode = event.key # This is the ASCII code
print("keypressedcode is " + str(keypressedcode))
go_and_do_things()
if event.type == pygame.KEYUP:
unClick == True
elif event.type == pygame.QUIT: # If user clicked close
done = True # Flag that we are done so we exit this loop
clock.tick(60)

Need help getting scroll up event

I'm creating a program in Python using Pygame and I can't find a working method to detect when I scroll up.
I'm trying to recreate a popular video called "Interstellar Mouse"
https://www.youtube.com/watch?v=aANF2OOVX40
I'm trying to get it to play the same music when you scroll (to do the same thing without having to edit it in).
I've been able to get this to work with keypresses by doing something like this:
keys = pygame.key.get_pressed()
if keys[pygame.K_KEYNAME]:
pygame.mixer.music.unpause()
Just using keys seems to work fine but I need to use the mouse wheel.
This is the main loop:
run = True
while run:
#quit game after pressing the close button
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
#exit game by pressing ESC
if keys[pygame.K_ESCAPE]:
run = False
#scroll to activate
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 4:
pygame.mixer.music.unpause()
else:
pygame.music.pause()
#update background
win.blit(bg, (width / 4, height / 4))
pygame.display.update()
pygame.quit()
The results are very inconsistent. Sometimes if I scroll really fast it will start playing after about a second but never stop. Sometimes it just doesn't play at all.
This part here:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 4:
pygame.mixer.music.unpause()
else:
pygame.music.pause()
Every time you have event.type == pygame.MOUSEBUTTONDOWN you are either pausing or unpausing the music. Mouse clicks and scroll downs will pause your music. I would change this to a specific pause option, say if event.button == 2 instead of your else for better control.

Categories

Resources