Kivy 和游戏中的声音:游戏更新循环在继续之前等待声音完成 [FPS issues using SoundLoader in Kivy]

Kivy and in-game sounds: Game update loop waits for sound to finish before continuing [FPS issues using SoundLoader in Kivy]

我正在通过使用 Kivy 制作游戏来学习编程 Python,但是我无法为不同的事件实现声音(例如 shield_on.play() 当盾牌被选中时向上。)因为游戏更新循环似乎会暂停一会儿,直到声音播放完毕。我在这里做了一个相关代码的简短版本...

shield_on = soundLoader('shield_on.wav')
class game(Widget):
#...loads of other stuff...

    def update_loop(foo):
        self.player_one.update()
        self.player_two.update()
        self.player_item_collision_detector()
        if "game_file_says_player_one's_shields_are on":
            self.player_one.drawShield()
            shield_on.play()

目前,我只是在全局加载我的声音。我知道这很糟糕,但它们也是我唯一的全局变量。然后是一个包含游戏本身的小部件,它有很多东西和一个更新循环......它更新玩家位置,检查与物品的碰撞 - 碰撞时,物品,这里是盾牌,被注册为 "on" 在游戏文件中。然后更新循环检查该游戏文件的 "shields" 状态,查看它们是否打开并且应该播放声音。

声音播放得很好,但是循环似乎停止了,直到它播放完声音。基本上,玩家会停下来一微秒。如何让更新循环不等待声音结束...?

The sound plays just fine, however the loop appears to halt until its finished playing the sound.

Multithreading 可能是您的解决方案。

import threading
...
class foo(something):
    ...
    def update_loop(self,foo):
        ...
        if "game_file_says_player_one's_shields_are on":
            #starting new thread, which will run parallely with the main loop
            threading.Thread(target=self.first_thread).start()

    def first_thread(self):
        self.player_one.drawShield()
        shield_on.play()

PyGame 的说明和解决方法:

这里解释问题的原因:github.com/kivy/kivy/issues/2728 本质上,SoundLoader.load() 函数应该 return class 最适合播放您传递给它的声音文件。它最终并没有完全做到这一点,据我所知,错误不在于 Kivy,而在于 GStreamer。这会导致应用程序的帧率暂时显着下降 - 无论您在何处调用 .play() 方法。

github-线程中提供了两种可能的解决方案; 1) 要么确保合适的 class 直接被 returned - 使用 SoundSDL2 2) 使用 PyGame 代替

我实现了后者,效果很好。

# Initialize files and PyGame mixer:
import pygame
pygame.init()
pygame.mixer.pre_init(44100, 16, 2, 4096) # Frequency, size, channels and buffersize    
shield_on = pygame.mixer.Sound("shield_on.wav")

class game(Widget):
    ...
    def update_loop(self):
        ...
        if "game_file_says_shield_is_on":
            shield_on.play()

希望对大家有所帮助!

我想说上面的答案也很有用,因为它使我能够确定真正的问题。我会给它投票,但我还没有这里的声誉。