Pygame_widgets button does not execute functions - python

I am trying to make a button in python and I attempted to use the Pygame_widgets library but my functions will not execute
import basic
import pygame as pg
import pygame_widgets as pw
from pygame_widgets.button import Button
def startWindow():
pg.init()
win = pg.display.set_mode((600, 600))
button = Button(
win, 100, 100, 300, 150, text='Hello',
fontSize=50, margin=20,
inactiveColour=(255, 0, 0),
pressedColour=(0, 255, 0), radius=20,
onClick=lambda: basicKit = True
)
run = True
while run:
events = pg.event.get()
for event in events:
if event.type == pg.QUIT:
pg.quit()
run = False
quit()
win.fill((255, 255, 255))
button.listen(events)
button.draw()
pg.display.update()
if __name__ == '__main__':
stop = False
print("* Welcome To \"Drum Easy\" V 1.0 *")
startWindow()
while stop == False:
kit = input("\nWhat Kit? \n\nBasic\n ^\n 1\n\n>")
if kit == "1":
basic.Kit()
stop = True
else: print('Invalid Kit')
see now in the button = Button part of the code has multiple options that can run functions but none of them seem to work, they all seem to have invalid syntax

A lambda must have an expression, not a statement (assignment, if,
while, ...). So add = lambda x: x + 1 is a valid lambda. But
lambda: basicKit = True is syntactically incorrect. You can instead
define a function that updates your variable and gives this
function to the Button constructor.
Something like that:
def update_basic_kit():
global basicKit
basicKit = True
button = Button(
win, 100, 100, 300, 150, text='Hello',
fontSize=50, margin=20,
inactiveColour=(255, 0, 0),
pressedColour=(0, 255, 0), radius=20,
onClick=update_basic_kit
)

Related

Image not printing to screen using 'Blit' Pygame

I am trying to make an Undertale like game in python - However I have a problem. When I try to 'blit' an image to the screen it doesn't show. I am 'blitting' a heart and I have rescaled it to an appropriate size in a 3rd party program.
import pygame # Imports Pygame Library
import keyboard # Imports Keyboard Library
# Defining Image Components
undertale_logo_ico = pygame.image.load('Undertale_Logo.ico')
Soul_Heart_Red = pygame.image.load('UndertaleHeart.png')
# Define Key-presses
def movement(key_pressed):
if key_pressed == 'right':
print('Right')
elif key_pressed == 'left':
print('Left')
elif key_pressed == 'up':
print('Up')
elif key_pressed == 'down':
print('Down')
else:
print('Not registered key')
# Execute Key Presses:
keyboard.on_press_key("right arrow", lambda _: movement('right'))
keyboard.on_press_key("left arrow", lambda _: movement('left'))
keyboard.on_press_key("up arrow", lambda _: movement('up'))
keyboard.on_press_key("down arrow", lambda _: movement('down'))
keyboard.on_press_key("d", lambda _: movement('right'))
keyboard.on_press_key("a", lambda _: movement('left'))
keyboard.on_press_key("w", lambda _: movement('up'))
keyboard.on_press_key("s", lambda _: movement('down'))
# Display Window Configuration
# area = screen.get_rect()
screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
background_colour = (0, 0, 0)
(width, height) = (300, 200)
pygame.display.set_caption('Game 1')
screen.fill(background_colour)
pygame.display.set_icon(undertale_logo_ico)
pygame.display.flip()
# Drawing Player
screen.blit(Soul_Heart_Red, [0, 0])
# Closing Script
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
The blit() is near the bottom of the code.
You have to update the display after blit:
screen.blit(Soul_Heart_Red, [0, 0])
pygame.display.flip() # <---
You have to update the display after the blit.
screen.blit(Soul_Heart_Red, [0, 0])
pygame.display.update()

Why does pygame load slow?

