python - 如何使用 Pygame 执行基于时间的音频?

标签 python audio pygame python-3.3

这是我在 StackOverflow 上的第一个问题,所以这里是:

编辑:我已经编辑了几次,只是修复了输入错误并更新了代码。即使对代码添加了各种更改,问题仍然完全相同。
另外, pygame.mixer.music.fadeout() 不是我想要的。当我想在暂停游戏或进入谈话场景时将音乐音量降低到大约 50% 时,此代码也将适用。

使用 Pygame,我试图根据过去的时间来执行音乐音量操作。我已经创建了一些不错的代码,但它并没有按照我直觉的方式执行。另外,我应该注意,我使用的是从 PySDL2 中提取的基于组件的 EBS 系统。这是 EBS 模块的链接:https://bitbucket.org/marcusva/py-sdl2/src/02a4bc4f79d9440fe98e372e0ffaadacaefaa5c6/sdl2/ext/ebs.py?at=default

这是我的初始代码块:

import pygame
from pygame.locals import *

# Setup import paths for module.
pkg_dir = os.path.split(os.path.abspath(__file__))[0]
parent_dir, pkg_name = os.path.split(pkg_dir)
sys.path.insert(0, parent_dir)
sys.path.insert(0, os.path.join(parent_dir, "Game"))

import Game
from Porting.sdl2.ext import ebs

pygame.display.quit()
print("Counting down...")
for n in range(5):
    print(str(n + 1))
    pygame.time.delay(1000)
appworld = ebs.World()
audio_system = Game.audio.AudioSystem(44100, -16, 2, 4096)
appworld.add_system(audio_system)
test1 = Game.sprites.AudioSprite(appworld)
test2 = Game.sprites.AudioSprite(appworld)
test1.audio = Game.audio.Audio(database["BGMusic0"], True)
test2.audio = Game.audio.Audio(database["BGMusic1"], True)
game_clock = pygame.time.Clock()
volume_change_clock = pygame.time.Clock()
loop = True
time_passed = 0
while loop:
    game_clock.tick(60)
    appworld.process()
    time_passed += volume_change_clock.tick(60)
    if time_passed > (10 * 1000):
        print(time_passed)
        if not audio_system.music_volume_changed:
            audio_system.set_music_volume(0, True)

我的下一个代码块:
import pygame
from Porting.sdl2.ext import ebs
class AudioSystem(ebs.System):
    def __init__(self, frequency, bit_size, channels, buffer):
        super(AudioSystem, self).__init__()
        self.componenttypes = Audio,
        pygame.mixer.init(frequency, bit_size, channels, buffer)
        pygame.mixer.set_num_channels(200)
        self.frequency = frequency
        self.bit_size = bit_size
        self.channels = channels
        self.buffer = buffer
        self.music_volume_change_clock = None
        self.music_volume_changed = False
        self.music_volume_current = 0
        self.music_volume_new = 0
        self.music_fade = False
        self.music_change_speed = 0
        self.time_passed_total = 0
        self.time_passed_remainder = 0

    def process(self, world, componentsets):
        for audio in componentsets:
            if audio.is_music:
                music = pygame.mixer.music
                if not pygame.mixer.music.get_busy():
                    music.load(audio.file)
                    music.play()
                if self.music_volume_changed:
                    self.music_volume_current = music.get_volume() * 100
                    if self.music_volume_current != self.music_volume_new and self.music_fade:
                        time_passed = self.music_volume_change_clock.tick(60)
                        self.time_passed_total += time_passed
                        self.time_passed_total += self.time_passed_remainder
                        self.time_passed_remainder = 0
                        if self.time_passed_total > self.music_change_speed:
                            self.time_passed_remainder = self.time_passed_total % self.music_change_speed
                            volume_change_amount = int(self.time_passed_total / self.music_change_speed)
                            self.time_passed_total = 0
                            if self.music_volume_current > self.music_volume_new:
                                self.music_volume_current -= volume_change_amount
                                music.set_volume(self.music_volume_current / 100)
                            elif self.music_current_volume < self.music_volume_new:
                                self.music_volume_current += volume_change_amount
                                music.set_volume(self.music_volume_current / 100)
                    elif self.music_volume_current != self.music_volume_new:
                        music.set_volume(self.music_volume_current / 100)
                    else:
                        self.music_volume_changed = False
                        self.music_fade = False
            else:
                if not audio.channel:
                    audio.channel = pygame.mixer.find_channel()
                    audio.channel.play()

    def set_music_volume(self, percent, fade = False, change_speed = 50):
        self.music_volume_changed = True
        self.music_volume_new = percent
        self.music_fade = fade
        self.music_change_speed = change_speed
        self.music_volume_change_clock = pygame.time.Clock()

class Audio(object):
    def __init__(self, file, is_music = False):
        self.is_music = is_music
        if self.is_music:
            self.file = file
        else:
            self.channel = None
            self.file = pygame.mixer.Sound(file)

我的测试表明,在我的 Game.audio 模块中以各种方式操作 Clock.tick() 的参数会影响音频播放从 100 下降到 0 的速度。将其留空会导致它几乎立即停止。在 60 岁时,它在大约 2 秒内降至 0,这让我感到困惑。在 30 时,在 1 秒内。在 5 时,它缓慢下降,音量似乎永远不会达到 0。我想完全取消我的音频音量操作与我的游戏帧速率的同步,但我不确定我将如何实现这一点。如果可能,我想避免线程和多处理。

提前致谢! :)

最佳答案

Clock.tick() 的参数用于调用 SDL sleep 函数来限制循环每秒运行的次数。

使用 Clock.tick(5) 调用它会将其限制为每秒五个循环。

我也从未在同一代码中使用过两个时钟,尤其是在多个滴答声中(所有这些时钟都会单独计算它们的 sleep 时间)。取而代之的是,考虑使用 tick 的返回值(自上次调用以来的毫秒时间),并使用它来跟踪整个应用程序的时间。

例子:

    timer = 0
    Do things
    timer += main_clock.tick(FPS)

关于python - 如何使用 Pygame 执行基于时间的音频?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24978856/

相关文章:

python - Pygame 窗口在 Mac 上不接收键盘事件

python - 在 Pygame 中比较图像(不是逐像素比较)

python - Python如何连续填充子进程的多个线程?

python - 我们可以使用django中/admin的登录页面供自己使用吗?

audio - 网站还可以自定义Flash mp3播放器吗?

iphone - iPhone 上音效的最佳格式是什么

python - 如何从阵列中产生声音信号?

python - 如何在 Pygame 中显示 Sprite ?

python - 在python中查找列表的所有子列表

python - Tesseract OCR 产生空结果