Для запуска музыкальных образцов служат кнопки, выполненные в виде компакт-диска. В моем проекте кнопки – анимированные, при наведении мыши на них они начинают вращаться, а в поле вывода появляется название музыкальной композиции. Разумеется, все «оформительские» элементы можно опустить, по крайней мере, в начале.

Вот что нужно сделать, так это создать новый слой над роялем, и назвать его «управление». В нем будут размещаться все кнопки переходов между блоками программы. Создайте кнопку, для выбора музыкального образца и для кнопки задайте следующий программный код (ниже приведен программный код для выбора первого музыкального фрагмента, для всех других кнопок, код аналогичен):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
on (rollOver) {
song = name_song1;
}
on (release) {
ex = obr1;
num = 1;
gotoAndPlay(3);
}
on (rollOut) {
if (num == 1) {
song = name_song1;
} else {
song = "";
}
}

Обратите, внимание, что в данном фрагменте описаны три разных набора действий, связанных с данной кнопкой. Каждый набор действий связан со своим событием:

rollover - (курсор мыши проходит над кнопкой);
release - (человек «щелкает» на кнопке);
rollOut - (курсор мыши уходит с кнопки).

Для изменения события в нормальном режиме создания программного кода вам нужно изменить соответствующий переключатель в окне «Действие кадра» (рисунок 13) .

Изменения события выполнения кода
Рис. 13. Изменения события выполнения кода.

При первом событии – rollover (строки кода 1-3), выполняется всего одно действие переменная song принимает значение другой переменной name_song1. При наведении мыши на экране должно появиться название композиции. Для этого на слое «управление» добавьте динамическое текстовое поле и дайте для него имя переменной song (рисунок 14).

 Создание динамического поля и задание переменной, для обращения к нему
Рис. 14. Создание динамического поля и задание переменной, для обращения к нему.

Второй набор команд происходит при событии – release (строки кода 4-8). Во временной переменной ex сохраняется значение «мелодического» кода, это сделано для того, чтобы после можно было сравнить игру музыканта с эталоном. Также в этом фрагменте переменная num (номер музыкального образца) принимает значение 1 и управление передается третьему кадру.

Третий набор команд происходит при событии – rollOut (строки кода 9-15). Здесь опредяеляется нужно ли убирать название музыкального образца после убирания курсора мыши с кнопки. Если переменная num равна единице, то есть игрок уже щелкнул на кнопку, то динамическое поле song отображает название музыкального фрагмента, если же это не так, при убирание курсора динамическое поле song становится пустым.

Давайте разберем, что должно происходить в третье ключевом кадре, ведь именно туда осуществляется переход при выборе музыкального образца (рисунок 15).

 Слои и ключевые кадры
Рис. 15. Слои и ключевые кадры.

Как видно из рисунка на слое «действия» добавлено три ключевых кадра, все другие слои продлены до пятого кадра.
На третьем кадре начинается классический трехкадровый цикл. В первом (третьем) кадре цикла задаются начальные значения, код образца разделяется на отдельные ноты. Во втором (четвертом) кадре совершается единичное действие, в нашем случае проигрывание одной ноты образца, а в третьем (пятом) кадре происходит зацикливание.

Разберем код третьего ключевого кадра подробней:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
n = eval("obr"+num+".length")/3;
z = 0;
z2 = 0;
sample = new Array();
for (i=1; i<=n; i++) {
sample[i] = eval("obr"+num).charAt(z);
z = z+1;
sample[i] = sample[i]+eval("obr"+num).charAt(z);
z = z+1;
sample[i] = sample[i]+eval("obr"+num).charAt(z);
z = z+1;
p = eval("p"+num).charAt(z2);
z2 = z2+1;
p = p+eval("p"+num).charAt(z2);
z2 = z2+1;
if (p == "32") {
pausa[i] = 0*dl;
} else if (p == "16") {
pausa[i] = 1*dl;
} else if (p == "08") {
pausa[i] = 2*dl;
} else if (p == "04") {
pausa[i] = 4*dl;
} else if (p == "02") {
pausa[i] = 8*dl;
} else {
pausa[i] = 16*dl;
}
}
i = 1;

