Pygame: getting a loop to run after mouse click - python

I want to get a certain loop to run after the mouse has previously been clicked.
I initiated a variable called mouse_clicked to false, and then change it to True after the mouse has been clicked. However, this doesn't seem to get things going afterwards.
Here's my code:
import sys, pygame
size = width, height = 320, 240
screen = pygame.display.set_mode(size)
running = True
mouse_pressed = False
while running:
while mouse_pressed:
rect = pygame.Rect(10, 20, 30, 30)
pygame.draw.rect(screen, (255,0,0), rect)
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pressed = True
if event.type == pygame.QUIT:
running = False
sys.exit(0)
Thanks!
omer

EDITED after answering too quickly
move your loop around:
while running:
rect = pygame.Rect(10, 20, 30, 30)
pygame.draw.rect(screen, (255,0,0), rect)
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pressed = True
if event.type == pygame.QUIT:
running = False
while mouse_pressed:
# do your stuff
mouse_pressed = False
In your version, the whole loop never starts, since mouse_pressed is initialized to False.

It looks like your second loop is not even starting: you are initiating mouse_pressed as False. Therefore,
while mouse_pressed
will necessarily stop the loop before it ever began.
Hope this helps!

Related

Is there a way to close the pygame window with a MOUSEBUTTONDOWN event?

I am trying to make a clickable image that exits pygame, but im not sure how to make it close. I have tried using the pygame.quit() and sys.exit() but that loads for a second but doesn't do anyhting. I will show the code I have here(the only relevant code is the x and y variables nad the exit button down the bottom):
import pygame, sys
clock = pygame.time.Clock()
from pygame.locals import *
pygame.init() # inititates Pygame
pygame.display.set_caption('Lightmind')
screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN) # initiates the window
logo = pygame.image.load("GameLogo.png").convert()
logo = pygame.transform.scale(logo, (256, 256))
start_button = pygame.image.load("StartButton.png").convert()
start_button = pygame.transform.scale(start_button, (256, 256))
exit_button = pygame.image.load("ExitButton.png").convert()
exit_button = pygame.transform.scale(exit_button, (256, 100))
x_2 = 560
y_2 = 400
fade_in = True
fade_out = True
fade_in_ball = True
fade_in_start = True
fade_in_exit = True
running = True
while running: # game loop
for event in pygame.event.get():
if event.type == QUIT:
running = False
pygame.quit()
sys.exit()
# fade in the logo
if fade_in == True:
for i in range(255):
screen.fill((0,0,0))
logo.set_alpha(i)
screen.blit(logo, (560,260))
pygame.display.flip()
clock.tick(60)
fade_in = False
# fade out the logo
if fade_out == True:
for i in range(255):
screen.fill((0,0,0))
logo.set_alpha(255-i)
screen.blit(logo, (560,260))
pygame.display.flip()
clock.tick(60)
fade_out = False
# fade in the start button
if fade_in_start == True:
for i in range(255):
start_button.set_alpha(i)
screen.blit(start_button, (560, 240))
pygame.display.flip()
clock.tick(60)
fade_in_start = False
# fade in the exit button
if fade_in_exit == True:
for i in range(255):
exit_button.set_alpha(i)
screen.blit(exit_button, (x_2, y_2))
pygame.display.flip()
clock.tick(60)
fade_in_exit = False
# make exit button exit game
if event.type == pygame.MOUSEBUTTONDOWN:
x_2, y_2 = event.pos
if exit_button.get_rect().collidepoint(x_2, y_2):
pygame.quit()
sys.exit()
pygame.display.update()
Any help is appreciated!
You're checking the event outside of your event loop. Move it up instead:
for event in pygame.event.get():
if event.type == QUIT:
running = False
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
x_2, y_2 = event.pos
if exit_button.get_rect().collidepoint(x_2, y_2):
pygame.quit()
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.
You must handle the click detection in the event loop.
pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, but it returns a rectangle that always starts at (0, 0) since a Surface object has no position.
The Surface is placed at a position on the display with the blit function.
You've to set the location of the rectangle, either by a keyword argument, e.g:
running = True
while running: # game loop
for event in pygame.event.get():
if event.type == QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
extit_button_rect = exit_button.get_rect(topleft = (x_2, y_2))
if extit_button_rect.collidepoint(event.pos):
running = False
# [...]
pygame.quit()
sys.exit()

