How to show text in pygame after button click - python

I have a button created with pygame. Now i want to show some text on screen once the button is pressed. But i want to give it a varibale instead of string. How do i do that ? I tried adding the screen.blit(txtSmjerKretanja, (150,150)) to if gumbLijevo.collidepoint(mouse_pos) and if gumbDesno.collidepoint(mouse_pos): but it doesn't work.
EDIT:
I looked at the suggested topics from other users, but it doesn't really solve my problem. Problem is that my program doesn't show text as soon as i use some varibale (in this case smjerKretanja) instead of usual string like ('some string..').
import pygame
import sys
def main():
pygame.init()
myfont = pygame.font.SysFont('Arial', 20)
clock = pygame.time.Clock()
fps = 60
size = [500, 500]
bg = [255, 255, 255]
smjerKretanja = 0
screen = pygame.display.set_mode(size)
gumbLijevo = pygame.Rect(20, 20, 100, 30)
gumbDesno = pygame.Rect(150, 20, 100, 30)
txtLijevo = myfont.render('Lijevo', False, (0,0,0))
txtDesno = myfont.render('Desno', False, (0,0,0))
txtSmjerKretanja = myfont.render(str(smjerKretanja), False, (0,0,0))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = event.pos # gets mouse position
# checks if mouse position is over the button
if gumbLijevo.collidepoint(mouse_pos):
# prints current location of mouse
# print('button was pressed at {0}'.format(mouse_pos))
smjerKretanja = smjerKretanja - 10
if smjerKretanja < 0:
smjerKretanja = 350
print smjerKretanja
screen.blit(txtSmjerKretanja, (150,150))
if gumbDesno.collidepoint(mouse_pos):
# prints current location of mouse
# print('button was pressed at {0}'.format(mouse_pos))
smjerKretanja = smjerKretanja + 10
if smjerKretanja > 360:
smjerKretanja = 10
print smjerKretanja
screen.blit(txtSmjerKretanja, (150,150))
screen.fill(bg)
pygame.draw.rect(screen, [255, 0, 0], gumbLijevo)
pygame.draw.rect(screen, [255, 0, 0], gumbDesno)
screen.blit(txtLijevo,(30,20))
screen.blit(txtDesno,(160,20))
pygame.display.update()
clock.tick(fps)
pygame.quit()
sys.exit
if __name__ == '__main__':
main()

You only update txtSmjerKretanja at the start of the code, in order to update it constantly you need to add
txtSmjerKretanja = myfont.render(str(smjerKretanja), False, (0,0,0))
the while loop

Related

Adding a particle effect to my clicker game

I'm currently making a Python clicking game using Pygame. Right now, there is a coin in the center of the screen that you can click. What I want to add now, it a little green "+$10" icon that appears somewhere next to the coin whenever someone clicks it. This is what I want the game to look like whenever someone clicks the coin:
Here is the code of my coin functions:
def button_collide_mouse(element_x, element_y, x_to_remove, y_to_remove):
mouse_x, mouse_y = pygame.mouse.get_pos()
if mouse_x > element_x > mouse_x - x_to_remove and \
mouse_y > element_y > mouse_y - y_to_remove:
return True
def check_events(coin, settings):
for event in pygame.event.get():
# Change button color if mouse is touching it
if button_collide_mouse(coin.image_x, coin.image_y, 125, 125):
coin.image = pygame.image.load('pyfiles/images/click_button.png')
if event.type == pygame.MOUSEBUTTONUP:
settings.money += settings.income
else:
coin.image = pygame.image.load('pyfiles/images/click_button_grey.png')
Using my current code, how can I add that kind of effect?
See How to make image stay on screen in pygame?.
Use pygame.time.get_ticks() to return the number of milliseconds since pygame.init() was called. When the coin is clicked, calculate the point in time after that the text image has to be removed. Add random coordinates and the time to the head of a list:
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
# [...]
if event.type == pygame.MOUSEBUTTONDOWN:
if coin_rect.collidepoint(event.pos):
pos = ... # random position
end_time = current_time + 1000 # 1000 milliseconds == 1 scond
text_pos_and_time.insert(0, (pos, end_time))
Draw the text(s) in the main application loop. Remove the text when the time has expired from the tail of the list:
for i in range(len(text_pos_and_time)):
pos, text_end_time = text_pos_and_time[i]
if text_end_time > current_time:
window.blit(text, text.get_rect(center = pos))
else:
del text_pos_and_time[i:]
break
Minimal example:
import pygame
import random
pygame.init()
window = pygame.display.set_mode((400, 400))
font = pygame.font.SysFont(None, 40)
clock = pygame.time.Clock()
coin = pygame.Surface((160, 160), pygame.SRCALPHA)
pygame.draw.circle(coin, (255, 255, 0), (80, 80), 80, 10)
pygame.draw.circle(coin, (128, 128, 0), (80, 80), 75)
cointext = pygame.font.SysFont(None, 80).render("10", True, (255, 255, 0))
coin.blit(cointext, cointext.get_rect(center = coin.get_rect().center))
coin_rect = coin.get_rect(center = window.get_rect().center)
text = font.render("+10", True, (0, 255, 0))
text_pos_and_time = []
run = True
while run:
clock.tick(60)
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
if coin_rect.collidepoint(event.pos):
pos = pygame.math.Vector2(coin_rect.center) + pygame.math.Vector2(105, 0).rotate(random.randrange(360))
text_pos_and_time.insert(0, ((round(pos.x), round(pos.y)), current_time + 1000))
window.fill(0)
window.blit(coin, coin_rect)
for i in range(len(text_pos_and_time)):
pos, text_end_time = text_pos_and_time[i]
if text_end_time > current_time:
window.blit(text, text.get_rect(center = pos))
else:
del text_pos_and_time[i:]
break
pygame.display.flip()
pygame.quit()
exit()