I have a simple project that display a "button" with an image,a text and a background color:
import os
os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide"
import pygame, sys
from pygame.locals import *
import requests
import io
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
GRAY = (200, 200, 200)
class Main_window:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((800, 600))
def draw(self):
Btn1 = Button(0,0,200,200,"hello",color=RED, text="test",text_color=BLACK)
def mainLoop(self):
done = False
while not done:
eventlist = pygame.event.get()
for ev in eventlist:
if ev.type == QUIT:
done = True
if ev.type == MOUSEBUTTONDOWN:
Button.getButton(ev)
pygame.quit()
class Button:
Buttons = []
def __init__(self, left, top, w, h,function,color=RED, text="", text_color = BLACK):
self.left = left
self.top = top
self.w = w
self.h = h
self.right = self.left+w
self.bottom = self.top+h
self.function = function
surf1 = pygame.Surface((w, h))
surf1.fill(color)
rect1 = pygame.Rect(left, top, w, h)
main.screen.blit(surf1, rect1)
Button.Buttons.append(self)
if text != "":
font1 = pygame.font.SysFont('chalkduster.ttf', 72)
text1 = font1.render(text, True, text_color)
text_rect = text1.get_rect(center=(int(w/2), int(h/2)))
main.screen.blit(text1, text_rect)
image_url = "https://image.flaticon.com/icons/png/512/31/31990.png"
r = requests.get(image_url)
img = io.BytesIO(r.content)
image = pygame.image.load(img)
image = pygame.transform.scale(image, (w, h))
main.screen.blit(image, (0, 0))
pygame.display.flip()
def getButton(event):
for i in Button.Buttons:
x, y = event.pos
if x>=i.left and x<=i.right and y<=i.bottom and y>=i.top:
eval(i.function+"()")
def hello():
print("hello")
main = Main_window()
main.draw()
main.mainLoop()
that's works fine but the problem is that when i launch the game it load the main window, wait some time(something like 1 second) and then load the button.I tried to add more button and it loaded them one at a time.I don't undestand why.
Two Fixes
Use a local image rather than an image sent with requests
It loads slowly maybe because of the draw function of the MainWindow class.
Try this in the main loop function
def mainLoop(self):
done = False
while not done:
eventlist = pygame.event.get()
for ev in eventlist:
if ev.type == QUIT:
done = True
if ev.type == MOUSEBUTTONDOWN:
Button.getButton(ev)
self.draw()
pygame.display.flip()
pygame.quit()
And at the end
main = Main_window()
main.mainLoop()
So you don't have to call main.draw() because it is already being called in the main loop.

How do I get a picture to appear when I press a key?

I'm trying to make Tic-Tac-Toe in Python, but I've run into a problem. I can't figure out how to let the players make a selection on the board. I have been trying to get an "X" in the top left square of the board. The "X" and "O" are both images, not text. The background is also an image. Every time I run my code, The window opens, the board and title are both their, but when I press the "1" key, nothing happens. Does anyone know what to do about this? I'm not sure which parts of my code are wrong so here's all of it:
import pygame
import os
import sys
from pygame.locals import *
pygame.init()
WIDTH, HEIGHT = 500, 500
P_WIDTH, P_HEIGHT = 100, 130
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
main_font = pygame.font.SysFont("Comic sans", 40)
#color = (255, 255, 255)
#light_color = (170, 170, 170)
#dark_color = (100, 100, 100)
def redraw_window():
BG = pygame.transform.scale(pygame.image.load(os.path.join("Board.jpg")).convert_alpha(), (WIDTH, HEIGHT))
title_label1 = main_font.render("Tic", True, (0, 0, 0))
title_label2 = main_font.render("Tac", True, (0, 0, 0))
title_label3 = main_font.render("Toe", True, (0, 0, 0))
Player_1 = pygame.transform.scale(pygame.image.load(os.path.join("X.jpg")).convert_alpha(), (P_WIDTH, P_HEIGHT))
WIN.blit(BG, (0, 0))
WIN.blit(title_label1, (10, 10))
WIN.blit(title_label2, (10, 40))
WIN.blit(title_label3, (10, 70))
pygame.display.update()
def main():
while True:
redraw_window()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit(0)
elif event.type == pygame.locals.KEYDOWN:
if event.key == K_1:
WIN.blit(Player_1, (72, 35))
main()
Also, if anyone sees something that could be improved, could you point that as well?
So you're getting an error, it's best if you include this detail in your question.
pygame 2.0.1 (SDL 2.0.14, Python 3.6.9)
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
File "./bad_noughts.py", line 47, in <module>
main()
File "./bad_noughts.py", line 44, in main
WIN.blit(Player_1, (72, 35))
NameError: name 'Player_1' is not defined
Inside the main() function, Python doesn't know about Player_1 because it's "local" to the function redraw_window() - that means that only the redraw_window() function knows about Player_1.
So how do you fix this?
The quickest and simplest way is to move the definition of Player_1 to the main program, giving it a "global" scope.
This fixes the error, but the 'X' still doesn't appear... why? The next problem is that you're only drawing the 'X' when the 1 event is received. Then (almost immediately) the background is re-painted again, covering it up. It's only on-screen for a split-second.
One way to fix this is to separate the state of the board with the drawing of the board.
Let's introduce a new list-of-lists board_state, which has 3 rows of 3 cells, one for each area of your nought-and-crosses board:
board_state = [ [ None, None, None ],
[ None, None, None ],
[ None, None, None ] ]
Using this, we can set and check the layout of the moves on the board by saying something like: board[0][0] (top-left) and board[2][2] (bottom-right). One important thing you just realised, is that lists are "zero-indexed", meaning the very first element is at number-0 (not 1)
So now when the player makes a move, we can just set the board state:
elif event.type == pygame.locals.KEYDOWN:
if event.key == K_1:
board_state[0][0] = 'x' # top-left
Now we need to adjust the window drawing function to look at the board-state, and draw what's needed:
def redraw_window():
global board_state
WIN.blit(BG, (0, 0))
WIN.blit(title_label1, (10, 10))
WIN.blit(title_label2, (10, 40))
WIN.blit(title_label3, (10, 70))
x_cursor = 0 # position on the board
y_cursor = 0
for row in ( 0, 1, 2 ):
x_cursor = 0
for col in ( 0, 1, 2 ):
# if there's a move on the board, draw it
if ( board_state[row][col] == 'x' ):
WIN.blit( Player_1, ( x_cursor, y_cursor ) )
elif ( board_state[row][col] == 'o' ):
WIN.blit( Player_2, ( x_cursor, y_cursor ) )
x_cursor += WIDTH//3 # move the cursor across
y_cursor += HEIGHT//3 # move the cursor down
pygame.display.update()
So the loops iterate through the rows and columns of the board_state. Using the (0, 1, 2) in the loop isn't best-practice, but I'm trying to keep it simple. As the loops move through the board, across then down, we also maintain a cursor-position where any player-move should be drawn.
If the board contains an 'x' or 'o', the correct bitmap is drawn. Except this code is a bit rough, so the co-ordinates will probably be a bit off, but I don't have your bitmaps, so that's the best we can do.
Reference Code:
import pygame
import os
import sys
from pygame.locals import *
pygame.init()
WIDTH, HEIGHT = 500, 500
P_WIDTH, P_HEIGHT = 100, 130
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
main_font = pygame.font.SysFont("Comic sans", 40)
#color = (255, 255, 255)
#light_color = (170, 170, 170)
#dark_color = (100, 100, 100)
BG = pygame.transform.scale(pygame.image.load(os.path.join("ox_board.png")).convert_alpha(), (WIDTH, HEIGHT))
Player_1 = pygame.transform.scale(pygame.image.load(os.path.join("ox_x.png")).convert_alpha(), (P_WIDTH, P_HEIGHT))
Player_2 = pygame.transform.scale(pygame.image.load(os.path.join("ox_o.png")).convert_alpha(), (P_WIDTH, P_HEIGHT))
title_label1 = main_font.render("Tic", True, (0, 0, 0))
title_label2 = main_font.render("Tac", True, (0, 0, 0))
title_label3 = main_font.render("Toe", True, (0, 0, 0))
# moves (or not) placed on the board
# None -> no move yet
# Or 'x', 'o'
board_state = [ [ None, None, None ],
[ None, None, None ],
[ None, None, None ] ]
def redraw_window():
global board_state
WIN.blit(BG, (0, 0))
WIN.blit(title_label1, (10, 10))
WIN.blit(title_label2, (10, 40))
WIN.blit(title_label3, (10, 70))
x_cursor = 0 # position on the board
y_cursor = 0
for row in ( 0, 1, 2 ):
x_cursor = 0
for col in ( 0, 1, 2 ):
# if there's a move on the board, draw it
if ( board_state[row][col] == 'x' ):
WIN.blit( Player_1, ( x_cursor, y_cursor ) )
elif ( board_state[row][col] == 'o' ):
WIN.blit( Player_2, ( x_cursor, y_cursor ) )
x_cursor += WIDTH//3 # move the cursor across
y_cursor += HEIGHT//3 # move the cursor down
pygame.display.update()
def main():
while True:
redraw_window()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit(0)
elif event.type == pygame.locals.KEYDOWN:
if event.key == K_1:
board_state[0][0] = 'x'
main()
The board_state also allows you to check whether a move has been made in the cell already. Assume the player pushes 5 (centre cell), you can just check board_state[1][1] != None to test if a move was already placed in that cell.

