Vediamo adesso come utilizzare i files sonori. Dobbiamo per prima cosa riflettere sul fatto che il suono è usato nei videogiochi in due modi diversi:
Anche riguardo ai files sonori è necessario conoscere qualche nozione tecnica; vediamone le tipologie:
.wav | Sono files che contengono suoni registrati da un microfono e poi digitalizzati (cioè convertiti in una serie di bytes). Possono contenere quindi suoni realistici come voci, veri strumenti musicali, musica orchestrale, ma hanno il problema di occupare molta memoria perchè non sono compressi. In genere vanno bene per gli effetti (suoni brevi) ma non per la colonna sonora. |
.mp3 | E' il formato attualmente più usato per la musica perchè produce una buona qualità sonora con una notevole compressione dei files. Il formato .mp3 è però legato ad alcuni brevetti e così di solito per riprodurli da pygame è necessario installare un altro programma (codec). Dovreste fare perciò delle prove per vedere se il vostro computer li suona. |
.ogg | E' un formato meno diffuso dell'.mp3 ma molto simile e senza nessuna limitazione. Questi files sono supportati da pygame. |
.mid | Sono files completamente diversi. Un file .mid non contiene musica digitalizzata, ma una specie di "spartito" che viene suonato dal sintetizzatore MIDI del sistema operativo. In questo modo un file molto piccolo può contenere musiche anche lunghe, ma naturalmente non realistiche: l'effetto è simile a quello dei vecchi videogiochi. Vanno quindi benissimo per la colonna sonora (a patto di non avere troppe pretese) ma non per gli effetti. |
In pygame le funzioni che si occupano di gestire i suoni sono raggruppate nel sottomodulo mixer
.
Anche gli effetti sonori devono essere caricati in memoria a partire da un file. Le cose sono però un po' differenti rispetto alle
immagini, perchè per i suoni esiste in pygame un oggetto apposito chiamato Sound, definito nel sottomodulo
mixer
. Quindi per caricare un suono dovremo creare un oggetto Sound tramite il costruttore ed assegnarlo ad una variabile.
La sintassi, per fortuna, è simile a quella per caricare le immagini:
beep = pygame.mixer.Sound("nome_del_file")
assegnerà alla variabile beep
il suono caricato dal file. Una volta assegnato
il suono alla variabile, potremo riprodurlo con il metodo play()
(che quindi va chiamato così:
beep.play()
senza più indicare i nomi dei moduli).
Un oggetto Sound
può caricare i files .wav e .ogg. Anche per i files sonori sorge il problema di
indicare il percorso quando il file non è nella stessa cartella del programma: adotteremo la stessa tecnica che abbiamo visto
qui per i files grafici. Nella cartella Effects
trovate alcune sottocartelle con vari files di effetti sonori; se non l'avete già fatto vi invito nuovamente a leggere
l'approfondimento che vi spiega dove potete cercare questi files e contiene anche le
informazioni di Copyright, con il nome dell'autore e il link originale di ogni file.
Riprendiamo il programma due_quadrati.py (qui) che scriveva nella finestra di IDLE quando cliccavamo su un quadrato e modifichiamolo in modo che emetta dei suoni. Dobbiamo caricare i due files "boing.wav" e "squeak2.wav" della cartella Effects.
import pygame
from pygame.locals import *
from os.path import join
# inizializzazione
pygame.init()
screen = pygame.display.set_mode((800, 600))
# creiamo la Surface surf1, la coloriamo di rosso e la posizioniamo sullo schermo
surf1 = pygame.Surface((200, 200))
surf1.fill("red")
rect1 = surf1.get_rect()
rect1.topleft = (50, 50)
screen.blit(surf1, rect1)
# stessa cosa con surf2 (blu)
surf2 = pygame.Surface((100, 100))
surf2.fill("blue")
rect2 = surf2.get_rect()
rect2.topleft = rect1.topright
screen.blit(surf2, rect2)
# ora creiamo i due suoni
sound1 = pygame.mixer.Sound(join("Effects", "boing.wav"))
sound2 = pygame.mixer.Sound(join("Effects", "squeak2.wav"))
# aggiorniamo lo schermo
pygame.display.flip()
# ciclo principale
done = False
while not done:
for ev in pygame.event.get():
# se l'evento è la fine del programma esce
if ev.type == QUIT:
done = True
# se l'evento e' un click ...
elif ev.type == MOUSEBUTTONDOWN:
click = ev.pos
if rect1.collidepoint(click):
sound1.play()
elif rect2.collidepoint(click):
sound2.play()
# fine del ciclo e termine del programma
pygame.quit()
Come vedete, rispetto al vecchio programma, abbiamo solo aggiunto le righe #24 e
#25, in cui carichiamo i files e li assegnamo alle rispettive variabili, ed abbiamo sostituito le vecchie
print()
con le istruzioni play()
in #41 e #43.
Qualche volta possiamo avere bisogno di effetti che si ripetano più volte (ad esempio una sirena della polizia); a questo scopo
il metodo play()
ha un parametro opzionale che indica quante volte il suono deve essere ripetuto (dopo la prima volta).
Quindi se snd
è una variabile di tipo Sound, possiamo scrivere snd.play(5)
. Questo ripeterà il
suono 6 volte (la prima più 5 ripetizioni). Invece scrivendo snd.play(-1)
ripeteremo il suono
all'infinito, fino a quando il programma non termina.
E se volessimo fermarlo? Niente paura, l'oggetto Sound ha anche altri metodi utili, vediamone quelli più utilizzati:
Metodo | Esempio | Significato |
---|---|---|
stop() |
snd.stop() |
Ferma immediatamente il suono |
fadeout() |
snd.fadeout(5000) |
Esegue una dissolvenza diminuendo gradatamente il volume fino a 0. Il parametro indica il numero di millisecondi (quindi 5000 = 5 secondi) |
set_volume() |
snd.set_volume(0.6) |
Aggiusta il volume; il parametro è un numero decimale da 0 (silenzio) a 1 (massimo). Quando la usate il suono avrà sempre lo stesso volume finchè non lo cambate |
Oltre ai file caricati in memoria, pygame può anche suonare files sonori in streaming (cioè caricando di volta in volta solo la parte che sta suonando in quel momento). Come saprete questa tecnica è nata per vedere filmati e musica in rete, in modo da non dover ricevere tutto il file prima di cominciare a suonare. Notate che, mentre per gli effetti sonori abbiamo la possibilità di riprodurne molti contemporaneamente (fino a 8), per lo streaming possiamo solo suonare un file per volta (facendone partire un altro si ferma il precedente).
Per lo streaming pygame ha delle funzioni speciali che si trovano nel sottomodulo music
di mixer
(sì,
esistono i sottomoduli dei sottomoduli!). Dal nostro punto di vista tutto questo è una scocciatura: per gli effetti sonori si usano
gli oggetti (e quindi per suonare dobbiamo usare la sintassi variabile.metodo()
) mentre per la colonna sonora avremo
delle normali funzioni (con la sintassi modulo.funzione(argomenti)
); ciò si traduce in istruzioni "quasi uguali ma diverse"
che possono facilmente portare a confondersi. Ecco anche qui una tabella con le principali funzioni.
Funzione | Significato |
---|---|
pygame.mixer.music.load("nome_del_file") |
Determina il file sonoro da suonare (possiamo caricare .wav, .ogg, .mid, mentre la documentazione avverte che il supporto per gli .mp3 è limitato e potrebbero mandare in crash il programma). |
pygame.mixer.music.play() |
Inizia a suonare il file. Anche qui possimo aggiungere un parametro con il numero delle ripetizioni (non compresa la prima); se il parametro è -1 la musica si ripeterà all'infinito. |
pygame.mixer.music.stop() |
Ferma la musica. |
pygame.mixer.music.fadeout(5000) |
Ferma la musica diminuendo gradatamente il volume. Il parametro n indica il numero di millisecondi (quindi 5000 = 5 secondi) |
pygame.mixer.music.set_volume(0.6) |
Aggiusta il volume; il parametro è un numero decimale da 0 (silenzio) a 1 (massimo). Quando la usate il suono avrà sempre lo stesso volume finchè non lo cambiate |
Nella cartella Music trovate alcune sottocartelle con file .ogg e .mid; potete provare anche a copiare qui qualcuno dei vostri .mp3 preferiti, per vedere se pygame li carica e suona (cosa che, come ho detto, non è garantita nell'installazione standard).
play()
e
verificate che effettivamente il file suona una sola volta e si ferma.Fine della lezione