如何在循环中按1秒间隔播放声音且不阻塞其他代码执行?
解决Pygame循环内按键播放间隔声音且不阻塞代码执行的问题
问题根源分析
你之前的线程代码错误在于直接调用了函数walk_sound(),而不是将函数对象传给线程的target参数。这会导致主程序在创建线程前就先执行了walk_sound()里的sleep(1),从而阻塞了后续的移动代码。另外,未添加时间间隔控制,持续按键时会频繁触发播放,导致声音间隔过短。
正确实现方案
通过时间标记控制播放间隔+正确创建线程来实现:既保证1秒间隔播放声音,又不阻塞主循环内的移动逻辑。
完整代码示例
import pygame as p import math as m import threading import time # 初始化pygame mixer p.mixer.init() walkSound = p.mixer.Sound('walk.mp3') # 记录上次播放声音的时间,初始为0 last_play_time = 0 def walk_sound(): # 播放声音(Pygame的Sound.play()本身是非阻塞的) walkSound.play() # 主循环 while True: # 处理pygame事件(必须保留,否则窗口会无响应) for event in p.event.get(): if event.type == p.QUIT: p.quit() exit() keysPressed = p.key.get_pressed() current_time = time.time() if keysPressed[p.K_UP]: # 检查距离上次播放是否已过1秒 if current_time - last_play_time >= 1: # 正确创建线程:传递函数对象,而非直接调用函数 thread = threading.Thread(target=walk_sound) thread.start() # 更新上次播放时间 last_play_time = current_time # 移动逻辑不受声音播放影响,立即执行 tX += 2 * m.sin(startRot) tY += 2 * m.cos(startRot) # 其他主循环逻辑... p.display.update()
关键要点说明
- 线程创建正确姿势:
threading.Thread(target=walk_sound)中target接收的是函数对象,不带括号,这样线程启动后才会执行函数,不会阻塞主程序。 - 时间间隔控制:通过
last_play_time记录上次播放的时间戳,每次检测到按键时判断是否满足1秒间隔,避免持续按键时频繁触发播放。 - Pygame声音特性:
walkSound.play()本身是异步执行的,播放操作不会阻塞主线程,线程的作用只是确保播放操作在后台执行(其实这里即使不用线程,直接在满足间隔时调用walkSound.play()也不会阻塞,但使用线程更符合你原本的思路,且扩展性更好)。
内容的提问来源于stack exchange,提问作者1m2n3
相关产品推荐
相关产品推荐

