Pygame- “Pygbuttons”- 如何同时更改按钮颜色和播放声音

-1 投票
1 回答
852 浏览
提问于 2025-04-18 10:05

我想让每个按钮的颜色一个接一个地改变,每次颜色变化时都想播放一个声音。

声音播放得很好,但按钮的颜色只在所有声音播放完后才会改变。

我该怎么做才能让每个按钮的颜色变化和声音播放同时进行呢?

这是我的代码:

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] 是大按钮,而 button_zebra 1,2,3,4 是大按钮里面的小按钮。

我在大按钮里有4个小按钮,当我点击大按钮时,它的颜色会改变。

1 个回答

-1

你发的代码主要是处理输入的部分,通常这只是游戏循环中的一部分。而你没有提供change_color_fg的具体内容,所以我只能猜测一下。

我猜change_color_fg并没有真正更新显示的内容,它只是改变了按钮应该用来绘制的颜色。之所以这么猜,是因为在一个函数里重复绘制显示内容是没有意义的,尤其是在同一帧内执行多次的时候。

首先,在更新循环中不要进行延迟。如果你需要在某个声音结束时做点什么,可以使用回调函数,或者每帧检查正在播放的声音,直到它们结束。

举个例子,当你播放每个声音时,可以用pygame.mixer.Sound.get_length来检查声音的长度,然后安排一个函数在这段时间后执行,这个函数可以改变下一个按钮的颜色并播放下一个声音。或者,你可以从 pygame.mixer.Sound.play中获取pygame.mixer.Channel对象,然后使用pygame.mixer.Channel.get_busy来检查,直到它返回False,这表示声音已经停止播放,这时你就可以播放下一个声音了。

撰写回答