首页 > 解决方案 > Pygame - 我可以让音乐有一个介绍,然后是一个循环点吗?

问题描述

我目前正在 Pygame 中开发一款游戏,我一直在尝试想办法让音乐曲目在不是曲目开头的地方循环播放。所以本质上,它播放一个介绍,然后移动到另一个重复的部分,而不重新访问那个介绍。

我已经想到了几种几乎可行的方法,但是它们存在问题。

第一个是有两个单独的音频文件用于介绍和循环部分,然后使用pygame.music.set_endevent(),并在第一个音频文件完成后加载第二个音频文件。这留下了一个相当明显的差距,但点击。

第二个是也使用两个音频文件,但在加载第一个时在第二个中排队。问题在于,您似乎无法将新排队曲目的播放模式从 0(播放一次)更改为 -1(循环)...

我觉得必须有一种方法可以做到这一点,我非常感谢任何帮助。

标签: pythonloopsaudiopygamemixer

解决方案


在下面的示例中,PyGame 的声音通道用于多个轨道。这里创建了一个事件,以便在 1500 毫秒后播放第二个声音(与循环轨道同时)。

对于您建议的用例,代码可以在开始时播放介绍音乐,但也可以在将来为/intro-length/毫秒设置一个事件计时器。当接收到该计时器事件时,您的音乐的循环部分可以连续播放,因为前奏应该刚刚停止。使用多个通道,这两个声音是否重叠几毫秒(静音/淡出)无关紧要,只要用户当然没有感知到它!在完全不同的系统上获得 100% 正确的时间可能会很棘手,但它应该让你接近。

请注意,在示例中,声音已经初始化为 PyGameSound对象,我希望这会减少启动延迟。

import pygame

# Window size
WINDOW_WIDTH    = 400
WINDOW_HEIGHT   = 400

DARK_BLUE = (   3,   5,  54)

### initialisation
pygame.init()
pygame.mixer.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ) )
pygame.display.set_caption("Multi Sound with Timer")

### sound
# create separate Channel objects for simultaneous playback
channel1 = pygame.mixer.Channel(0) # argument must be int
channel2 = pygame.mixer.Channel(1)

# Rain sound from: https://www.freesoundslibrary.com/sound-of-rain-falling-mp3/ (CC BY 4.0)
rain_sound = pygame.mixer.Sound( 'rain-falling.ogg' )
channel1.play( rain_sound, -1 )   # loop the rain sound forever

# Car Horn sound from: https://www.freesoundslibrary.com/car-horn-sound-effect/ (CC BY 4.0)
horn_sound = pygame.mixer.Sound( 'car-horn.ogg' )

# Create a timer, which will (after the delay-time) post an event to the main loop
pygame.time.set_timer( pygame.USEREVENT, 1500 )   # play the horn in 1500 milliseconds



### Main Loop
clock = pygame.time.Clock()
done = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.USEREVENT ):
            # Timer expired, play the sound
            channel2.play( horn_sound )

    # Movement keys
    #keys = pygame.key.get_pressed()
    #if ( keys[pygame.K_UP] ):
    #    print("up")

    # Update the window, but not more than 60fps
    window.fill( DARK_BLUE )
    pygame.display.flip()

    # Clamp FPS
    clock.tick_busy_loop(60)

pygame.quit()

推荐阅读