Pygame - How to Fill an object gradually from bottom to top?

I'm currently working on a game based around working a restaurant, and one of the aspects im working on is filling a cup up with water, i'm choosing not to do water simulations as i'm no expert ahah but my idea of filling a cup up using rectangles one a top another when the mouse button is held is not working. Here's the section of code im trying to fix, any and all feedback is appreciated : ).
while True:
e = pygame.event.wait()
if e.type == pygame.MOUSEBUTTONDOWN:
DrawWater = True
if e.type == pygame.MOUSEBUTTONUP:
print("Lol")
WaterLine = False
if DrawWater:
pygame.draw.rect(screen, [0, 0, 255], [300, WaterLine, 400, 1])
WaterLine -= 1
pygame.display.flip()
pygame.event.wait() wait for a single event from the queue and halts the application loop. Implement an event loop and use pygame.event.get:
Use pygame.time.Clock to control the frames per second and thus the game speed.
The method tick() of a pygame.time.Clock object, delays the game in that way, that every iteration of the loop consumes the same period of time. See pygame.time.Clock.tick().
This method should be called once per frame.
That means that the loop:
clock = pygame.time.Clock()
run = True
while run:
clock.tick(60)
runs 60 times per second.
clock = pygame.time.Clock()
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
DrawWater = True
if event.type == pygame.MOUSEBUTTONUP:
print("Lol")
WaterLine = False
if DrawWater:
pygame.draw.rect(screen, [0, 0, 255], [300, WaterLine, 400, 1])
WaterLine -= 1
pygame.display.flip()
Alternatively you can use pygame.mouse.get_pressed():
import pygame
pygame.init()
screen = pygame.display.set_mode((300, 400))
WaterLine = 300
clock = pygame.time.Clock()
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if any(pygame.mouse.get_pressed()):
pygame.draw.rect(screen, [0, 0, 255], [100, WaterLine, 100, 1])
WaterLine -= 1
pygame.display.flip()
The MOUSEBUTTONDOWN event occurs once when you click the mouse button and the MOUSEBUTTONUP event occurs once when the mouse button is released.
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.

pyagame.error: Video not intiialized. Code Posted

Ask for any more information if needed!
I am using vscode's ide and python 3. When I run script.py the display will pop-up, but a half of a second later the display will disappear and will give this error pyagame.error: Video not intiialized.
import pygame
pygame.init()
run = True
while run:
screen = pygame.display.set_mode([500, 500])
pygame.display.set_caption("TicTac")
pygame.quit()
x = 250
y = 250
width = 40
height = 60
vol = 5
run = True
while run:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT():
run = False
run = False
pygame.QUIT()
You do pygame.quit() immediately after pygame.display.set_mode(). pygame.quit() terminates all pygame modules. Remove it:
screen = pygame.display.set_mode([500, 500])
pygame.display.set_caption("TicTac")
# pygame.quit() <--- DELETE
pygame.QUIT is not a function, it is an enumerator constant. You can't invoke pygame.QUIT:
if event.type == pygame.QUIT():
if event.type == pygame.QUIT:
You need just one application loop, not 2 of them. Furthermore you have to update the window by either pygame.display.flip() or pygame.display.update()
import pygame
pygame.init()
screen = pygame.display.set_mode([500, 500])
pygame.display.set_caption("TicTac")
x, y = 250, 250
width, height = 40, 60
vol = 5
run = True
while run:
pygame.time.delay(100)
# handle events
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# clear dispaly
screen.fill((0, 0, 0))
# draw the scene
pygame.draw.rect(screen, (255, 0, 0), (x, y, width, height))
# update display
pygame.display.flip()
pygame.quit()

Pygame Text Blit and time.sleep not working