Using a variable instead of the actual value causes a bug

I was messing around trying to figure out how to centre text in a button. This is the code.
import pygame
pygame.init()
win = pygame.display
d = win.set_mode((500, 500))
text = "A Button"
size = 50
size = [3*size, 1*size]
rectx = size[0]
recty = size[1]+ 5
textsizey = recty
t = len(text) * 5
textsize = int(textsizey/ t)
if textsize >= recty:
textsize = recty
testrect = pygame.Surface((rectx, recty))
testrect.fill((255, 255, 255))
def write(screen, text, color, position, size):
font = pygame.font.Font(pygame.font.get_default_font(), size)# Defining a font with font and size
text_surface = font.render(text, True, color)# Defining the text color which will be rendered
screen.blit(text_surface, (position[0], position[1])) # Rendering the font
while True:
pygame.event.get()
d.fill((0, 0, 0))
d.blit(testrect, (10, 10))
write(d, text, (0, 255, 0), [10, 10+(0.5*recty)-(0.5*textsize)], textsize)
win.flip()
On line 11, the variable t = len(text) * 5 is used in the next line textsize = int(textsizey/ t). When i do this the text size diminishes, which is not supposed to happen. But, if i use the value of t and replace the line with textsize = int(textsizey/ len(text) * 5), it works just fine. Printing the value of the variable and the actual value just before using it gives the same result. I am not using the variable t elsewhere in the program either. Why could this be happening?
To center text on button you need pygame.Rect() and its .center
button_rect = testrect.get_rect()
and then
text_rect = text_surface.get_rect()
text_rect.center = button_rect.center
or in one line
text_rect = text_surface.get_rect(center = button_rect.center)
and then you draw
text_rect.x = position[0]
text_rect.y = position[1]
blit(text_surface, text_rect)
BTW: If you don't change text then you could define Font, text_surface and text_rect only once. And later only change .x .y or .center
BTW: pygame.Rect() has other useful values - .centerx, .centery, .widht, .height, .x, .y, .left (the same as .x), .right (x + width), .top(the same as.y), .bottom (y+height), .size`,
Minimal working code with other changes.
It moves button randomly and it uses .center to center text on button.
import pygame
import random
pygame.init()
win = pygame.display.set_mode((500, 500))
size = 50
# --- button's rectange ---
button_image = pygame.Surface((3*size, 1*size))
button_rect = button_image.get_rect(x=10, y=10)
button_image.fill((255, 255, 255))
# --- button's text ---
text = "A Button"
font = pygame.font.Font(pygame.font.get_default_font(), size//2)
text_image = font.render(text, True, (255, 0, 0))
text_rect = text_image.get_rect(center=button_rect.center)
# --- main loop ---
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
exit()
# clear buffer
win.fill((0, 0, 0))
# draw button in buffer
win.blit(button_image, button_rect)
win.blit(text_image, text_rect)
# send buffer on screen
pygame.display.flip()
# slow down to 2 FPS (2 frames per second)
clock.tick(2)
# move button to new place
button_rect.x = random.randint(0, 500-button_rect.width)
button_rect.y = random.randint(0, 500-button_rect.height)
# center text on button
text_rect.center = button_rect.center
BTW: I use smaller text - size//2 but if you want to fit button to text size then you can do
button_rect.width = text_rect.width + margins
button_rect.height = text_rect.height + margins
and recreate image/surface
button_image = pygame.Surface(button_rect.size)
button_image.fill((255, 255, 255))
text_rect.center = button_rect.center
Minimal working code
import pygame
import random
pygame.init()
win = pygame.display.set_mode((500, 500))
size = 50
margins = 10
# --- button's rectange ---
button_image = pygame.Surface((3*size, 1*size))
#button_rect = pygame.Rect((10, 10, 3*size, 1*size))
button_rect = button_image.get_rect(x=100, y=100)
button_image.fill((255, 255, 255))
# --- button's text ---
text = "A Button"
font = pygame.font.Font(pygame.font.get_default_font(), size)
text_image = font.render(text, True, (255, 0, 0))
text_rect = text_image.get_rect(center=button_rect.center)
# --- resize button to text ---
button_rect.width = text_rect.width + margins
button_rect.height = text_rect.height + margins
button_image = pygame.Surface(button_rect.size)
button_image.fill((255, 255, 255))
text_rect.center = button_rect.center
# --- main loop ---
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
exit()
# clear buffer
win.fill((0, 0, 0))
# draw button in buffer
win.blit(button_image, button_rect)
win.blit(text_image, text_rect)
# send buffer on screen
pygame.display.flip()
# slow down to 2 FPS (2 frames per second)
clock.tick(2)
# move button to new place
button_rect.x = random.randint(0, 500-button_rect.width)
button_rect.y = random.randint(0, 500-button_rect.height)
# center text on button
text_rect.center = button_rect.center

Fixing an error where the code goes unresponsive after one cycle

I'm trying to have the for loop run 5 iterations of the code below it but once it runs once and i try to click the rectangle the code goes unresponsive.
I can't see why this is happening so i'm looking for some help.
def Reaction_game():
intro = True
while intro == True:
for event in pygame.event.get():
#Stops game when close is selected
if event.type == pygame.QUIT:
file=open('currentuser.txt', 'w')
file.close()
pygame.quit()
quit()
Reaction_times=[]
for x in range (5):
clicked = False
BackGround = Background("background1.png",[0,0])
screen.fill(white)
screen.blit(BackGround.image, BackGround.rect)
pygame.draw.rect(screen, black,(0,0,1000,55))
Font = pygame.font.SysFont('TitilliumWeb.ttf',72)
Label = Font.render("Get Ready:", 1, white)
screen.blit(Label, (380,0,325,75))
pygame.display.update()
time.sleep(2)
screen.blit(BackGround.image, BackGround.rect)
pygame.draw.rect(screen, black,(0,0,1000,55))
Font = pygame.font.SysFont('TitilliumWeb.ttf',72)
Label = Font.render("Go:", 1, white)
screen.blit(Label, (450,0,325,75))
pygame.display.update()
RectX = randrange(50,950)
RectY = randrange(60,513)
round_rect(screen,(RectX,RectY,75,40),(black),10,5,(white))
pygame.display.update()
TimeStart = time.time()
while clicked !=True:
mouse = pygame.mouse.get_pos()
if RectX+75 > mouse[0] > RectX and RectY+40 > mouse[1] > RectY:
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
TimeEnd = time.time()
ReactionTime = TimeEnd - TimeStart
Reaction_times.append(ReactionTime)
clicked = True
else:
pass
Reaction_game()
I expect the code to run 5 iterations of this little reaction time game but it doesn't even get past the first loop before going unresponsive.
You have to use for event in pygame.event.get(): inside while clicked to get new events from system. Without this you have the same values in event.type and even.button.
Even pygame.mouse.get_pos() can't work correclty because it uses data created by pygame.event.get() (or similar)
If you have event MOUSEBUTTONDOWN, MOUSEBUTTONUP then you have mouse position in event.pos and you don't need pygame.mouse.get_pos()
while not clicked:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
if RectX+75 > event.pos[0] > RectX and RectY+40 > event.pos[1] > RectY:
TimeEnd = time.time()
ReactionTime = TimeEnd - TimeStart
Reaction_times.append(ReactionTime)
clicked = True
EDIT:
You can keep Rectangle position and size in pygame.Rect()
RectX = randrange(50,950)
RectY = randrange(60,513)
rect = pygame.Rect(RectX, RectY, 75, 40)
and then you can use rect instead of (RectX,RectY,75,40)
round_rect(screen, rect, black , 10, 5, white)
and you can use rect to check if you clicked in rectangle rect.collidepoint(event.pos)
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
if rect.collidepoint(event.pos):
TimeEnd = time.time()
ReactionTime = TimeEnd - TimeStart
Reaction_times.append(ReactionTime)
clicked = True
EDIT: working example with other changes - ie. I use pygame.time.wait() instead of time.sleep() and pygame.time.get_ticks() instead of time.time(). Both use miliseconds instead of seconds.
import pygame
import random
# --- constants ---
WHITE = (255, 255, 255)
BLACK = ( 0, 0, 0)
# --- main ---
pygame.init()
screen = pygame.display.set_mode((1000, 600))
reaction_times= []
for x in range(5):
clicked = False
screen.fill(WHITE)
pygame.draw.rect(screen, BLACK, (0, 0, 1000, 55))
font = pygame.font.SysFont(None, 72)
label = font.render("Get Ready:", 1, WHITE)
screen.blit(label, (380, 0, 325, 75))
pygame.display.update()
pygame.time.wait(2000) # 2000ms = 2s
pygame.draw.rect(screen, BLACK, (0, 0, 1000, 55))
font = pygame.font.SysFont(None, 72)
label = font.render("Go:", 1, WHITE)
screen.blit(label, (450, 0, 325, 75))
pygame.display.update()
x = random.randrange(50, 950)
y = random.randrange(60, 513)
rect = pygame.Rect(x, y, 75, 40)
pygame.draw.rect(screen, BLACK, rect)
pygame.display.update()
time_start = pygame.time.get_ticks()
while not clicked:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
if rect.collidepoint(event.pos):
print('clicked')
time_end = pygame.time.get_ticks()
reaction_time = (time_end - time_start)/1000 # convert to seconds
reaction_times.append(reaction_time)
clicked = True
print(reaction_times)
pygame.quit()

How to single click and turn to another page in Pygame?

So I'm writing this code for a school assignment, which I'm supposed to use pygame and display some text. I put those text in different pages, and if single click the screen, it will show the next screen.
Here is what I have so far:
import pygame
pygame.init()
pygame.font.init()
# defining the screen
SIZE = (1000, 700)
screen = pygame.display.set_mode(SIZE)
# define time
clock = pygame.time.Clock()
#define button
button = 0
# define font
fontIntro = pygame.font.SysFont("Times New Roman",30)
# define draw scene
def drawIntro(screen):
#start
if button > 0:
screen.fill((0, 0, 0))
text = fontIntro.render("Sigle click to start", 1, (255,255,255))
screen.blit(text, (300, 300, 500, 500))
pygame.display.flip()
#page1
if button == 1:
screen.fill((0, 0, 0))
text = fontIntro.render("page 1", True, (255, 255, 255))
pygame.display.flip()
#page2
if button == 1:
screen.fill((0, 0, 0))
text = fontIntro.render("page 2", True, (255, 255, 255))
screen.blit(text, (300,220,500,200))
pygame.display.flip()
#page3
if button == 1:
screen.fill((0, 0, 0))
text = fontIntro.render("page3", True, (255, 255, 255))
screen.blit(text, (200,190,500,200))
pygame.display.flip()
running = True
while running:
for evnt in pygame.event.get():
if evnt.type == pygame.QUIT:
running = False
if evnt.type == pygame.MOUSEMOTION:
mx,my = evnt.pos
print(evnt.pos)
drawIntro(screen)
pygame.quit()
Though it is not working, can someone please help?! Thanks!
You define button = 0 at the beginning, but never change its value in your main loop. In your drawIntro function, you check if button > 0 or if button == 1
So obviously you never execute any of those if statements.
You need to catch the mouse button by calling pygame.mouse.get_pressed() and figure how to switch correctly to the next page.
By the way, you also have if button == 1 three times, which is not what you want I guess, because the if statements will be immediately executed as they are written, so your page 3 will be shown immediately. You need some counter to keep track of which page you need to show next time the mouse button is pressed.
You need to increment the button counter when the user presses a mouse button.
The drawIntro function shouldn't be called in the event loop once per pygame.MOUSEMOTION event but in the main while loop. Also, change MOUSEMOTION to MOUSEBUTTONDOWN to increment the button once per click.
The conditionals in the drawIntro function are incorrect.
import pygame
pygame.init()
SIZE = (1000, 700)
screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()
button = 0
fontIntro = pygame.font.SysFont("Times New Roman",30)
def drawIntro(screen):
#start
if button == 0: # == 0
screen.fill((0, 0, 0))
text = fontIntro.render("Sigle click to start", 1, (255,255,255))
screen.blit(text, (300, 300, 500, 500))
elif button == 1: #page1
screen.fill((0, 0, 0))
text = fontIntro.render("page 1", True, (255, 255, 255))
screen.blit(text, (300,220,500,200))
elif button == 2: #page2
screen.fill((0, 0, 0))
text = fontIntro.render("page 2", True, (255, 255, 255))
screen.blit(text, (300,220,500,200))
elif button == 3: #page3
screen.fill((0, 0, 0))
text = fontIntro.render("page3", True, (255, 255, 255))
screen.blit(text, (200,190,500,200))
running = True
while running:
for evnt in pygame.event.get():
if evnt.type == pygame.QUIT:
running = False
if evnt.type == pygame.MOUSEBUTTONDOWN: # Once per click.
button += 1
drawIntro(screen)
pygame.display.flip()
pygame.quit()

Main menu help (pygame)

I have created mouse clicking functions to print (start, options and about) when I click those buttons. I just don't know how to go to the next stage of actually opening a new page once clicking those buttons. I had a go with trying to screen.fill when clicking the button but it would only last a couple of seconds and buttons would appear in front of it.
I am fairly new to pygame.
Here is my code so far,
import pygame
from pygame import *
pygame.init()
screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
HOVER_COLOR = (50, 70, 90)
#Background Music
pygame.mixer.music.load('game.ogg')
pygame.mixer.music.set_endevent(pygame.constants.USEREVENT)
pygame.mixer.music.play()
pygame.display.update()
clock.tick(15)
#Background
bg = pygame.image.load("greybackground.png")
#Fonts
FONT = pygame.font.SysFont ("Times New Norman", 60)
text1 = FONT.render("START", True, WHITE)
text2 = FONT.render("OPTIONS", True, WHITE)
text3 = FONT.render("ABOUT", True, WHITE)
#Buttons
rect1 = pygame.Rect(300,300,205,80)
rect2 = pygame.Rect(300,400,205,80)
rect3 = pygame.Rect(300,500,205,80)
buttons = [
[text1, rect1, BLACK],
[text2, rect2, BLACK],
[text3, rect3, BLACK],
]
running = False
def game_intro():
while not running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.MOUSEMOTION:
for button in buttons:
if button[1].collidepoint(event.pos):
button[2] = HOVER_COLOR
else:
button[2] = BLACK
screen.blit(bg, (0, 0))
for text, rect, color in buttons:
pygame.draw.rect(screen, color, rect)
screen.blit(text, rect)
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
if rect1.collidepoint(event.pos):
screen.fill((0, 0, 0))
elif rect2.collidepoint(event.pos):
print ('options')
elif rect3.collidepoint(event.pos):
print ('about')
if event.type == KEYDOWN:
if (event.key == K_UP):
print ("UP was pressed")
elif (event.key == K_DOWN):
print ("DOWN was pressed")
elif (event.key == K_w):
print ("W was pressed")
elif (event.key == K_s):
print ("S was pressed")
else:
print ("error")
pygame.display.flip()
clock.tick(60)
game_intro()
pygame.quit()
I actually had to do a similar thing myself. This is what you would put at the bottom:
while running:
event = pygame.event.wait()
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
x,y = pygame.mouse.get_pos()
if 300 <= x <= 505 and 300 <= y <= 380:
#change stuff here
running = False
#insert code here \/ for the next screen
This can be used universally for every button. If you need more buttons, just copy and paste the third if statment and change as needed.
Don't forget to do 'pygame.display.update()' to refresh the screen; else, you will see nothing change (which is what happened to me).
I hope this helps!

Categories

Resources