В моем проекте при проигрывании музыкального образца на нотном стане появляется его нотная запись. При игре на рояле на нотном стане также появляются ноты, но они уже другого цвета. По совпадению наших нот и нот образца можно судить о правильности игры. В данной главе мы разберем, как формировать нотный стан.

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

Именованные символы нот
Рис. 16. Именованные символы нот.

Эти символы мы будем дублировать программно, будем располагать на нотном стане, изменяя их координаты. Для программного изменения свойств у символа на сцене должно быть уникальное имя. Имена могут быть любыми, но, как и любые имена переменных, они должны быть «говорящими» для более легкого восприятия программного кода. В моем случае символы имеют следующие имена: n_1-1, n_1-2, n_1-4, n_1-8, n_1-16, n_1-32, di.

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

Выравнивание символа ноты «по сцене»
Рис. 17. Выравнивание символа ноты «по сцене».

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (p == "32") {
pausa[i] = 0*dl;
duplicateMovieClip("n_1-32", "n_1-32"+i, i);
name = "n_1-32"+i;
} else if (p == "16") {
pausa[i] = 1*dl;
duplicateMovieClip("n_1-16", "n_1-16"+i, i);
name = "n_1-16"+i;
}
. . .
} else {
pausa[i] = 16*dl;
duplicateMovieClip("n_1-1", "n_1-1"+i, i);
name = "n_1-1"+i;
}

В данном фрагменте помимо определения длительности каждой ноты, вычисления времени ее звучания происходит дублирование символа – строки 3, 7, 13. Команда duplicateMovieClip("n_1-32", "n_1-32"+i, i) берет объект с именем n_1-32, на основе его создает новый объект с именами n_1-321, n_1-322. Напомню, что все дело происходит в цикле, где переменная i меняет свое значение от 1 до n. Новый объект помещается на слой под номером i (основная сцена располагается на нулевом слое). Далее имя вновь созданного объекта сохраняется в переменной name – строки 4, 8, 14. Это имя нужно для дальнейшего выстраивания объектов на нотном стане:

1
2
3
4
5
6
7
8
9
10
11
12
13
if (sample[i] == "c_1") {
setProperty(eval(name), _y, y0+0*dy);
} else if (sample[i] == "cd1") {
setProperty(eval(name), _y, y0+0*dy);
duplicateMovieClip("di", "di"+i+n, i+n);
setProperty("di"+i+n, _y, y0+0*dy);
setProperty("di"+i+n, _x, x0+i*dx);
}
. . .
} else {
setProperty(eval(name), _y, y0+23*dy);
}
setProperty(eval(name), _x, x0+i*dx);

Данный фрагмент располагается также в третьем ключевом кадре, в самом конце цикла. Значение массива sample[i] и значение переменной name уже определенно. Вновь представлен не весь программный код, а лишь часть в котором, я надеюсь, видна идея.

Напомню, что для расположения ноты на нотном стане мы должны знать значение ноты и ее длительность, причем диез ноты располагаются на том же уровне, что и основная нота, но перед ними добавляется символ диеза. программный код, располагающий ноты состоит из большого условного оператора, имеющего много вариантов выбора. Если необходимо найти место для ноты до первой октавы (значение массива sample[i] равно c_1), выполняется команда setProperty(eval(name), _y, y0+0*dy+ddy) – строка 2. В ней у объекта под именем name, преобразованного из строки в выражение, изменяется значение свойства _y (координата y). Новое значение свойства определяется выражением y0+0*dy+ddy, где y0 – общее смещение нот относительно края холста, координата самой нижней ноты, dy – смещение между нотами на нотном стане по оси y. В моем проекте данные константы равны: y0 = 226, dy = -6, они задаются в первом ключевом кадре, но нужно помнить, что их значения, полностью определяются тем, как вы нарисуете нотный стан. Их значения вам придется подбирать самостоятельно, так, чтобы ноты располагались именно на той высоте, на которой они должны быть.

Несколько более сложный код ожидает нас, если нужно расположить ноту до-диез – строки 3-7. Помимо выстраивания ноты (строка 4) нужно дублировать символ диеза (строка 5) и у вновь созданного символа изменить координату y (строка 6). Для изменения координаты x используется команда setProperty("di"+i+n, _x, x0+i*dx), она полностью аналогична, команде изменяющей координату y. Разница только в выражении, вычисляющем эту координату. x0 – координата, определяющая смещение всех нот, координата самой первой ноты, dx – расстояние между нотами по горизонтали. Эти константы также задаются в первом кадре и их значение необходимо определять экспериментально.

Приведенный фрагмент кода завершается командой изменяющей координату x у ноты с именем name – строка 13.
Теперь запустив ролик и выбрав нужный музыкальный фрагмент, вы не только можете прослушать музыку, но и увидеть ее нотную запись.