You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在循环中按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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 19:54:40