Poniat wzbogacił się o oprawę dźwiękową.



Dopisałem dziś do kodu coś, co jest obowiązkowym elementem gry i co w dużym stopniu decyduje o grywalności - dźwięki. Muzyka, dźwięki tła oraz wszystkie zdarzenia obsługiwane są za pomocą jednej prostej klasy.

 1 class Sounds(object):
2
3 def __init__(self):
4 mixer.set_num_channels(8)
5 self.a = mixer.Channel(1)
6 self.b = mixer.Channel(2)
7 self.c = mixer.Channel(3)
8 self.d = mixer.Channel(4)
9 self.f = mixer.Channel(5)
10 self.ambient = mixer.Sound('data/tlo.ogg')
11 self.music = mixer.Sound('data/cory_gray_someone_kill_jt.ogg')
12 self.passing_sound = mixer.Sound('data/mijanie.ogg')
13 self.crash_sound = mixer.Sound('data/uderzenie.ogg')
14 self.car_honk = mixer.Sound('data/klakson2.ogg')
15 self.tram_bell = mixer.Sound('data/dzwonek_tramwajowy.ogg')
16
17 def background_sounds(self):
18 if not self.a.get_busy():
19 self.a.set_volume(0.5)
20 self.a.play(self.ambient)
21
22 if not self.c.get_busy():
23 self.c.set_volume(0.7)
24 self.c.play(self.music)
25
26 def passing(self, dist):
27 if not self.b.get_busy():
28 self.b.play(self.passing_sound)
29 self.b.set_volume(1.0/(dist/10))
30 else:
31 self.b.set_volume(1.0/(dist/10))
32
33
34 (...)

W inicie powołujemy do życia kanały dźwiękowe, które ja nazwałem sobie kolejnymi literami alfabetu. Dzięki kanałom będziemy w stanie odtwarzać kilka dźwięków równocześnie, np. muzykę i odgłosy klaksonów. Po kanałach ładujemy muzykę z pliczków ogg do pamięci.

Funkcja background_sounds() służy do odtwarzania długo trwających kawałków. Wywołuję ją za każdym obrotem głównej pętli gry i sprawdzam czy muzyka nadal gra za pomocą .get_busy().

Najciekawszy problem pojawił się przy symulowaniu odgłosu samochodu, który zbliża się i oddala od gracza. Chciałem, żeby poziom głośności dźwięku zależał w sposób proporcjonalny od odległości pojazdu do gracza. Do obliczania bezwzględnej odległości między nimi posłużyłem się czymś takim:

1 dist = sqrt((self.b.px - car.x)**2 + (self.b.py - car.y)**2)


W przystępniejszej formie można to opisać tak:

Odejmuję od siebie położenia roweru i samochodu na osi x a następnie podnoszę do kwadratu, żeby pozbyć się minusów. Dodaję to do wyniku podobnej operacji na położeniu y. Ponieważ wyniki zostały podniesione do kwadratu, redukuję je za pomocą pierwiastka kwadratowego (math.sqrt).

Funkcja passing(dist) przyjmuje za argument wyliczoną odległość i ustawia głośność między 0.1 a 1.0, bo takiego przedziału oczekuje pygame.mixer.set_volume().

Prawdę mówiąc jestem totalnym beztalenciem matematycznym i sam pewnie bym nigdy nie wpadł na pomysł jak coś takiego liczyć. Do znalezienia rozwiązania zainspirowało mnie to zadanko: http://matematyka.pisz.pl/strona/1248.html

Zapraszam do testowania.

Źródła gry można jak zwykle znaleźć na sorsfordżu:

Ściągnij źródło Poniata