Создание игр для мобильных телефонов - Майкл Моррисон
Шрифт:
Интервал:
Закладка:
Несмотря на то что код приложения весьма интересен, не менее интересно посмотреть на работу мидлета. На рис. 8.1 показан мидлет SoundCheck, запущенный в эмуляторе J2ME.
Рис. 8.1. Мидлет SoundCheck запрашивает типы поддерживаемого телефоном контентаКак видно из рисунка, мобильный телефон в эмуляторе J2ME поддерживает тоны, Wav-файлы, MIDI-музыку и MP3-аудио. Вы можете использовать эти результаты, чтобы включать поддержку определенных типов контента в мидлете.
Воспроизведение тонов в мобильных играх
Существует два принципиально разных метода воспроизведения тонов (звуков) в мобильных играх: использование тонов или последовательностей. Отдельный звук – это просто тон, имеющий определенную высоту и длительность воспроизведения. Хотя тоны, несомненно, ограничены событиями игры, они являются важной составляющей процесса разработки игр ввиду их простоты и эффективности. Чтобы воспроизвести звук, надо написать очень маленький код, затратив мало времени и ресурсов.
Тоновые последовательности более удобны с точки зрения создания звуковых эффектов и музыки. Звуковые последовательности можно сравнить с рингтонами на вашем телефоне.
Тоновые последовательности – это набор отдельных звуков, но они структурированы с точки зрения высоты и длительности звучания. На самом деле тоновая последовательность – это фрагмент музыки. Это объясняет, почему я решил затронуть тему музыки и нот в начале главы – это очень важно для создания звуковых последовательностей.
Воспроизведение отдельных звуков
Класс Manager в пакете javax.microedition.media используется для воспроизведения отдельных тонов. Этот класс содержит статический метод playTone(), который принимает следующие параметры:
► нота – высота тона от 0 до 127;
► длительность – длительность тона в миллисекундах;
► громкость – громкость тона в процентах от максимального уровня громкости устройства.
Задать высоту звука из диапазона от 0 до 127 – не простая задача, но вы можете использовать математические формулы для вычисления нужной частоты звука. Не пугайтесь, я покажу вам наиболее простой способ определения значений нужных нот. Если вы вспомните, о чем шла речь в предыдущем разделе, в октаве – 12 нот (таблица 8.1). Расположив несколько октав по степени повышения звука, вы получите 128 нот. Отсюда и появился диапазон от 0 до 127 – каждой ноте соответствует один байт данных.
Так уж случилось, что средняя С имеет порядковый номер 60. В интерфейсе ToneControl пакета javax.microedition.media.control для средней С определена константа С4 (С в четвертой октаве). Поскольку вы знаете порядок нот (см. таблицу 8.1), вы без труда сможете вычислить значения нужных. Ниже приведен пример, как можно вычислить значения некоторых нот:byte C4 = ToneControl.C4;
byte C5 = (byte)(C4 + 12);
byte A6 = (byte)(C4 + 21);
byte B6 = (byte)(C4 + 23);
byte G5 = (byte)(C4 + 19);
byte G4 = (byte)(C4 + 7);
byte D5 = (byte)(C4 + 14);Первая переменная введена, чтобы упростить использование константы ToneControl.C4. Оставшиеся переменные – это ноты различных октав, которые рассчитаны относительно средней C4. Переменная C5 очень интересна, поскольку она на одну октаву выше, чем C4. Поскольку в октаве 12 нот, то, чтобы из C4 получить C5, можно к первой прибавить 12. Аналогично, чтобы из C5 получить C4, необходимо из C5 вычесть 12. Чтобы лучше понять операции с нотами, посмотрите таблицу 8.1. Теперь, когда вы знаете, как определить высоту ноты, вам остается лишь передать ее в метод Manager.playTone() и воспроизвести ее:
try {
// воспроизвести среднее C (C4) в течение двух секунд (2000ms)
при максимальной громкости (100)
Manager.playTone(ToneControl.C4, 2000, 100);
}
catch(MediaException me) {
}Этот код воспроизводит ноту C4 средней октавы, все очень просто, для этого даже не надо рассчитывать смещений. Обратите внимание, что эта функция принимает два дополнительных параметра, которые устанавливают длительность воспроизведения звука (2 секунды) и громкость (100 %). Вы, вероятно, обратили внимание, что метод playTone() вызывается внутри конструкции try-catch. Это необходимо, поскольку этот метод может вызвать исключение MediaException, если произойдет какой-нибудь сбой во время воспроизведения тона. В данном примере код ничего не выполняет, но вы можете, например, вывести соответствующее предупреждение или учесть это в коде.
Воспроизведение последовательности тонов
Тоновая последовательность – это набор звуков, воспроизводимых в определенном порядке. Такие последовательности очень часто применяются при создании игр. Используя последовательности тонов, вы можете программировать музыку, а это не такая простая задача. Ниже приведены основные шаги, которые необходимо выполнить, чтобы воспроизвести звуковую последовательность средствами MIDP 2.0 Media API:
1. создать проигрыватель;
2. реализовать проигрыватель;
3. получить тональное управление проигрывателя;
4. установить тональную последовательность;
5. использовать проигрыватель для воспроизведения последовательности;
6. закрыть проигрыватель.
Создается впечатление, что это не такая уж простая задача, но не все так плохо. Самая хитрая часть кода – это создание структуры данных, представляющей тоновую последовательность. После того как последовательность создана, ее установка и воспроизведение выполняются парой строк.
Тоновая последовательность хранится внутри массива типа byte, каждый байт массива имеет свое особое значение. Как только вы научитесь создавать такие массивы, размещая информацию в нужных местах, вы увидите, что это не так уж и сложно. Чтобы задать тоновую последовательность как массив типа byte, необходимо использовать ряд констант, определенных в интерфейсе ToneControl. Ниже приведен список наиболее важных констант:
► VERSION – версия тоновой последовательности (обычно равно 1 для новой последовательности);
► TEMPO – темп тоновой последовательности (скорость воспроизведения);
► BLOCK_START – начальный блок тонов;
► BLOCK_END – конец блока тонов;
► PLAY_BLOCK – воспроизводимые ноты, включая блоки.
Блок в тоновой последовательности – это фрагмент тоновой последовательности. Например, если у вас есть музыкальный фрагмент, который повторяется несколько раз во время звучания музыки, то вы можете поместить его ноты в блок, а затем, вместо того чтобы записывать ноты вновь, просто сослаться на блок нот. Константа PLAY_BLOCK ставится в том месте, где следует воспроизвести блок. Вы можете указать отдельные ноты или их последовательность, используя константу PLAY_BLOCK.
Я понимаю, что это рассуждение, вероятно, не так легко воспринять, поскольку сложно представить, как константа может символизировать блок тонов. Поэтому давайте рассмотрим пример. Ниже приведен код тоновой последовательности песни, которая, вероятно, вам знакома:
byte[] marylambSequence = {
ToneControl.VERSION, 1,
ToneControl.Tempo, 30,
ToneControl.BLOCK_START, 0, //Секция А песни
E4, 8, D4, 8, C4, 8, D4, 8,
E4, 8, E4, 8, E4, 8, rest, 8,
ToneControl.BLOCK_END, 0,
ToneControl.PLAY_BLOCK, 0, //Этот код воспроизводит секцию А
D4, 8, D4, 8, D4, 8, rest, 8 //Воспроизвести секцию В
E4, 8, G4, 8, G4, 8, rest, 8,
ToneControl.PLAY_BLOCK, 0, //Воспроизвести секцию А снова
D4, 8, D4, 8, E4, 8, D4, 8, C4, 8 //воспроизвести секцию С
};Как видно, версия последовательности равна 1, а темп – 30. Темп измеряется количеством ударов в минуту, но когда вы задаете темп байтовым значением, вы должны разделить значение бита на 4. В данном случае темп равен 120 ударам в минуту.
Константа BLOCK_START открывает блок «А». Обозначение «А» ничего особенного не значит, оно просто выделяет фрагмент тональной последовательности. В примере программируется песня «Mary Had a Little Lamb» («У Мэри был маленький ягненок»), а фрагменты нот воспроизводятся в следующем порядке: A-B-A-C. Иначе говоря, блок «А» воспроизводится дважды: один раз в начале, а затем после фрагмента B. Поскольку фрагменты B и C не повторяются, то нет необходимости выделять их в отдельные блоки.
Каждая нота в последовательности определяется парой значений, которые задают высоту и длительность звука. Например, в блоке А нота Е4 имеет длительность 8, что соответствует одной восьмой. В таблице 8.3 приведены значения наиболее часто используемых длительностей.
Таблица 8.3. Длительности нот и соответствующие им значенияЧтобы лучше разобраться с последовательностью нот, взгляните на рис. 8.2, на котором представлены ноты и их соответствие тоновым данным.
Рис. 8.2. Песню «Mary Had a Little Lamb» можно запрограммировать тоновой последовательностьюВернемся к тоновой последовательности для этой песни. Я не объяснил, как используется переменная rest. Эта переменная используется для установления паузы в последовательности. Константа SILENCE означает тишину в тоновой последовательности. Ниже приведено объявление переменной rest:
byte rest = ToneControl.SILENCE;
После того как вы задали тоновую последовательность массивом типа byte, вы можете воспроизвести рингтон. Сначала необходимо создать проигрыватель, который сможет воспроизвести тоновую последовательность. Вот как можно это сделать: