Call function by button click in Pygame - python

I got a screen with buttons in Pygame here in the code below. Now I want to click the button, then a random() function starts and after 5 seconds it returns to the screen from the beginning with the buttons and let me the option to click again and call a random function again.
def loop():
clock = pygame.time.Clock()
number = 0
# The button is just a rect.
button = pygame.Rect(300,300,205,80)
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# This block is executed once for each MOUSEBUTTONDOWN event.
elif event.type == pygame.MOUSEBUTTONDOWN:
# 1 is the left mouse button, 2 is middle, 3 is right.
if event.button == 1:
# `event.pos` is the mouse position.
if button.collidepoint(event.pos):
# Incremt the number.
number += 1
random()
loop()
pygame.quit()

Add a state variable (runRandom), which indicates if the the function random has to be run:
runRandom = False
while not done:
# [...]
if runRandom:
random()
Add user defined pygame.event, which can be used for a timer:
runRandomEvent = pygame.USEREVENT + 1
for event in pygame.event.get():
# [...]
elif event.type == runRandomEvent:
# [...]
Allow the button to be pressed if random ins not running. If the button is pressed then state runRandom and start the timer (pygame.time.set_timer()) with the decided period of time (e.g. 5000 milliseconds = 5 seconds):
# [...]
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
if button.collidepoint(event.pos) and not runRandom:
# [...]
runRandom = True
pygame.time.set_timer(runRandomEvent, 5000)
When the time has elapse, the stop running random by runRandom = False and stop the timer:
# [...]
elif event.type == runRandomEvent:
runRandom = False
pygame.time.set_timer(runRandomEvent, 0)
Apply the suggestion to your code somehow like this:
# define user event for the timer
runRandomEvent = pygame.USEREVENT + 1
def loop():
clock = pygame.time.Clock()
number = 0
# The button is just a rect.
button = pygame.Rect(300,300,205,80)
done = False
runRandom = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# This block is executed once for each MOUSEBUTTONDOWN event.
elif event.type == pygame.MOUSEBUTTONDOWN:
# 1 is the left mouse button, 2 is middle, 3 is right.
if event.button == 1:
# `event.pos` is the mouse position and "random" is not running
if button.collidepoint(event.pos) and not runRandom:
# Incremt the number.
number += 1
# Start timer and enable running "random"
runRandom = True
pygame.time.set_timer(runRandomEvent, 5000) # 5000 milliseconds
elif event.type == runRandomEvent:
runRandom = False
pygame.time.set_timer(runRandomEvent, 0)
# [...]
# run "random"
if runRandom:
random()
# [...]

Related

How to restart my program with a button press 'r'?

Okay I've created Space Invaders in Python 3.7.4 and Pygame 1.9.6. I've got everything working no bugs or anything. I've even got the paused button to work great. It's just when the screen puts up 'GAME OVER' text to signify you lost. I would like to pop up a window to ask play again after the text goes away. But I just don't know where to begin at. I've looked at How do I restart a program based on user input? for help, but I couldn't understand where to implement it at or where to look at. This was my first real project/game I created in Pygame.
Code:
paused = False
running = True
while running:
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_p: # Pausing
paused = True
if event.key == pygame.K_u: # Unpausing
paused = False
if not paused:
'''The rest of the code, with the movement key presses, etc.'''
Since everything above the 'while running loop' is constantly being loaded or for data retrieval like the images the coordinates for where the images should be, the background music, etc. So I wanted it to be like the pausing/unpausing part of the code when I press down on say 'r'. I want to replay the program without exiting it. So I would be very grateful for help by people. Thank you all.
You have to create function or methods in object to reset data and use it before every game. You can use external while-loop for this.
# executed only once
pygame.init()
screen = ...
# .. load data ...
player = ...
enemy = ...
gameing = True
while gameing:
# reset data before every game
player.reset()
enemy.reset()
score = 0
paused = False
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT: # exit game
running = False
gameing = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_r: # restart game (but don't exit)
running = False
#gameing = True
if event.key == pygame.K_x: # exit game and program
running = False
gameing = False
if game_over: # restart game (but don't exit)
running = False
#gameing = True
You can also organize it as #Starbuck5 mentioned in commen - but then you should use running to exit program but not to exit game on game over
def reset():
global score, paused, running
player.reset()
enemy.reset()
score = 0
paused = False
running = True
# executed only once
pygame.init()
screen = ...
# .. load data ...
player = ...
enemy = ...
# (re)set data before first game
reset()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT: # exit game
running = False
gameing = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_r: # restart game (but don't exit)
#running = False # DON'T DO THIS
reset()
if event.key == pygame.K_x: # exit game and program
running = False
if game_over: # restart game (but don't exit)
#running = False # DON'T DO THIS
reset()
This need use global for every variable which you have to reset so it can be more useful when you have code in classes and you can use self. instead of global