I'm having a hard time with pygame blitting text onto the screen. Right now before quitting I just want to have a message show up for 2 seconds, then have the game quit. To do this I use time.sleep(2). However, and I believe most other people don't have this issue from questions I've looked up on Stackoverflow, the text just doesn't show up until what seems to be the last moment before the window closes. Rather, the screen remains white after pressing the close button. My code is below. Please note that this is not a duplicate of this question.
import pygame
import time
pygame.init()
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((display_width,display_height))
clock = pygame.time.Clock()
FPS = 30
font = pygame.font.SysFont(None, 25)
x = False
while not x:
for event in pygame.event.get():
if event.type == pygame.QUIT:
x = True
gameDisplay.fill(white)
pygame.display.update()
clock.tick(FPS)
screen_text = font.render('Test', True, red)
gameDisplay.blit(screen_text, (0, 0))
pygame.display.update()
time.sleep(2)
pygame.quit()
I ended up using the pygame.time.set_timer workaround #CodeSurgeon mentioned.
This worked for me - replacing time.sleep(2), with:
pygame.time.set_timer(pygame.USEREVENT, 2000)
should_quit = False
while not should_quit:
for event in pygame.event.get():
if event.type == pygame.USEREVENT:
should_quit = True
I actually have the exact same problem and found that if I moved time.sleep(2) directly after pygame.quit() it worked as intended. I'm new to pygame and not sure why this works
screen_text = font.render('Test', True, red)
gameDisplay.blit(screen_text, (0, 0))
pygame.display.update()
pygame.quit()
time.sleep(2)
You could try replacing time.sleep(2) with
for i in range(0, 200, 1):
time.sleep(0.01)
This can be useful in other situations with long sleeps if you want to be able to use CTRL-C to stop the program. It also might be more convenient to use a function:
def MySleep(duration, resolution=10):
"""Sleep, without freezing the program. All values in ms"""
for i in range(0, int(duration), int(resolution)):
time.sleep(resolution / 1000)
for some reason, stdlib time.sleep() does not work in pygame.
However, pygame does have its own time function.
Here is the code I wrote to print out a message, character by character.
message = ""
font = pygame.font.Font("freesansbold.ttf", 32)
message_text_x = 0
message_text_y = 550
message_text_speed = 35
inF = open("chapter_1.txt")
lines = inF.readlines()
def write_message(char, x, y):
# first render the value as text so it can be drawn on the screen using screen.blit
message_text = font.render(char, True, (0, 0, 0))
screen.blit(message_text, (x, y))
running = True
while running:
for line in lines:
for char in line:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
running = False
if event.key == pygame.K_SPACE:
message_text_speed = 10
message += char
write_message(message, message_text_x, message_text_y)
pygame.event.pump()
pygame.time.delay(message_text_speed)
pygame.display.update()
clock.tick(60)
When spacebar is clicked the speed of the text becomes faster

pygame screen failing to display

I have the following code in Python 3 (and pygame), but the white surface fails to display and I don't understand why. Has it got something to do with where it has been placed? I tried de-indenting, but that didn't work either? The code is as below:
import pygame
from pygame.locals import*
pygame.init()
screen=pygame.display.set_mode((800,600))
# Variable to keep our main loop running
running = True
# Our main loop!
while running:
# for loop through the event queue
for event in pygame.event.get():
# Check for KEYDOWN event; KEYDOWN is a constant defined in pygame.locals, which we imported earlier
if event.type == KEYDOWN:
# If the Esc key has been pressed set running to false to exit the main loop
if event.key == K_ESCAPE:
running = False
# Check for QUIT event; if QUIT, set running to false
elif event.type == QUIT:
running = False
# Create the surface and pass in a tuple with its length and width
surf = pygame.Surface((50, 50))
# Give the surface a color to differentiate it from the background
surf.fill((255, 255, 255))
rect = surf.get_rect()
screen.blit(surf, (400, 300))
pygame.display.flip()
So it does appear that your indentation is wrong.
You need to define the surface and update the screen etc. outside of the event loop.
At the very least you must move the screen.blit(surf, (400, 300)) and pygame.display.flip() outside of the event loop.
This is it fixed:
# Our main loop!
while running:
# for loop through the event queue
for event in pygame.event.get():
# Check for KEYDOWN event; KEYDOWN is a constant defined in pygame.locals, which we imported earlier
if event.type == KEYDOWN:
# If the Esc key has been pressed set running to false to exit the main loop
if event.key == K_ESCAPE:
running = False
# Check for QUIT event; if QUIT, set running to false
elif event.type == QUIT:
running = False
# Create the surface and pass in a tuple with its length and width
surf = pygame.Surface((50, 50))
# Give the surface a color to differentiate it from the background
surf.fill((255, 255, 255))
rect = surf.get_rect()
screen.blit(surf, (400, 300))
pygame.display.flip()

Categories