tldr: Nadawanie wiadomości z wewnątrz gry i odbieranie jej stamtąd działa pełną parą. Pozostało zaimplementować rozgrywkę z prawdziwego zdarzenia i podsumować serię w okrągłych dziesięciu postach.
Rozwiązanie problemu z głośnikami
Przekopałem całą dokumentację Beads, nie znalazłem niczego co wskazywałoby na problem albo chociaż pozwalało nadać wszystko ciągiem – znalazłem jednak możliwość zapisywania wygenerowanych częstotliwości jako plik .wav i… bingo.
Zapisuję każdą jedną z częstotliwości dotychczas już generowanych na dysku (każda po ~32.kB) , po czym łączę je w jeden duży (5.8 MB) plik i odtwarzam wewnątrz Mad Pirates. Takich mniejszych plików jest 188, wygenerowanie ich zajmuje około 6 sekund.
Wygenerowane pliki.
Odtworzenie całej wiadomości jako plik .wav nie stwarza najmniejszych problemów z głośnikami, więc największy problem transmisji jest już na dobre zamknięty.
Klasa FileMerger.java którą łączę powstałe pliki .wav.
Klasa FileRecorder.java która jest przerobionym tutorialem Beads ze strony:
https://github.com/orsjb/beads/blob/master/packages/Beads/beads_tutorial/Lesson09_RecordToSample.java
Emitowanie i nasłuchiwanie
Komputer musi w jakiś sposób wiedzieć, czy ta część wiadomości, którą do tej pory odebrał, nadaje się do parsowania. Rozwiązałem to, tworząc cyklicznie co sekundę nowy wątek próbujący sparsować obecny bufor z informacjami z głośników. Jeśli się nie powiedzie – trudno, exception, wątek ginie, tworzy się nowy i próbuje to samo. Jeśli się uda – transmisję uznajemy za udaną i podstawiamy wyniki ze sparsowanego obiektu do symulacji. Działa, ale niezbyt eleganckie. Do wymiany w przyszłości.
Jeśli chodzi o emitowanie wiadomości, to skorzystałem ze starej klasy StarterBroadcaster.java, która zamiast odtwarzać dźwięki, to zapisuje je, a po skończeniu tego procesu odczytuje główny plik ze zlepionymi dźwiękami – po wszystkim wątek się zamyka. StarterBroadcaster tworzony jest na żądanie, przyciskiem klawisza G.
Reorganizacja kodu
Do utrzymania porządku dopisałem kilka klas, m.in. FileLoader.java, z którego biorę referencje do tekstur które załadował, a także HUD.java, który trzyma wszystkie możliwe opcje wyświetlania interfejsu użytkownika, tj. tryb w którym wypisuje “Tura planowania”, tryb z wypisywaniem “Tura symulacji” i tak dalej. KeyboardInterpreter.java odpowiada za logikę przy wciskaniu klawiszy a InputModel.java został dodany dla łatwego transportu informacji pomiędzy klasami.
Nie do końca jestem zadowolony ze zmian (logika działania nadal nie jest do końca czytelna i można się pogubić w boolean-ach), ale na ten moment wystarczy.
Efekty
Oto zakończona sukcesem próba przesłania obecnej pozycji statku dźwiękiem (odbiorcą i nadawcą był ten sam komputer).
Co dalej
Aby uczynić owoce tej pracy użytecznymi, zamiast przesyłać pozycję XY statku będziemy przesyłać pozycję kliknięcia myszką gracza i do tego na start gry przyjmować w argumencie konsoli to, którym graczem gramy (wtedy obie strony wzajemnie znają początkową pozycję początkową siebie i przeciwnika) – tak właściwie, to już to zrobiłem, tym urywkiem kodu:
Aby przetestować to rozwiązanie prosto w IDE, wystarczy wyedytować konfigurację startową:
Jesteśmy na skraju celu, którym jest faktycznie móc się poruszać po planszy co turę, grając w dwie osoby, więc to już w następnym, podsumowującym poście.
Jak zawsze, kod dostępny jest na moim GitHubie:
https://github.com/dbeef/soundcoding