My pause statement is not working for pygame loop

My collide_rect function is not working as I expect to be. The problem is when press the key 'r', it should be able to reset everything and continue the game. But when I actually press the key 'r', it does not change anything when I add in the pause statement. I want to have the game pause when two of the sprites I have(ball, obstacle) collide. After the user inputs the letter 'r', it should go back to running and reset position for both sprites. The error I am getting is when I press the key 'r', it does not change anything on the surface.
This is my while loop:
paused = False
def display_text(text):
font = pygame.freetype.Font('helvetica.ttc', 32)
text_attributed = font.render_to(gameDisplay, (300,300), text, black)
while not crashed:
time = pygame.time.get_ticks()
obstacle.change_x()
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
ball.jump_true()
if event.key == pygame.K_SPACE:
ball.jump_true()
if event.key == pygame.K_r:
paused = not paused
if ball.collide == True:
gameDisplay.fill(white)
display_text('You Lost! type "R" to restart')
paused = True
if paused == True:
ball.reset_position()
obstacle.reset_position()
pygame.display.flip()
clock.tick(20)
else:
ball.jump()
ball.test_collision(obstacle)
gameDisplay.fill(white)
ball.update()
obstacle.update()
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()
Don't overcomplicate things. You don't need multiple event loops. Use 1 main loop, 1 event loop and a state which indicates if the game is paused. e.g.:
paused = False
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_r
# Toggle pause
paused = not paused
if paused:
# "pause" mode
# [...]
else
# "run" mode
# [...]
# update display etc.
# [...]

Pause system in pygame [duplicate]

This question already has answers here:
Why is my pause system not working in Pygame?
(2 answers)
Closed 8 years ago.
hi there i've spent hours trying to make a toggle pause in pygame that you press space and it pauses then you press space again to un-pause and i'm having no luck would any one be able to help me please?
############### 2nd attempt #############
global timedelay
timedelay = pygame.time.wait (0)
pause = 0
if event.type == KEYUP:
if event.key == K_p and pause == 0:
timedelay = pygame.time.wait (9999)
pause = 1
if event.key == K_p and pause == 0:
timedelay = pygame.time.wait (0)
pause = 0
timedelay
############### 1st attempt #############
if event.type == KEYDOWN:
pause = 0
if event.key == K_p and pause == 0:
while 1:
pause = 0
event = pygame.event.wait()
pause = 1
if event.type == KEYDOWN:
if event.key == K_p and pause == 0:
print "woo!"
pause = 0
break
Don't block your whole main loop from running, just skip the state change part of the loop. You still need to be able to respond to events or your app is "unresponsive". You also want to keep drawing as windows can be moved around and cover your game and the screen still needs to refresh. So:
game_over = False
paused = False
while not game_over:
# handle events
for event in pygame.event.get():
if event.type == KEYDOWN:
paused = False
if event.key == K_p:
paused = True
...
if not paused:
# handle game state change
# handle screen drawing
pygame.display.flip()

pygame mouse button down not working

I am making this multiple choice program, but I need the mouse event to only work after enter is pressed.
Here is my code:
for event in pygame.event.get(): # If user did something
if event.type == pygame.QUIT: # If user clicked close
done = True
elif event.type == pygame.KEYDOWN: # If user pressed a key
if event.key == pygame.K_RETURN: # If user pressed enter
# Makes the start screen go away
enter_pressed = True
# Increments question_number
question_number += 1
# Where I Draw the question screen
Then down below I have this:
for event in pygame.event.get(): # If user did something
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
print("Derp")
Derp won't print when I press left mouse button.
However, when I have it indented like this:
for event in pygame.event.get(): # If user did something
if event.type == pygame.QUIT: # If user clicked close
done = True
elif event.type == pygame.KEYDOWN: # If user pressed a key
if event.key == pygame.K_RETURN: # If user pressed enter
# Makes the start screen go away
enter_pressed = True
# Increments question_number
question_number += 1
# Where I Draw the question screen
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
print("Derp")
Derp does print when I press left mouse button
You could use a boolean indicating wheter or not enter was pressed.
for event in pygame.event.get(): # If user did something
enter_pressed = False
if event.type == pygame.QUIT: # If user clicked close
done = True
elif event.type == pygame.KEYDOWN: # If user pressed a key
if event.key == pygame.K_RETURN: # If user pressed enter
# Makes the start screen go away
enter_pressed = True
# Increments question_number
question_number += 1
# Where I Draw the question screen
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1 and enter_pressed:
print("Derp")
I think that the problem is that you are iterating over all events, and inside that loop you are iterating over all events (again), and that causes some problems
It is hard to tell from what you said, but I have a couple of recommendations for you. First, make sure that the for loop with derp isn't in any if statements you don't want it to be in. Second, make sure you call pygame.event.get() once per game loop or the code will only give you events that happened between the two calls, which will not be all of them. If neither of these things work, try posting the whole code.

multiple clicks registering in pygame

I'm trying to make a board that changes color upon a left mouse click. But when I click it cycles through is_square_clicked() 3 times. That's a problem, I only want it to do it once. As you can probably guess this causes an issue for my program. So how do I limit it to 1 pass through per click? Thanks!
def is_square_clicked(mousepos):
x, y = mousepos
for i in xrange(ROWS):
for j in xrange(COLS):
for k in xrange(3):
if x >= grid[i][j][1] and x <= grid[i][j][1] + BLOCK:
if y >= grid[i][j][2] and y <= grid[i][j][2] + BLOCK:
if grid[i][j][0] == 0:
grid[i][j][0] = 1
elif grid[i][j][0] == 1:
grid[i][j][0] = 0
while __name__ == '__main__':
tickFPS = Clock.tick(fps)
pygame.display.set_caption("Press Esc to quit. FPS: %.2f" % (Clock.get_fps()))
draw_grid()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONUP and event.button == 1:
mousepos = pygame.mouse.get_pos()
is_square_clicked(mousepos)
pygame.display.update()
The reason that it cycles through is because you hold down the mouse long enough for it to check three times. I think if you have it wait between clicks, or you have it check not every time a cycle, it should be fixed.
im going to guess that since the game loops more than once each click it changes more then once
even though a click is very fast the loop is looping faster (depending on the FPS)
here is an example that will change the color of the screen on each click:
"""Very basic. Change the screen color with a mouse click."""
import os,sys #used for sys.exit and os.environ
import pygame #import the pygame module
from random import randint
class Control:
def __init__(self):
self.color = 0
def update(self,Surf):
self.event_loop() #Run the event loop every frame
Surf.fill(self.color) #Make updates to screen every frame
def event_loop(self):
for event in pygame.event.get(): #Check the events on the event queue
if event.type == pygame.MOUSEBUTTONDOWN:
#If the user clicks the screen, change the color.
self.color = [randint(0,255) for i in range(3)]
elif event.type == pygame.QUIT:
pygame.quit();sys.exit()
if __name__ == "__main__":
os.environ['SDL_VIDEO_CENTERED'] = '1' #Center the screen.
pygame.init() #Initialize Pygame
Screen = pygame.display.set_mode((500,500)) #Set the mode of the screen
MyClock = pygame.time.Clock() #Create a clock to restrict framerate
RunIt = Control()
while 1:
RunIt.update(Screen)
pygame.display.update() #Update the screen
MyClock.tick(60) #Restrict framerate
this code will blit a random color background each time you click so you can probably figure out the proper way to do it from the above code
Good Luck!

Categories