В первой строчке определяется количество нот в музыкальном фрагменте, для этого к строковому объекту применяется метод .length (определение длинны строки) и полученное значение делится на три. Но какой длину какого строкового объекта определять и меня таких объектов шесть, у вас может быть еще больше. Здесь нам помогает функция eval(), которая позволяет работать с переменной, которая в свою очередь является вычисляемым значением. Вначале выполняется конкатенация "obr"+ num +".length", причем num – это переменная, а "obr" и ".length" – строки. результатом выполнения данной команды для переменной num равной одному становится строка obr1.length и вот она-то и превращается из строки в выражение, с помощью функции eval() .

В четвертой и пятой строчках создаются два массива sample – для хранения нот образца и pausa, для хранения длительности каждой ноты . В шестой строке начинается цикл «с параметром», который разделяет строки с кодом музыки на отдельные элементы.

7-12 строки служат для выделения трех символов в строке с «мелодическим» кодом и сохранение этих трех символов в элементе массива sample[i]. Для этого трижды к строковому объекту применяется метод .charAt(z), выделяющий в строке z-й элемент. Так как нумерация элементов строке начинается с нуля, вначале переменная z приравнивается к нулю во второй строке фрагмента, а после каждого выполнения метода .charAt(z) переменная z увеличивается на единицу.

13-16 строки служат для выделения двух символов в строке с кодом длительностей и помещение результата такого выделения в переменную p. Тем, что результат выделения помещается не в массив, а в переменную объясняется очень просто. В массив pausa[i] помещается не код длительности каждой ноты, а время, в течении которого, эта нота должна звучать. Это преобразование совершается в строках кода с 16 по 28. В Action Script нет конструкции, аналогичной оператору case в Pascal. Для выбора из нескольких значений используется конструкция

 if () {
} else if () {
} else if () {
...
} else {
}

В нашем примере, если переменная p равна «32» (одна тридцать вторая нота), то в массив pausa[i] заносится значение 0*dl, если p равно «16», то элемент массива примет значение 1*dl. Здесь dl – это константа, которая определяет длительность одной шестнадцатой ноты в миллисекундах. Все константы определяются в первом ключевом кадре (смотри финальный код) и в нашем случае dl равно 200. Использование констант облегчает отладку и изменение программы. Как видно из примера длительность 1/32 ноты равно нулю. В действительности это конечно не так. Просто это означает, что компьютер не будет делать задержку для этой ноты, ее длительность, как будет видно ниже, определяться временем смены кадра во Flash. Также обратите внимание, что при использовании условного оператора проверяется, равно ли p «32». Кавычки здесь важны, ведь p – это строковая переменная.

К тридцатой строчке кода мелодия разбита на n нот, значения каждой ноты сохранено в массиве sample[i], а длительности в массиве pausa[i]. Действие переходит к четвертому ключевому кадру, но вначале переменная i принимает значение равное 1. Забегая вперед, скажу, что эта переменная будет определять, сколько нот образца уже сыграно:

1
2
3
4
5
6
7
eval(sample[i]).start("", 1);
x = getTimer();
y = getTimer();
while ((x-y)<pausa[i]) {
x = getTimer();
}
i = i+1;

В первой строчке фрагмента запускается музыкальный объект (метод .start), имеющий имя то же, что и элемент массива sample[i]. Я думаю теперь понятно, почему столь важно было придумать единую систему кодирования нот в данном проекте.

Во второй и третьей строчке запоминается текущее «время ролика». Напомню, что оно начинает отсчитываться от момента запуска ролика и измеряется в миллисекундах. До тех пор пока разница между x и y не станет равна значению элемента массива pausa[i], происходит постоянное измерение времени (строка 5). Когда это наступает, переменная i увеличивается на единицу и ролик переходит к следующему, пятому кадру, в котором происходит «зацикливание». Он - самый простой:

1
2
3
4
5
if (i<=n) {
gotoAndPlay(4);
} else {
stop();
}

Если переменная i приняла значение меньше либо равное n, то есть, проиграны еще не все ноты, ролик переходит к четвертому кадру, где будет проиграна следующая нота. Иначе ролик останавливается.

Данная глава получилась довольно большой, но в ней мы познакомились с несколькими важными примами программирования на Flash, а главное, теперь щелкая на кнопку, у нас проигрывается музыкальный образец.