21 марта 2010

PyGame: Звуки музыки...

Здравствуйте. Попробуйте запустить игру. Например neverball. Запустили? Поиграйте немного. А теперь отключите звук и поиграйте еще немножко. Ну как, поиграли? Замечаете разницу? Будем считать что да. Звук и музыка важные составляющие атмосферы игры.

Начнем мы с простого, подготовим один короткий звук для топанья и какую-нибудь мелодию (ссылка в конце урока).

Теперь давайте поговорим о том как заставить pygame проигрывать звук. Все очень просто, для этого есть pygame.mixer.

Попробуем просто воспроизвести звуковой файл.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pygame

pygame.init()

# Загрузка музыки.
pygame.mixer.music.load('music.ogg')
# Проигрывание музыки.
pygame.mixer.music.play()

# get_busy вернет False когда музыка прекратит проигрываться.
while pygame.mixer.music.get_busy():
    pass

Это прекрасно подходит для воспроизведения музыки. А что делать если нам нужен звук шагов, выстрелов и всего остального что может издавать звук в игре? Для этого есть pygame.mixer.Sound и pygame.mixer.Channel.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pygame
from math import sqrt

if __name__ == '__main__':
    pygame.init()

    display = pygame.display.set_mode((640,480))

    clock = pygame.time.Clock()

    # Загрузка музыки и звука.
    music = pygame.mixer.Sound('music.ogg')
    sound = pygame.mixer.Sound('step.ogg')

    # Начинаем проигрывать музыку,
    # loops = -1 заставляет проигрывать звук циклично,
    # непереставая.
    music_channel = music.play(loops = -1)
    # Устанавливаем громкость.
    music_channel.set_volume(0.1)
    # Начинаем проигрывать звук.
    sound_channel = sound.play(loops = -1)
    # Здесь устанавливается громкость правого и левого канала.
    sound_channel.set_volume(1.0, 1.0)

    hero = pygame.sprite.Sprite()
    hero.image = pygame.Surface((16,16))
    hero.image.fill((0,0,0))
    hero.rect = hero.image.get_rect()
    hero.rect.move_ip(312,232)

    done = False
    dt = 0
    # Координаты центра, в нем звук будет наиболее громким.
    cx = 320.0
    cy = 240.0
    while not done:
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                done = True
                continue
            if e.type == pygame.KEYDOWN \
               and e.key == pygame.K_ESCAPE:
                done = True
                continue

        display.fill((255,255,255))
        display.blit(hero.image, hero.rect)
        pygame.display.flip()

        # Получаем координаты мыши.
        point = pygame.mouse.get_pos()
        # Определяем расстояния по x от центра.
        x = (pygame.mouse.get_pos()[0] - cx) / cx
        # Определяем дистанцию на которую от нас удален источник звука.
        y = sqrt((abs(point[0] - cx) ** 2 + abs(point[1] - cy) ** 2))
        # Высчитываем максимальную громкость.
        y = 1.0 - y / sqrt(cx**2 + cy**2)
        # Высчитываем громкость левого, правого уха.
        v = y - abs(x)
        if v < 0:
            v = 0
        # Устанавливаем громкость так что бы эмитировать
        # отдаленность источника.
        if x > 0:
            sound_channel.set_volume(v,y)
        elif x < 0:
            sound_channel.set_volume(y,v)
        elif x == 0:
            sound_channel.set_volume(y, y)

        dt = clock.tick(40)

Вот так можно без особых усилий добавить в нашу игру звук. Я не уверен что все здесь правильно, точнее я уверен что здесь что-то не так. Хотя это работает. Надеюсь это дало вам хоть какое-то представление о том, как работать со звуков в pygame.

Вот кстати звуки.