Ну вообще-то работа со звуком — это слишком громкое название для этой статьи. На самом деле, во время написания этой вот игры у меня возникла необходимость проигрывать фоновые мелодии и звуки нажатия на экран. Ну и полез я в справку по Android SDK. Ребята из гугла предлагают для таких целей использовать класс SoundPool. Однако у меня с ним почему-то не заладилось. То ли я справку читал не внимательно, то ли еще что, не знаю… И я решил накидать пару своих собственных небольших классов для решения этой не столь уж эпохальной проблемы. Вот собственно об этих классах мы сейчас и поговорим.
Начнем с того, что опишем небольшой класс mSoundTrack, который будет отвечать за проигрывание одного звука. На самом деле — это просто обертка для класса MediaPlayer. И вот его код:
package ru.davidmd.myengine; import android.content.Context; import android.media.MediaPlayer; public class mSoundTrack { private MediaPlayer track; private boolean playable; private String name; /** * Конструктор * * @param cont * - контекст * @param resid * - идентификатор ресурса * @param name * - имя трека * @param looped * - зацикленность проигрывания */ public mSoundTrack(Context cont, int resid, String name, boolean looped) { this.playable = true; this.track = MediaPlayer.create(cont, resid); this.track.setLooping(looped); this.name = name; } /** * запускает трек если в настройках mSettings есть звук */ public void start() { if (mSettings.isSound()) { if (!track.isPlaying()) track.start(); } else this.stop(); } /** * перезапускает звук независимо от того играется он в данный момент или нет */ public void forceStart() { if (mSettings.isSound()) { if (track.isPlaying()) { track.pause(); track.seekTo(0); track.start(); } else { track.start(); } } } /** * приостанавливает проигрывание звука! ВНИМАНИЕ!!! Не высвобождает память, * не отсоединяется от потока... просто приостанавливает! */ public void stop() { if (track.isPlaying()) track.pause(); } /** * перематывает трек на начало */ public void rewind() { this.stop(); track.seekTo(0); this.start(); } /** * @return возвращает параметр playable */ public boolean isPlayable() { return playable; } /** * @param playable * - истина, если трек должен играться при проигрывании ложь в * противном случае */ public void setPlayable(boolean playable) { this.playable = playable; } public String getName() { return name; } }
Теперь посмотрим попристальнее, что тут к чему. Имеются целых три переменные, это track — экземпляр класса MediaPlayer, name — строка в которой мы храним имя трека и логическая переменная playable — которая отвечает за то можно ли воспроизводить данный конкретный звук или нет (для чего нам последняя будет понятно чуть позже).
Соответственно имеется конструктор с целой кучей параметров: Context cont, int resid, String name, boolean looped. По порядку: Context cont — контекст из которого мы получаем доступ к ресурсам программы, int resid — идентификатор ресурса с изображением (надеюсь этой теме я тоже посвящу как-нить отдельную статью) — две эти переменные отвечают за загрузку данных из ресурсов мы их уже использовали в классе mSimpleSprite. Дальше все гораздо проще — сначала строка с именем звука, а затем, булева переменная looped — которая отвечает за то, будет ли зациклено воспроизведение нашего трека. Ну а сам конструктор думаю в комментариях не нуждается.
Идем дальше какие методы у нас здесь имеются? Давайте по порядку: start() — метод который запускает воспроизведение звука. Если звук был приостановлен, тогда воспроизведение продолжается с места где звук остановили. Метод forceStart() отличается от предыдущего тем, что если звук в данный момент воспроизводится, то происходит перемотка на самое начало трека и звук воспроизводится с самого начала. Оба эти метода проверяют перед запуском включен ли звук в классе глобальных настроек приложения mSettings.
Следующий метод stop() — не знаю почему я назвал его «стоп», ведь на самом деле он просто приостанавливает воспроизведение звука. На самом деле думаю стоило так и назвать его pause 🙂 Но видно писал все это я глубокой ночью, так что претензии не принимаются :). Метод rewind() тоже не содержит каких-то откровений и просто перематывает звук на начало. Два метода isPlayable() и setPlayable(boolean playable) соответственно проверяют и устанавливают для трека статус playable. Ну а метод getName() — просто возвращает имя трека. Вот и все что касается нашего трека. Итак у нашего проигрывателя есть треки, и мы легко можем их проиграть, приостановить или перемотать на начало. Казалось бы, для наших целей большего и не надо! Но нет, на самом деле в игре (а вы ведь не забыли что это все еще часть нашего игрового движка?) гораздо удобнее обладать каким-то общим средством для запуска и проигрывания звуков.
Таким средством станет наш следующий класс: mPlayer. Начну по привычке с его кода:
package ru.davidmd.myengine; import java.util.ArrayList; import android.content.Context; public class mPlayer { private static ArrayList<mSoundTrack> tracks = new ArrayList<mSoundTrack>(); /** * Добавляет трек из ресурсов * * @param c * - контекст * @param resid * - идентификатор ресурса * @param name * - имя для нового трека * @param looped * - зацикленность трека */ public static void addTrack(Context c, int resid, String name, boolean looped) { mSoundTrack track = new mSoundTrack(c, resid, name, looped); tracks.add(track); } /** * Возвращает трек из списка по его имени * * @param name * - имя трека * @return возвращает трек с именем name */ public static mSoundTrack getTrackByName(String name) { mSoundTrack t = null; for (mSoundTrack a : tracks) { if (a.getName() == name) { t = a; break; } } return t; } /** * Метод запускает все треки, свойство playable которых имеет значение * истина */ public static void playAll() { for (mSoundTrack a : tracks) { if (a.isPlayable()) { a.start(); } } } /** * Метод останавливает все треки * */ public static void stopAll() { for (mSoundTrack a : tracks) { a.stop(); } } }
Тоже на самом деле ничего сложного! В классе имеется статический список треков и метод для добавления трека в список — addTrack(). Помимо этого присутствует метод возвращающий трек по его имени — getTrackByName(String name), если такого имени не оказалось то возвращается null. Ну и собственно то ради чего все это затевалось: метод запуска всех треков (при запуске проверяется имеет ли трек статус проигрываемого) и метод остановки всех треков. Для написания не сложной игры этого простенького менеджера звуков оказалось вполне достаточно!
На сегодня все! жду комментов или примеров работы с SoundPool (Наверняка там все несколько легче).
Читать дальше тут.
«запускает трек если в настройках mSettings есть звук»
А где определение mSettings?
Честно говоря не помню где именно но где-то на страницах посвященных движку я об этом писал 🙂 В любом случае вы можете скачать полный код движка и посмотреть что там за такие mSettings 🙂
Здравствуйте. Хотел добавить в Пятнашки музыку. для этого добавил в папку «w» мелодию с именем «track». В классе MainScreen добавил к подключаемым классам mPlayer и в методе onStart() добавил mPlayer.getTrackByName(«track»).setPlayable(true);
mPlayer.getTrackByName(«track»).forceStart();
mPlayer.playAll();
отладчик ошибок никаких не находит, но в эмуляторе игра не работает. Не подскажите в чем причина?
Разобрался что к чему =)
Где можно посмотреть реализацию метода isSound()?
Никогда не делайте так))