Threading issue with Pygame

I am developing a small game for learning purposes. I have created a simple animation for the title screen. Since there is also a function for full screen in the code, I wanted to create a title screen that:
Displayed the animation
Turned into full screen when the key was activated
Continued the animation at the point it was before activating full screen
In order to do this, I resorted to threading. However, this is the first time I tried to do any multi-threading, and I donĀ“t know what did I do wrong. The result is an undetermined error.
The code for the title screen is this:
try:
GameAnimation = threading.Thread(target=GameTitleAnimation, (Window, WindowDimensions, FontDictionary, CurrentVersion))
GameAnimation.start()
except:
print "There was an error while loading the screen. Press one key to exit the program."
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
Quit()
if event.type == pygame.KEYDOWN:
if event.key == K_ESCAPE:
Quit()
elif event.key == K_f:
Fullscreen(Window, WindowDimensions)
else:
return
The code for the animation is:
TitleWhite = [255, 255, 255, 0]
Black = BASE_BLACK
TitleLetters = ("R", "O", "G", "U", "E", " ", "H", "U", "N", "T", "E", "R")
Title = FontDictionary["TitleFont"][1].render("ROGUE HUNTER", False, TitleWhite)
TextWidth = Title.get_width()
TextHeight = Title.get_height()
TitleXPosition = (WindowDimensions[0] - TextWidth) / 2
TitleYPosition = (WindowDimensions[1] / 2) - (TextHeight / 2)
for letter in TitleLetters:
if letter == " ":
TitleXPosition += CurrentLetterWidth
else:
while TitleWhite[3] < 100:
TitleWhite[3] += 1
CurrentLetter = FontDictionary["TitleFont"][1].render(letter, False, TitleWhite)
CurrentLetter.set_alpha(TitleWhite[3])
Window.blit(CurrentLetter, (TitleXPosition, TitleYPosition))
time.sleep(0.008)
try:
pygame.display.update()
except Exception:
traceback.print_exception
TitleWhite[3] = 0
CurrentLetterWidth = CurrentLetter.get_width()
TitleXPosition += CurrentLetterWidth
FadeInSurface = pygame.Surface((WindowDimensions[0], WindowDimensions[1]))
FadeInSurface.fill(TitleWhite)
OpacityRounds = 1
while TitleWhite[3] < 100.0:
TitleWhite[3] = 1.1 ** OpacityRounds
FadeInSurface.set_alpha(TitleWhite[3])
Window.blit(FadeInSurface, (0, 0))
OpacityRounds += 1
pygame.display.update()
time.sleep (0.015)
time.sleep(0.7)
TitleXPosition = (WindowDimensions[0] - TextWidth) / 2
Version = FontDictionary["BodyFont"][1].render(CURRENT_VERSION, False, TitleWhite)
VersionHeight = Version.get_height()
VersionWidth = Version.get_width()
VersionXPosition = (WindowDimensions[0] - VersionWidth) / 2
VersionYPosition = TitleYPosition + TextHeight
while True:
pygame.draw.rect(Window, Black, (0, 0, WindowDimensions[0], WindowDimensions[1]), 0)
Window.blit(Title, (TitleXPosition, TitleYPosition))
Window.blit(Version, (VersionXPosition, VersionYPosition))
pygame.display.update()
I'd be very grateful if anyone could help me with this. I am going crazy.
There's no reason to use threading in your code. It will only make your code harder to read, harder to debug and error prone.
Usually you want to have some kind of state in your game that you use to determinate what should happen in a frame. You can find a class based example here.
Another way to handle this, which is a bit similar to your code, is to use coroutines.
Look at your animation code and instead of calling pygame.display.update(), give the control back to the main loop. The main loop will handle events, frame limiting and drawing, then give control back to the coroutine (which keeps track of it's own state).
Here's a simple hacky example:
import pygame
import pygame.freetype
pygame.init()
size = (640, 480)
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
def game_state(surf):
rect = pygame.Rect(200, 200, 32, 32)
while True:
events = yield
pressed = pygame.key.get_pressed()
x = 1 if pressed[pygame.K_RIGHT] else -1 if pressed[pygame.K_LEFT] else 0
rect.move_ip(x*5, 0)
pygame.draw.rect(surf, pygame.Color('dodgerblue'), rect)
yield
def title_state(surf):
text = 'Awesome Game'
colors = [[255, 255, 255, 20] for letter in text]
font = pygame.freetype.SysFont(None, 22)
font.origin = True
while True:
for color in colors:
color[3] += 33
if color[3] > 255: color[3] = 0
x = 200
for (letter, c) in zip(text, colors):
bounds = font.get_rect(letter)
font.render_to(surf, (x, 100), letter, c)
x += bounds.width + 1
font.render_to(surf, (180, 150), 'press [space] to start', pygame.Color('grey'))
events = yield
yield
def main():
title = title_state(screen)
game = game_state(screen)
state = title
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_ESCAPE:
return
if e.key == pygame.K_SPACE:
state = game if state == title else title
if e.key == pygame.K_f:
if screen.get_flags() & pygame.FULLSCREEN:
pygame.display.set_mode(size)
else:
pygame.display.set_mode(size, pygame.FULLSCREEN)
screen.fill(pygame.Color('grey12'))
next(state)
state.send(events)
pygame.display.update()
clock.tick(60)
if __name__ == '__main__':
main()
See how the main loop is clean and simple, and all of the game state is handled in the coroutines. The title screen part of the code does not care about fullscreen or not or how to switch to fullscreen, and the main loop does not care of what the title screen coroutine does. And we don't need threading.
In practice it's not that different from the class based example I linked above, but using coroutines makes it easy to implement the title screen animation.
Basically you have an endless loop, you mutate some state (like the color of a letter), and then say "now draw this!" by just calling yield.
This is a large chunk of code to debug.
I'm not familiar with pygame or python threading, but it seems to me that you need to include some debug lines to determine exactly where the error occurs during your game animation thread (if it's even occuring there at all).
Something like this pattern should help determine the source of the problem:
import logging
logging.info("start animation initialization")
...
logging.info("begin animation loop")
...
logging.info("end animation loop")
https://docs.python.org/2/howto/logging.html

Pygame- "Pygbuttons"- How to change button color and sound play simultaneously

I want to change the color of each button inside one by one, on every change in color I want to play one sound.
The sounds are playing perfectly, but the button color is changing only at the end when all of the sounds are played.
What should I do the make the color change and sound play for each button at the same time?
Here is my code:
import pygame, pygbutton, sys
from pygame.locals import *
import time
import threading
from threading import Thread
FPS = 30
WINDOWWIDTH = 1550
WINDOWHEIGHT = 1200
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
BLACK = (0, 0, 0)
GREY = (211, 211, 211)
exitcode = 0
def main():
#1 constants
windowBgColor = WHITE
size=(100,30)
running = 1
#2 initialize
FPSCLOCK = pygame.time.Clock()
pygame.mixer.init(frequency=22050,size=-16,channels=13)
#3 load
zebrasound = pygame.mixer.Sound("resources/audio/zebra.wav")
zlet = pygame.mixer.Sound("resources/audio/Z.wav")
elet = pygame.mixer.Sound("resources/audio/E.wav")
blet = pygame.mixer.Sound("resources/audio/B.wav")
rlet = pygame.mixer.Sound("resources/audio/R.wav")
alet = pygame.mixer.Sound("resources/audio/A.wav")
wrong = pygame.mixer.Sound("resources/audio/fail.wav")
right = pygame.mixer.Sound("resources/audio/chime.wav")
beep = pygame.mixer.Sound("resources/audio/sensor.wav")
flip = pygame.mixer.Sound("resources/audio/flip.wav")
zebrasound.set_volume(3)
zlet.set_volume(3)
elet.set_volume(3)
blet.set_volume(3)
rlet.set_volume(3)
alet.set_volume(3)
wrong.set_volume(3)
right.set_volume(5)
#4 Display
screen = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
pygame.display.set_caption('Animal game')
#5 Buttons
buttonForward = pygbutton.PygButton((700, 900, 600,482), normal='resources/images/arrow.png')
buttonBackward = pygbutton.PygButton((600, 900, 600,482), normal='resources/images/arrowBackward.png')
buttonZebra = pygbutton.PygButton((100, 150, 640,480), normal='resources/images/zebraclip.png')
buttonZebra1 = pygbutton.PygButton((850, 200, 600, 120), 'Z E B R A')
buttonZebra2 = pygbutton.PygButton((850, 400, 600, 120), 'Z A B R A')
buttonZebra3 = pygbutton.PygButton((850, 600, 600, 120), 'Z B R E A')
buttonZebra11 = pygbutton.PygButton((855, 205, 110, 110), 'Z')
buttonZebra12 = pygbutton.PygButton((975, 205, 110, 110), 'E')
buttonZebra13 = pygbutton.PygButton((1095, 205, 110, 110), 'B')
buttonZebra14 = pygbutton.PygButton((1215, 205, 110, 110), 'R')
buttonZebra15 = pygbutton.PygButton((1335, 205, 110, 110), 'A')
buttonZebra1.font = pygame.font.Font(None,110)
buttonZebra11.font = pygame.font.Font(None,110)
buttonZebra12.font = pygame.font.Font(None,110)
buttonZebra13.font = pygame.font.Font(None,110)
buttonZebra14.font = pygame.font.Font(None,110)
buttonZebra15.font = pygame.font.Font(None,110)
buttonZebra2.font = pygame.font.Font(None,110)
buttonZebra3.font = pygame.font.Font(None,110)
button = [buttonZebra,buttonZebra1,buttonZebra2,buttonZebra3]
button_zebra = [buttonZebra11,buttonZebra12,buttonZebra13,buttonZebra14,buttonZebra15]
allButtons = button
windowBgColor = WHITE
#6 Event loop
#while True:
while running:
#pygame.display.flip()
for event in pygame.event.get(): # event handling loop
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
if 'click' in button[0].handleEvent(event):
zebrasound.play()
if 'click' in button[1].handleEvent(event):
sound_please(right)
change_color_bg(button[1], GREEN)
change_color_fg(button_zebra[0], GREEN)
change_color_bg(button_zebra[0], BLACK)
sound_please(zlet)
change_color_fg(button_zebra[1], GREEN)
change_color_bg(button_zebra[1], BLACK)
sound_please(elet)
change_color_fg(button_zebra[2], GREEN)
change_color_bg(button_zebra[2], BLACK)
sound_please(blet)
change_color_fg(button_zebra[3], GREEN)
change_color_bg(button_zebra[3], BLACK)
sound_please(rlet)
change_color_fg(button_zebra[4], GREEN)
change_color_bg(button_zebra[4], BLACK)
sound_please(alet)
if 'click' in button[2].handleEvent(event):
sound_please(wrong)
change_color_bg(button[2], RED)
if 'click' in button[3].handleEvent(event):
sound_please(wrong)
change_color_bg(button[3], RED)
pygame.display.update()
screen.fill(windowBgColor)
buttonForward.draw(screen)
for a in allButtons:
a.draw(screen)
for b in button_zebra:
b.draw(screen)
pygame.display.update()
FPSCLOCK.tick(FPS)
def change_color_fg(button,color):
button.fgcolor = color
pygame.display.update()
def change_color_bg(button,color):
button.bgcolor = color
pygame.display.update()
def sound_please(sound):
sound.play()
while pygame.mixer.get_busy():
time.sleep(1)
pygame.display.update()
if __name__ == "__main__":
main()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit(0)
Button[1] is the big button and button_zebra 1,2,3,4 are small buttons inside bigbutton.
I have 4 buttons in a bigbutton, When I click the bigbutton and color of it changes.
Since input handling (the section of code that you posted) is usually just one part of the game loop, and you haven't posted the contents of change_color_fg, I can only make an educated guess here.
My guess is that change_color_fg does not actually update the display, and only changes the color that a button is supposed to draw with. It's my guess partly because it wouldn't make sense to re-draw the display within a function that's executing multiple times within a single frame.
For starters, don't delay in the middle of your update loop. If you need to do something when a single sound ends, implement a callback, or check playing sounds for completion once every frame until they finish.
For example, with each sound you play, you could either check its length with pygame.mixer.Sound.get_length, and then schedule a function to execute after that amount of time which changes the color of your next button and plays your next sound. Or, you could get the pygame.mixer.Channel object back from pygame.mixer.Sound.play, and then check pygame.mixer.Channel.get_busy until it returns False, which would indicate that your sound has stopped playing, at which point you can play the next one.

Categories

Resources