import pygame, sys, os.path
pygame.init()
# set up the colours
# R G B
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 50, 130, 255)
screen_surf = pygame.display.set_mode((500,500), 0, 24)
pygame.display.set_caption("Lewis' Menu")
screen_surf.fill((100,0,0))
class Button():
def create(self,w,h,colour):
self.button_surf = pygame.Surface((w,h), 0, 24)
self.button = pygame.draw.rect(self.button_surf, colour, (0, 0, w, h))
def view(self,text,x,y):
width = self.button_surf.get_width()
height = self.button_surf.get_height()
sys_font = pygame.font.SysFont(("None"), 25)
rendered = sys_font.render(text,0,(255,255,255))
self.button_surf.blit(rendered, ((width - 140),((height / 2) - 10)))
screen_surf.blit(self.button_surf, (x,y))
start_button = Button()
start_button.create(300,100,BLUE), start_button.view("Clicky Button!",10,10)
exit_button = Button()
exit_button.create(300,50,GREEN), exit_button.view("Exit!",10,200)
while True:
pos = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONUP:
if start_button.button.collidepoint(pos):
print("You opened a chest!")
if exit_button.button.collidepoint(pos):
pygame.quit()
sys.exit()
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
The 'button click' functionality works by checking to see if the mouse position overlaps the button rect. I can reposition the blitted view of the rectangle in the Button.view() method, but the actual rectangle doesn't move with it, which makes the clicking functionality trigger in the wrong location in the window. Is there any way to move the actual button rectangle collision along with the blitted view of it?
Thanks in advance.
I'd replace the create method with an __init__ method in which the background surface, the text surface and their corresponding rects are created. That allows you to pass all the needed parameters during the instantiation:
start_button = Button(10, 10, 300, 100, "Clicky Button!", BLUE)
Use the parameters to place the self.button rect at the desired coordinates:
self.button = pygame.Rect(x, y, w, h)
You can also use the get_rect method of the button surface to create the rect (see the text_rect creation).
The only purpose of the view method is to blit the surfaces at their rects.
import sys
import pygame
pygame.init()
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 50, 130, 255)
screen_surf = pygame.display.set_mode((500,500), 0, 24)
screen_surf.fill((100,0,0))
clock = pygame.time.Clock()
# No need to recreate the font object all the time.
SYS_FONT = pygame.font.SysFont(None, 25)
class Button():
def __init__(self, x, y, w, h, text, colour):
self.button_surf = pygame.Surface((w,h), 0, 24)
self.button_surf.fill(colour)
self.button = pygame.Rect(x, y, w, h)
self.text_surf = SYS_FONT.render(text, False, (255,255,255))
# Pass the center coords of the button rect to the newly
# created text_rect for the purpose of centering the text.
self.text_rect = self.text_surf.get_rect(center=self.button.center)
def view(self, screen_surf):
screen_surf.blit(self.button_surf, self.button)
screen_surf.blit(self.text_surf, self.text_rect)
# Button() calls the __init__ method.
start_button = Button(10, 10, 300, 100, "Clicky Button!", BLUE)
start_button.view(screen_surf) # Call `view` in a separate line.
exit_button = Button(10, 200, 300, 50, "Exit!", GREEN)
exit_button.view(screen_surf)
while True:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONUP:
if start_button.button.collidepoint(event.pos):
print("You opened a chest!")
elif exit_button.button.collidepoint(event.pos):
pygame.quit()
sys.exit()
elif event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
clock.tick(60) # Limit the frame rate to 60 FPS.
Related
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
I need to draw text into the buttons, which can be seen as the four smaller rectangles in my program, alongside this I need to draw text onto the title as well. I am unsure on how to do this, as the structure of my program, is different to others that I have seen.
Followed other questions, and the answer they've received in an attempt to influence mine.
import pygame
import sys
def main():
pygame.init()
clock = pygame.time.Clock()
fps = 60
size = [700, 600]
bg = [255, 255, 255]
font = pygame.font.Font('freesansbold.ttf', 32)
screen = pygame.display.set_mode(size)
black = (0, 0, 0)
button = pygame.Rect(400, 400, 250, 125)
button2 = pygame.Rect(50, 400, 250, 125)
button3 = pygame.Rect(400, 250, 250, 125)
button4 = pygame.Rect(50, 250, 250, 125)
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 button.collidepoint(mouse_pos):
# prints current location of mouse
print('Instructions'.format(mouse_pos))
if button2.collidepoint(mouse_pos):
# prints current location of mouse
print('Controls'.format(mouse_pos))
if button3.collidepoint(mouse_pos):
# prints current location of mouse
print('Information'.format(mouse_pos))
if button4.collidepoint(mouse_pos):
# prints current location of mouse
print('Start Game'.format(mouse_pos))
screen.fill(bg)
pygame.draw.rect(screen, black, (button)) # draw button
pygame.draw.rect(screen, black, (button2))
pygame.draw.rect(screen, black, (button3))
pygame.draw.rect(screen, black, (button4))
pygame.draw.rect(screen, black, (50, 25, 600, 200))
pygame.display.update()
clock.tick(fps)
pygame.quit()
sys.exit
if __name__ == '__main__':
main()
I expect the buttons to have text on them, so in the future when I click on them they will open a new window.
If you want to use pygame.font, the you've to render the text by pygame.font.Font.render:
e.g.
red = (255, 0, 0)
button = pygame.Rect(400, 400, 250, 125)
text = font.render("button 1", True, red)
The result is a pygame.Surface, which can be .blit to the center of the rectangular button area:
pygame.draw.rect(screen, black, button)
textRect = text.get_rect()
textRect.center = button.center
screen.blit(text, textRect)
The other option is to use pygame.freetype:
e.g.
import pygame.freetype
ft_font = pygame.freetype.SysFont('Times New Roman', 32)
An to render the text directly to the screen by pygame.freetype.Font.render_to
text2 = "button 2"
textRect2 = ft_font.get_rect("button 2")
pygame.draw.rect(screen, black, button2)
textRect2.center = button2.center
ft_font.render_to(screen, textRect2, text2, red)
I've been watching a bunch of tutorials and new to pygame and coding in general. None of the tutorials I watched helped me with this. What i'm aiming for is for the buttons to change the button to a different colour when the user hovers over the button. Below is my entire code for the main menu so far.
import pygame
import time
import random
pygame.init()
size = (800, 600)
screen = pygame.display.set_mode(size)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
pygame.display.set_caption("Basketball Shootout")
clock = pygame.time.Clock()
#GAME INTRO
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
#print(event)
if event.type == pygame.QUIT:
pygame.quit()
quit()
#Font's and text
font = pygame.font.SysFont ("Times New Norman", 60)
text = font.render ("", True, WHITE)
#Background Image
background_images = pygame.image.load("greybackground.jpg").convert()
screen.blit(background_images, [0,0])
screen.blit(text, (150, 50))
#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)
#BUTTONS
screen.blit(text, (150, 50))
pygame.draw.rect(screen,(0,0,0),(300,300,205,80));
pygame.draw.rect(screen,(0,0,0),(300,400,205,80));
pygame.draw.rect(screen,(0,0,0),(300,500,205,80));
font = pygame.font.SysFont ("Times New Norman, Arial", 30)
text = font.render ("START", True, WHITE)
screen.blit(text, (340, 320))
font = pygame.font.SysFont ("Times New Norman, Arial", 30)
text = font.render ("OPTIONS", True, WHITE)
screen.blit(text, (340, 420))
font = pygame.font.SysFont ("Times New Norman, Arial", 30)
text = font.render ("ABOUT", True, WHITE)
screen.blit(text, (340, 520))
pygame.display.flip();
#Quit Pygame
game_intro()
pygame.quit
I recommend storing the button data (text surface, rect, color) in a list of lists. When the mouse moves, pygame.MOUSEMOTION events get added to the event queue. In the event loop check if the mouse moved and then iterate over your buttons and set the color of colliding buttons to the hover color, reset the others to black. Blit the rects and text surfaces in a for loop as well.
import pygame
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)
# Don't define new font objects in your while loop (that's inefficient).
FONT = pygame.font.SysFont ("Times New Norman", 60)
# If the text surfaces and button rects don't change,
# you can define them once outside of the while loop.
text1 = FONT.render("START", True, WHITE)
text2 = FONT.render("OPTIONS", True, WHITE)
text3 = FONT.render("ABOUT", True, WHITE)
rect1 = pygame.Rect(300,300,205,80)
rect2 = pygame.Rect(300,400,205,80)
rect3 = pygame.Rect(300,500,205,80)
# The buttons consist of a text surface, a rect and a color.
buttons = [
[text1, rect1, BLACK],
[text2, rect2, BLACK],
[text3, rect3, BLACK],
]
def game_intro():
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.MOUSEMOTION:
for button in buttons:
# button[1] is the rect. Use its collidepoint method with
# the `event.pos` (mouse position) to detect collisions.
if button[1].collidepoint(event.pos):
# Set the button's color to the hover color.
button[2] = HOVER_COLOR
else:
# Otherwise reset the color to black.
button[2] = BLACK
screen.fill((20, 50, 70))
# Draw the buttons with their current colors at their rects.
# You can unpack the button lists directly in the head of the loop.
for text, rect, color in buttons:
pygame.draw.rect(screen, color, rect)
screen.blit(text, rect)
pygame.display.flip()
clock.tick(15)
game_intro()
pygame.quit()
I'd actually recommend defining a Button class, but I'm not sure if you're already familiar with classes/object-oriented programming.
The buttons also need callback functions to actually do something. Take a look at my answer here: https://stackoverflow.com/a/47664205/6220679
I would recommend creating a function for this:
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x + w > mouse[0] > x and y + h > mouse[1] > y:
gameDisplay.blit(active, (x, y))
else:
gameDisplay.blit(inactive, (x, y))
and then in you game intro call you function like this:
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
#print(event)
if event.type == pygame.QUIT:
pygame.quit()
quit()
# For example
button(100, 350, 195, 80, startBtn, startBtn_Hover)
This is what each parameter means:
x: x-coordinate of button
y: y-coordinate of button
w: width of button
h: height of button
active: picture when mouse is hovered over button
inactive: picture when button is idle
#Importing Modules
import pygame
import sys
import random
#All pygame stuff under here
pygame.init()
#Font definitions
backFont = pygame.font.SysFont("monospace",40)
titleFont = pygame.font.SysFont("garamond", 100)
buttonFont = pygame.font.SysFont("garamond", 25)
bigFont = pygame.font.SysFont("garamond",100)
#Colour definitions
BackGray = pygame.Color('gray60')
screenGray = pygame.Color('gray80')
buttonGray1 = pygame.Color('gray40')
buttonGray2 = pygame.Color('gray50')
buttonGray3 = pygame.Color('gray30')
textColour = pygame.Color('navy')
#Screen size set
screen = pygame.display.set_mode((800, 600))
#Class for the buttons set here
class Button:
def __init__(self, x, y, width, height, colour, surface):
self.x = x
self.y = y
self.height = height
self.width = width
self.colour = colour
self.surface = surface
def isPressed(self):
mouse_position = pygame.mouse.get_pos()
mouse_x = mouse_position[0]
mouse_y = mouse_position[1]
if mouse_x > self.x:
if mouse_x < self.x + self.width:
if mouse_y > self.y:
if mouse_y < self.y + self.height:
mouse_click = pygame.mouse.get_pressed()
left_click = mouse_click[0]
if left_click:
self.colour = (0,0,0)
return True
self.colour = (230, 230, 230)
return False
def drawButton(self):
pygame.draw.rect(self.surface, self.colour, (self.x, self.y, self.width, self.height))
pygame.display.flip()
def FrontPage():
#Back screen
screen.fill(screenGray)
#The background is defined here
BinaryPage = []
for i in range(0,15):
BinaryString = ""
for j in range(0,33):
BinaryString += random.choice(["0","1"])
BinaryPage.append(BinaryString)
for i in range(0,15):
screen.blit(backFont.render(BinaryPage[i], 1, BackGray), (0,i * 40))
#The title is defined and printed here
Title1 = titleFont.render("The Six", 10, textColour)
Title2 = titleFont.render("Cipher", 10, textColour)
Title3 = titleFont.render("Simulator", 10, textColour)
screen.blit(Title1, (100, 100))
screen.blit(Title2, (100, 200))
screen.blit(Title3, (100, 300))
#Text for the button
buttonText = buttonFont.render("Continue", 10, textColour)
screen.blit(buttonText, (115,405))
#Where the buttons are defined and drawn
ButtonBig = Button(100, 450, 120, 60, buttonGray1, screen)
ButtonSmall = Button(105, 455, 110, 50, buttonGray2, screen)
ButtonBig.drawButton()
ButtonSmall.drawButton()
#Pygame While loop
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if ButtonBig.isPressed():
print("Hello")
break
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
clock.tick(60)
The above code runs a window that has 0's and 1's in a random order as the background, with the title of my program in the middle.
Then, there should be a button at the bottom, or a grey rectangle. However, when I try to .blit, or print, something onto the button frame, after I have drawn the button onto the screen, it does not appear.
Can anybody tell me why and how to fix it?
Or any alternatives of how to output text onto the buttons.
Thanks in advance
I'd first create a separate background surface and blit all the background graphics which never change onto it (the numbers in the following example). In the main loop you can just blit this background to clear the screen.
To blit text onto a button:
Pass the text to the __init__ method
create the button image (a pygame.Surface)
render the text
create rects for the image and the text (pass the center of the image rect to the text rect to center the text)
blit the text surface onto the image.
For the buttons I'd use sprites and put them into a sprite group, so that you can draw them simply by calling sprite_group.draw(screen). Sprites need an image and a rect attribute to work. Pygame rects have collision detection methods that you should use instead of writing your own. In this case we can use the collidepoint method and pass the event.pos to it.
import random
import pygame as pg
pg.init()
screen = pg.display.set_mode((800, 600))
FONT = pg.font.SysFont('garamond', 25)
SCREEN_GRAY = pg.Color('gray80')
BUTTON_GRAY = pg.Color('gray40')
TEXT_COLOUR = pg.Color('navy')
# Inherit from pg.sprite.Sprite. That will allow you to
# put the instances into a sprite group.
class Button(pg.sprite.Sprite):
def __init__(self, text, x, y, width, height, colour):
super().__init__()
# Create the image of the button.
self.image = pg.Surface((width, height))
self.image.fill(colour)
# A pygame.Rect will serve as the blit position.
self.rect = self.image.get_rect()
# Render the text.
txt = FONT.render(text, True, TEXT_COLOUR)
# This txt_rect is used to center the text on the image.
txt_rect = txt.get_rect(center=self.rect.center)
self.image.blit(txt, txt_rect)
# Set the position of the image rect.
self.rect.topleft = x, y
def is_pressed(self, event):
if event.type == pg.MOUSEBUTTONDOWN:
# MOUSE... events have an event.pos attribute (the mouse position)
# which you can pass to the collidepoint method of the rect.
if self.rect.collidepoint(event.pos):
return True
return False
def main():
button_big = Button('big button', 100, 250, 120, 60, BUTTON_GRAY)
button_small = Button('small button', 105, 455, 120, 50, BUTTON_GRAY)
buttons_group = pg.sprite.Group(button_big, button_small)
background = pg.Surface(screen.get_size())
background.fill(SCREEN_GRAY)
for i in range(screen.get_height()//40):
for j in range(screen.get_width()//40):
n = random.choice(['0', '1'])
background.blit(FONT.render(n, True, BUTTON_GRAY), (j*40, i*40))
clock = pg.time.Clock()
while True:
for event in pg.event.get():
if event.type == pg.QUIT:
return
if button_big.is_pressed(event):
print('big')
elif button_small.is_pressed(event):
print('small')
screen.blit(background, (0, 0))
# Blit the images of the contained sprites onto the screen.
buttons_group.draw(screen)
pg.display.flip()
clock.tick(60)
if __name__ == '__main__':
main()
pg.quit()
I am trying to make a hangman game in pygame, but I cannot get buttons to work after they have been created from an event (in my case after pressing enter), they appear on screen but do not work ( rollover or activate events), please help!
from pygame.locals import *
import pygame, sys, eztext
import time
pygame.init()
Black = ( 0, 0, 0)
Grey = (100, 100, 100)
DarkGrey = (70, 70, 70)
White = (255, 255, 255)
Blue = ( 0, 0, 255)
NavyBlue = ( 60, 60, 100)
Cyan = ( 0, 255, 255)
Purple = (255, 0, 255)
Red = (255, 0, 0)
DarkRed = (180, 0, 0)
Orange = (255, 128, 0)
Yellow = (255, 255, 0)
Green = ( 0, 255, 0)
DarkGreen = ( 0, 180, 0)
LightBlue = ( 90, 164, 213)
Magenta = (153, 0, 76)
screen = pygame.display.set_mode((1000,600),0,32)
screen.fill(Orange)
txtbx = eztext.Input(maxlength=45, color=(0,0,0), prompt='Enter username: ')
def text_objects(text, font):
textSurface = font.render(text, True, Black)
return textSurface, textSurface.get_rect()
smallText = pygame.font.Font("freesansbold.ttf",20)
def button(msg,x,y,w,h,ic,ac,action=None):
if x+w > mouse[0] > x and y+h > mouse[1] > y:
pygame.draw.rect(screen, ac,(x, y, w, h))
if click [0] == 1 and action!= None:
if action == "Quit":
pygame.quit()
if action == "Single player":
pygame.draw.rect(screen, Green,(10, 10, 500, 500))
else:
pygame.draw.rect(screen, ic,(x, y, w, h))
smallText = pygame.font.Font("freesansbold.ttf",20)
textSurf, textRect = text_objects(msg, smallText)
textRect.center = ((x+(w/2)), (y + (h/2)))
screen.blit(textSurf, textRect)
while True:
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
string1 = txtbx.value
pygame.display.update()
time.sleep(0.02)
pygame.draw.rect(screen, Green,(10, 100, 500, 50))
clock = pygame.time.Clock()
clock.tick(30)
events = pygame.event.get()
txtbx.set_pos(10,110)
label = smallText.render("Enter you user name and then press enter!", 1, (0,0,0))
screen.blit(label, (10, 10))
for event in events:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_KP_ENTER or event.key == pygame.K_RETURN:
button("Single player",10, 400, 150, 50, Green, DarkGreen,"Single player")
if string1 in open('Users.txt').read():
username = string1
Welcomeold1 = smallText.render('Welcome back', 1, (0,0,0))
screen.blit(Welcomeold1, (10, 200))
Welcomeold2 = smallText.render(username, 1, (0,0,0))
screen.blit(Welcomeold2, (160, 200))
else:
username = string1
f = open('Users.txt','a')
string1 = txtbx.value
f.write(string1)
f.write('\n')
f.close()
Welcomenew1 = smallText.render('Welcome to my game', 1, (0,0,0))
screen.blit(Welcomenew1, (10, 200))
Welcomenew2 = smallText.render(username, 1, (0,0,0))
screen.blit(Welcomenew2, (230, 200))
if event.key == pygame.K_BACKSPACE:
screen.fill(Orange)
txtbx.update(events)
txtbx.draw(screen)
pygame.display.flip()
if __name__ == '__main__': main()
button function is inside event.key so it will work only when RETURN is pressed, released, and pressed again, and released again, etc.
You should create class with method draw and handle_event to use this method in mainloop in different places. You can create button in event.key but you have to check button pressed in different place.
-
Simple button. Full working example.
When you press button function do_it is called and background changed color.
#
# pygame (simple) template - by furas
#
# ---------------------------------------------------------------------
import pygame
import pygame.gfxdraw
import random
# === CONSTANS === (UPPER_CASE names)
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
CYAN = ( 0, 255, 255)
MAGENTA = (255, 0, 255)
YELLOW = (255, 255, 0)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
# === CLASSES === (CamelCase names)
class Button():
def __init__(self, text, x, y, width, height, on_click=None, fg_color=RED, bg_color=WHITE, font_size=35):
self.text = text
font = pygame.font.SysFont(None, font_size)
# rectangle - without position, to put text in correct place
self.rect = pygame.Rect(0, 0, width, height)
# normal button - fill background
self.normal_image = pygame.surface.Surface( self.rect.size )
self.normal_image.fill(bg_color)
# normal button - add text
text_image = font.render(text, True, fg_color)
text_rect = text_image.get_rect(center=self.rect.center)
self.normal_image.blit(text_image, text_rect)
# hover button - fill background
self.hover_image = pygame.surface.Surface( self.rect.size )
self.hover_image.fill(fg_color)
# hover button - add text
text_image = font.render(text, True, bg_color)
text_rect = text_image.get_rect(center=self.rect.center)
self.hover_image.blit(text_image, text_rect)
# set position
self.rect.x = x
self.rect.y = y
# other
self.on_click = on_click
self.hover = False
def draw(self, surface):
# draw normal or hover image
if self.hover:
surface.blit(self.hover_image, self.rect)
else:
surface.blit(self.normal_image, self.rect)
def event_handler(self, event):
# is mouse over button ?
if event.type == pygame.MOUSEMOTION:
self.hover = self.rect.collidepoint(event.pos)
# is mouse clicked ? run function.
if event.type == pygame.MOUSEBUTTONDOWN:
if self.hover and self.on_click:
self.on_click()
# === FUNCTIONS === (lower_case names)
def do_it():
global background_color
if background_color == BLACK:
background_color = RED
elif background_color == RED:
background_color = GREEN
else:
background_color = BLACK
print("Button pressed")
# === MAIN ===
# --- init ---
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
screen_rect = screen.get_rect()
# --- objects ---
# create button
button = Button('CHANGE COLOR', 0, 0, 300, 50, on_click=do_it)
# add function later
#button_quit.on_click = do_it
# center button
button.rect.center = screen_rect.center
# default bacground color - changed in do_it()
background_color = BLACK
# --- mainloop ---
clock = pygame.time.Clock()
is_running = True
while is_running:
# --- events ---
for event in pygame.event.get():
# --- global events ---
if event.type == pygame.QUIT:
is_running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
is_running = False
# --- objects events ---
button.event_handler(event)
# --- updates ---
# empty
# --- draws ---
# clear buffer
screen.fill(background_color)
# draw all objects - widgets (buttons, labels)
button.draw(screen)
clock.tick(25)
# send buffer to video card
pygame.display.update()
# --- the end ---
pygame.quit()