Класс Sound и модуль pygame.mixer.music

В Pygame для работы с аудио предназначены модули pygame.mixer и pygame.mixer.music. Модули похожи, однако pygame.mixer в первую очередь адаптирован для добавления и настройки звуковых эффектов в игре. В то время как pygame.mixer.music – для добавления фоновой музыки.

Функция pygame.mixer.music.load() загружает потоковое аудио, т. е. не грузит файл целиком, а делает это отдельными порциями. В результате можно проигрывать только один файл за раз. Однако можно ставить файлы в очередь функцией queue(). Поддерживает в том числе формат mp3 (но не в Ubuntu).

С другой стороны, в pygame.mixer ключевым является класс Sound. Он позволяет загружать, проигрывать и выполнять ряд других действий с файлами форматов wav или ogg. При создании экземпляра Sound в конструктор передается имя файла.

В примере ниже подгружается фоновая музыка: pygame.mixer.music.load(). Функция не возвращает никакого "музыкального" объекта, поэтому результат ее вызова не присваивается переменной.

С помощью функции music.play() файл начинает проигрываться. Если требуется зациклить композицию, то в play() передается число -1. Положительный аргумент указывает на количество повторов + одно дополнительное. То есть, если надо проиграть композицию 2 раза, то в функцию передается число 1.

В программе при нажатии на клавишу 1 клавиатуры музыка ставится на паузу: music.pause(). Клавиша 2 уменьшает громкость в два раза: music.set_volum(0.5). Нажатие 3 возвращает громкость на прежний уровень. Функция unpause() вызывается на случай, если до этого музыка была выключена (клавишей 1).

В примере создаются два объекта типа Sound. У них есть свой метод play(). В данном случае файлы проигрываются при клике левой и правой кнопками мыши. Объекты Sound могут проигрываться одновременно, так как обычно принадлежат разным каналам. Если требуется более тонкое управление звуками, дополнительно используют класс Channel.

Программа ниже в процессе выполнения интерпретатором python3.6 может выбросить ошибку, в 3.8 – все нормально. На официальном сайте pygame.org рекомендуется использовать Pygame с версией Питона от 3.7.7.

import pygame as pg
import sys
pg.init()
sc = pg.display.set_mode((400, 300))
 
pg.mixer.music.load('Beethoven.ogg')
pg.mixer.music.play()
 
sound1 = pg.mixer.Sound('boom.wav')
sound2 = pg.mixer.Sound('one.ogg')
 
while 1:
    for i in pg.event.get():
        if i.type == pg.QUIT:
            sys.exit()
 
        elif i.type == pg.KEYUP:
            if i.key == pg.K_1:
                pg.mixer.music.pause()
                # pygame.mixer.music.stop()
            elif i.key == pg.K_2:
                pg.mixer.music.unpause()
                # pygame.mixer.music.play()
                pg.mixer.music.set_volume(0.5)
            elif i.key == pg.K_3:
                pg.mixer.music.unpause()
                # pygame.mixer.music.play()
                pg.mixer.music.set_volume(1)
 
        elif i.type == pg.MOUSEBUTTONUP:
            if i.button == 1:
                sound1.play()
            elif i.button == 3:
                sound2.play()
 
    pg.time.delay(20)
 

Если закомментировать вызовы функций pause() и unpause() и раскомментировать stop() и play(), то результат будет схож. Разница в том, что при использовании комбинации stop-play файл начнет проигрываться сначала, а при pause-unpause продолжится с места останова.

Если у вас нет файлов wav или ogg для тестов, можете найти немного в каталоге data модуля pygame.examples. Модуль находится в папке библиотеки pygame, адрес которой можно посмотреть так:

>>> import pygame
>>> pygame.__file__
'/home/.../pygame/__init__.py'

Практическая работа

Добавьте фоновую музыку и звук столкновения в игру из практической работы предыдущего урока.

Окно игры должно закрываться только после того, как звук столкновения полностью проиграется. В зависимости от решения вам может понадобиться метод get_length() объекта типа Sound. Метод возвращает продолжительность звука, выраженную в секундах (тип float).

Курс с примерами решений практических работ:
android-приложение, pdf-версия

Pygame. Введение в разработку игр на Python