Создание Flash-игр

         

Составь лису методом "Перетащи и положи"

Исходный файл: Makeafox-drag.fla

Многие компьютерные игры созданы по подобию игрушек докомпьютерной эры. Одна из таких старых игрушек - "Mister Potato Head" (Господин картофельная голова). Она представляла собой набор пластиковых частей тела которые ребенок мог прикрепить к картошке и сделать смешного человечка. Позже вместо картошки стали использовать пластиковое туловище.

Задача проекта

Задача этого проекта - создать приложение, которое позволит пользователю присоединять части тела лисы к неподвижному туловищу и так составлять изображение зверька. Метод drag-and drop (перетащи и положи) должен быть знаком всем, кто умеет работать с компьютером.

Подход

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

Подготовка ролика

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

Рисунок 7.1 Изображенные слева части тела можно

переместить к расположенному справа туловищу

Ролик можно запустить, открыв файл Makeafox-drag.fla. Вы можете выбрать любую часть тела и переместить ее в любую часть экрана.

Создание кода

Если вы уже работали во Flash, вы можете подумать, что это легко - необходимо просто использовать клипы частей тела и команды startDrag, и stopDrag. На самом деле такой подход только все усложнит. Я не любитель команды startDrag и не буду использовать ее здесь, поскольку перемешать с ее помощью элементы по рабочему полю не так уж и просто.
Представив каждую часть тела в виде кнопки, вы можете назначить ей обработчик события on (press) и применить команду startDrag. Однако кнопка не может служить в качестве цели команды startDrag, такой целью может быть только клип. Если же вы представите их в виде клипов, им нельзя будет назначить функцию on (press), так как она используется только с кнопками. Еще одним вариантом является представление каждой части тела как клипа с кнопкой внутри. Здесь можно легко запутаться, так как каждый раз при добавлении в ролик новой части вам придется выполнить несколько действий.
Лучшим выходом будет написать код, выполняющий процедуру drag-ard-drop самостоятельно. Отдельным частям не будет назначено никакого кода, благодаря чему их будет легко создавать и добавлять новые.
Весь код поместим в клип "actions", который как обычно находится вне, пределов рабочей области и содержит только надпись "Actions".
Данному клипу назначен сценарий ActionScript, управляющий перемещением всех элементов. Он должен включать несколько функций onClipEvent. Ниже приведено краткое описание событий и реакций на них, которые сценарий должен выполнять:
• load (загрузить) - задание переменной, указывающей, что никакого перемещения еще не происходит;
• mouseDown (кнопка мыши нажата) - определение выбранного элемента и создание переменной, сообщающей, что этот элемент перетаскивается. Определение смешения между местом, над которым нажата кнопка мыши, и центром выбранного элемента;
• mouseUp (кнопка мыши отпущена) - установка начальных параметров переменной, указывающих, что никакой элемент в данный момент не перетаскивается;
• enterFrame (проигрывание кадра) - изменение положения перемещаемого элемента соответственно движению курсора минус разница между координатами центра элемента и координатами точки, по которой щелкнул пользователь.
Два момента из предыдущего списка могут смутить непрограммиста. Первый - это постоянно упоминаемая переменная. В коде ей будет назначено имя dragPart и исходное значение 0. Это значение соответствует состоянию, при котором не происходит никакого перемещения. Однако, как только пользователь выбирает элемент, переменной dragPart присваивается номер данного элемента, а когда значение переменной равно какому-либо числу, происходит перемещение. Когда пользователь отпускает элемент, переменная вновь принимает значение 0.
В рассматриваемом коде есть еще один сложный момент - смешение при передвижении элементов. Когда мы перетаскиваем какой-либо объект, то приравниваем значения его координат значению координат курсора. Однако, если пользователь щелкнет не в центре координат объекта, то при приравнивании положения объекта к положению курсора, произойдет "скачок"; координаты объекта мгновенно станут равны координатам курсора.
Чтобы этого не происходило, мы используем переменные offsetx и offsety для хранения величины расстояния между центром объекта и местом клика и при изменении координат объекта учитываем это смещение.
Теперь давайте рассмотрим каждую часть данного кода. Вначале выполняется функция onClipEvent (load). Она необходима для инициализации переменной dragPart.

// При загрузке ничего не перетаскиваем.
onClipEvent (load) {
dragPart = 0; }

Наиболее сложной частью кода является функция onClipEvent (mouse-Down) . Она проверяет все 13 элементов при помощи функции hitTest и определяет, над какой из них расположен курсор. Затем задает переменную dragPart, а также переменные of f setx и of f sety.
Обратите внимание, что клипы элементов для упрощения кода имеют имена от "Part1" до "Partl3".

// Начинаем перемещение.
onClipEvent (mouseDown) {
// Определяем текущие координаты курсора.
x = _root._xmouse;
y = _root._ymouse;
// Находим часть, над которой в данный момент находится курсор.
for(i=1;i<=13;i++) {
// Имеет смысл заменить константу 13 переменной, содержащей
// количество частей, например countOfParts. Это облегчит
// дальнейшую модификацию ролика.
if (_root["Part"+i].hitTest(x,y, true)) {
// Указываем, какой элемент нужно перетаскивать,
// и задаем смещение.
dragPart = i;
offsetx = _root["Part"+i]._x - x;
offsety = _root["Part"+i]._y - y;
break;
}
}
}

Когда пользователь отпускает кнопку мыши, переменная вновь принимает значение 0.

onClipEvent (mouseUp) {
dragPart = 0;
}

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

Основополагающим компонентом данного кода является функция onClipEvent (enterFrame). Она проверяет, не равна ли переменная dragPart нулю, а затем задает положение перетаскиваемого элемента соответственно текущему положению курсора мыши плюс значение смешения.

// Если какой-либо элемент перетаскивается, меняем его координаты
onClipEvent (enterFrame) {
if (dragPart > 0) {
_root["Part"+dragPart]._x = _root._xmouse + offsetx;
_root["Part"+dragPart]._y = _root._ymouse + offsety;
}
}

В нашем примере используются не клипы, а графические элементы из библиотеки. Но для всех графических символов, которые будут иметь возможность перемещаться по рабочему полю, мы устанавливаем свойство MovieClip в выпадающем меню Symbol Behavior (Поведение символа). Это меню находится в верхней левой части панели Properties (рис. 7.2). Теперь, хотя мы создали этот символ как графический элемент его копии можно присваивать имя, как будто он является клипом! Например, символ "Arm1" в библиотеке отображается как графический: элемент, но на панели Properties мы присвоили ему имя "Part1", так как свойство его поведения было изменено.

Рисунок 7.2 В панели Properties вы можете назначить графическому Flash-элементу свойство клипа и имя, отличное от его имени в библиотеке

Несколько слов о взаимном перекрывании символов на рабочем столе. Я расположил все подвижные элементы поверх головы и туловища, которые статичны. Исключение сделано для символов с изображением ног - они помешены на последний (задний) и предпоследний планы. Выделив элемент на рабочем столе, вы можете изменить его уровень с помощью команды Modify -> Arrange (Изменения -> Упорядочить).
На рис. 7.3 изображен один из вариантов изображения лисы, получившийся в результате перемещения ряда элементов из левой части в правую.

Рисунок 7.3 Ролик Make-A-Fox дает пользователю возможность перетаскивать части тела лисы в любое место экрана

Создай лису методом "Нажми и измени"

Исходный файл: Makeafox-switch.fla

В другом варианте конструирования изображений все элементы остаются на местах, однако пользователь получает возможность изменять их. Это версия "нажми и измени" предыдущего примера. Здесь не используется перемещение, все действия выполняются только щелчками мыши.

Задача проекта

Исходное изображение будет полным, но, когда пользователь щелкнет по одному из его элементов, он изменится. Например, пользователь может щелкнуть по глазам и вместо них появится другая пара глаз.

Подход

Библиотека данного ролика имеет не такую, как мы рассматривали раньше, организацию. Вместо отдельных изображений каждого варианта элемента лисы используются клипы. Каждый клип содержит все варианты данного элемента, по одному в кадре. Например, клип "Eyes" ("Глаза") будет стоять из трех кадров, каждый из которых содержит другое изображение глаз.

Создание кода

Здесь не применяется перетаскивание, поэтому сценарий будет немного проще. Код представляет собой сценарий onClipEvent (mouseDown) помешенный в клип "actions", который расположен за пределами рабочего поля клипа. Как и функция hitTest в ролике Makeafox-drag.fla, данный сценарий проверяет, какой клип выбран.
Однако вместо имен "Part1" - "Part 13" клипы получают значащие имена (например, "Eyes" и "Head"). Сценарий должен проверить каждый клип, для чего все клипы собраны в общий список.
При нахождении соответствующего клипа код продвигается на один кадр вперед. Если впереди кадров больше нет, он возвращается к кадру 1.

onClipEvent (mouseDown) {
// Определяем, в каком месте щелкнул пользователь
x = _root._xmouse;
y = _root._ymouse;
// Выясняем, по какому элементу произведен щелчок
list = ["Eyes", "Mouth", "Head", "Legs", "Left Arm", "Right Arm", "Body"];
for(i=0;i if (_root[list[i]].hitTest(x, y, true)) {
// Меняем выбранный элемент
with (_root[list[i]]) {
// Переходим к следующему кадру
if (_currentFrame == _totalframes) {
gotoAndStop(1);
} else {
nextFrame();
}
}
break;
}
}
}

Номер кадра и обшее количество кадров определяется при помощи параметров _currentFrame и _totalFrame. Это очень удобно в случае, когда клипы могут включать любое количество кадров, а код -учитывать все возможные варианты.

Конструкция with указывает, что все команды и функции кода в рамках этой конструкции должны выполняться для определенного клипа. Это позволит вам обойтись без добавления _root [movieclip] в начале каждой команды или функции.

Ролик Makeafox-switch.fla можно увидеть на Web-сайте. На рис. 7.4 показан один из возможных вариантов, получившихся в результате внесенных изменений. Независимо от того, сколько раз и в какой последовательности пользователь щелкает по элементам изображения, оно всегда будет оставаться цельным.

Рисунок 7.4 Пользователь может щелкнуть по любой части тела и изменить ее

К сведению

Для того чтобы закончить создание ролика Makeafox-switch.fla, следует обратить внимание еще на несколько деталей. Во-первых, каждый первый кадр клипа должен содержать команду stop(). Это поможет избежать безостановочного воспроизведения всех вариантов клипа при первом запуске ролика. Затем каждый клип должен быть помещен на рабочее поле и назван, как соответствующий элемент списка в коде.

Другие возможности

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


Альбом для рисования

Исходный файл: Drawing-line.fla, Drawing-fill.fla

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

Задача проекта

Задача данного раздела - создать программу, в которой пользователь может рисовать, как в простом графическом приложении. Пользователь должен иметь возможность рисовать простые линии и фигуры, а также применять различные цвета.

Создание простой программы рисования

Конечный ролик позволит пользователю рисовать, используя различные фигуры и цвета, однако для начала дадим ему возможность нарисовать непрерывную линию.
Мы воспользуемся новыми командами для рисования, появившимися в версии MX. Описание этих команд вы можете найти на панели ActionScript (Objects -> Movie -> Movie Clip -> Drawing Methods) или в окне Reference (справка).
Эти команды как бы имитируют движения пользователя, передвигающего мышь. Сначала используем команду line style для определения толщины и цвета будущей линии. Команда moveTo передвигает указатель точки для рисования по экрану; линия при этом не прорисовывается. И наконец, мы используем команду lineTo для рисования линии из текущей позиции в заданную.
Единственным элементом нашего ролика является клип "actions", который содержит весь необходимый код.
Сценарий начинается с присваивания переменной draw значения false. Эта переменная используется, чтобы определить, рисует пользователь или нет. Затем с помощью linestyle мы задаем толщину и цвет.

Третий параметр команды lineStyle определяет прозрачность линии, то есть свойство alpha. Значение 100 соответствует абсолютно непрозрачному объекту, значение 50 делает объект полупрозрачным.

onClipEvent (load) {
// Рисовать или не рисовать?
draw = false;
// Линия шириной в 1 пиксел, черная, непрозрачная
_root.lineStyle(1,0x000000,100);
}

Когда пользователь нажимает кнопку мыши, переменной draw присваивается значение true. Затем команда moveTo перемещает указатель в текущую позицию курсора. Мы используем конструкцию _root для обращения к свойствам _xmouse и _ymouse, т.к. хотим чтобы центр координат был независим от положения клипа "actions".

onClipEvent (mouseDown) {
// Будем рисовать
draw = true;
// Переходим к координатам курсора.
_root.moveTo(_root._xmouse, _root._ymouse);
}

Когда пользователь отпускает кнопку мыши, переменной draw присваивается значение false, и процесс рисования завершается.

onClipEvent (mouseUp) {
// Завершаем рисование.
draw = false;
}

Значение переменной draw проверяется при каждом обращении к кадру. Если оно истинно, то рисуется линия от предыдущей к текущей позиции курсора.

Константы true и false могут использоваться конструкциями if и for в качестве проверки условия выполнения кода. Вы также можете использовать их для отслеживания объектов, которые могут нахолиться только в двух состояниях (вкл/выкл).

onClipEvent (enterFrame) {
if (draw) {
_root.lineTo(_root._xmouse,_root._ymouse);
}
}

Обратите внимание, что все обращения к командам рисования происходят через конструкцию _root. Это делается для того, чтобы линии рисовались в самом ролике, на рабочем поле, а не на рабочей области клипа "actions". Можно создать отдельный клип "canvas " (холст) и рисовать линии в нем. Прорисовываясь, линии автоматически оказываются на самом заднем плане, так что, если в клипе ( или ролике) есть еще какие-то объекты, они будут закрывать линию. Наверное, вам будет удобней рисовать на пустом уровне.

На рис. 7.5 показана кривая, которая получилась в результате нажатия пользователем кнопки мыши и перемещения курсора. Помните, что скорость рисования соответствует частоте смены кадров ролика, поэтому для того, чтобы процесс рисования проходил плавно, это значение должно быть максимальным и равняться 120 калр/с. Готовый ролик вы можете увидеть, загрузив файл Drawing-line.fla.

Рисунок 7.5 Простая программа рисования позволяет нарисовать длинную черную кривую

Создание полной программы рисования

Хотя предыдущая программа демонстрирует продвинутые возможности ActionScript, результат ее работы не очень-то интересен. В программу можно добавить другие фигуры и цвета, а также возможность выводить на печать результаты рисования.
Второй параметр функции lineStyle отвечает за выбор цвета. В предыдущем примере был выбран черный цвет — 0x000000. Префикс Ох сообщает программе, что следующее за ним число надо воспринимать в шестнадцатеричном формате, так же, как это происходит при HTML-верстке. Шесть последних цифр обозначают собственно цвет. Также можно использовать значение цвета, получаемое вызовом функции getRGB. В ролике Drawing-fill.fla я использовал несколько разноцветных кнопок. Каждая из этих кнопок представляет собой клип с кнопкой внутри.
На рис. 7.6 показан вид исходного файла Drawing-fill.fla. Слева расположены кнопки, с помощью которых пользователь может управлять цветом.

Рисунок 7.6 Кнопки в левой части экрана дают пользователю возможность выбрать цвет и фигур

Каждая из этих кнопок создана из одного библиотечного эталона. Когда копия помешается на рабочее поле, можно настроить ее цвет с помощью меню color на панели Properties. Внутри клипа находится кнопка, чтобы отслеживать выбор пользователя. Ниже приведен сценарий кнопки. Значение цвета кнопки помещается в переменную brushcolor. Ее значение затем передается переменной linecolor в клип "actions".

on (release) {
// Определяем цвет.
myColor = new Color(this);
brushColor = myColor.getRGB();
// Передаем значение переменной linecolor клипа "actions"
_root.actions.lineColor = brushColor;
// Определяем позицию рамки.
_root["Color Selection"]._x = this._x;
_root["Color Selection"]._y = this._y;
}

Сценарий кнопки устанавливает координаты клипа "Color Selection", то есть рамки, равными координатам клипа, по которому щелкнул пользователь. При этом вокруг кнопки с выбранным цветом появится контур (рис. 7.6.)
Маленькая кнопка с кружочком посередине служит для выбора режима рисования - с заливкой или без. Клип с этой кнопкой состоит из двух кадров: с пустым и заполненным кружочком. Кнопка содержит сценарий, позволяющий переключаться между кадрами, и определяет переменную fill клипа "actions".

on (release) {
if (_currentFrame ==1) {
gotoAndStop(2);
_root.actions.fill = true;
} else {
gotoAndStop(l);
_root.actions.fill = false;
}
}

С помощью кнопок, определяющих цвета, и кнопки выбора режима (с заливкой/без заливки) пользователь может рисовать разноцветные фигуры. Как и в предыдущем примере, код, необходимый для рисования, содержится в клипе "actions".
Он начинается с определения значения следующих переменных: draw - false, fill - false, linecolor - 0x000000. Также определяются четыре переменные, для которые ограничивают область в которой пользователь может рисовать.

onClipEvent (load) {
// Рисовать или не рисовать?
draw = false;
// Определяем значение fill
fill = false;
// Начальный цвет линии - черный. linecolor = 0x000000;
// Определяем границы области рисования.
хтах = 550;
xmin = 70;
утах = 400;
ymin = 0;
}

При нажатии кнопки мыши курсор начинает оставлять след. Координаты курсора хранятся в переменных х и у. Их значения проверяются, и, если они выходят за фаницы разрешенной области, рисование не происходит.
Переменная linecolor передается функции lineStyle в качестве аргумента, определяющего цвет линии. Если переменная fill имеет значение true, то определяется новый массив. Он содержит координаты всех точек вдоль кривой, которую нарисовал пользователь. Массив состоит из объектов следующего вида: {х: значение, у: значение}. Элементы массива потребуются для создания залитой цветом области.

onClipEvent (mouseDown) {
// Определяем позицию курсора.
х = _root._xmouse;
у = _root . _ymouse;
// Рисуем, если не вышли за границы поля
if ((x>xmin) and (x<xmax) and (y>ymin) and (y<ymax)) {
draw = true;
// Определяем параметры линии.
_root.lineStyle(1,lineColor,100);
_root.moveTo(x,у);
// Если выбран режим заливки, то создаем массив if (fill) {
fillArray = new Array();
fillArray,push({x:x, y:y});
}
}
}

После того как переменной draw присвоено значение true, продолжаем линию до тех пор, пока пользователь не отпустит кнопку мыши. При каждом обращении к кадру переменным х и у присваиваются текущие координаты курсора. Если эти значения выходят за разрешенные границы, переменные х и у переопределяются. Затем используется команда lineTo для отображения очередного сегмента линии. Если выбран режим заливки, то добавляется новый элемент в массив fillArray.

onClipEvent (enterFrame) {
if (draw) {
// Определяем текущую позицию.
x = _root,_xmouse;
у = _root._ymouse;
// Задаем границы области рисования,
if (x < xmin) x = xmin;
if (x > xmax) x = xmax;
if (y < ymin) у = ymin;
if (y > ymax) у = ymax;
// Рисуем линию.
_root.lineTo(x,у);
// Если выбран режим заливки, то запоминаем точку,
if (fill) {
fillArray.push({х:х, y:y});
}
}
}

Когда пользователь отпускает кнопку мыши, переменная draw принимает, значение false, и рисование прекращается. Если при этом выбран режим заливки, то в цикле просматривается массив fillArray и созданная область перерисовывается. При этом также используются команда beginFill и endFill. В результате область заливается цветом linecolor.

onClipEvent (mouseUp) {
if (draw) {
// Прекращаем рисовать.
draw = false;
// Перерисовываем кривую и заливаем
// получившуюся область,
if (fill) {
// Начинаем с первой точки.
_root.moveTo(fillArray[0].x,fiiiArray[0] .у);
// В цикле определяем область для заливки.
_root.beginFill(lineColor);
for(var i=l;i < fillArray.length;i++) {
_root.lineTo(fillArray[i].x,fillArray[i].y);
}
_root.endFill();
}
}
}

Другой способ состоит в том, что вы можете вызвать команду beginFill до того, как пользователь начнет рисовать, и команду endFill - когда он закончит, вместо того чтобы перерисовывать кривую. Но Flash не очень любит использовать заливку при разных обращениях к кадру, и результат может быть хаотичен. Лучше сохранить кривую, а затем перерисовать ее и создать всю заливку в пределах одного обработчика.

Добавление кнопок Clear и Print

Чтобы очистить рабочую область, мы просто нарисуем сверху заполненный цветом области прямоугольник. Это выполняется с помощью сценария кнопки Clear (Очистить).
Мы устанавливаем толщину линии 0. Затем перемещаем указатель в верхний левый угол нашей области и рисуем прямоугольник, который точно ее повторяет и определяет область заливки. Цвет заливки - белый, так как именно он выбран фоновым в нашем ролике.

on (release) {
// Толщина линии - ноль.
_roou.lineStyle(0,OxFFFFFF,100);
// Перемещаем указатель в верхний левый угол.
_root.moveTo(actions.xmin,act ions.ymin);
// Создаем область заливки.
_root.beginFill(OxFFFFFF);
_root.lineTo(actions.xmax,actions.ymin);
_root.lineTo(actions.xmax,actions.ymax);
_root.lineTo(actions.xmin,actions.ymax);
_root.lineTo(actions.xmin,actions.ymin);
_root.endFill();
}

Еше легче создать кнопку Print (Печать). Для этого необходимо добавить команду print. Осталось еше присвоить метку "#р" единственному кадру ролика.

on (release) {
// Распечатываем клип
print(_root,"bframe");
}

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

Рисунок 7.7 Изображение примера использования ролика.

К сведению

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

Другие возможности

Вы можете усовершенствовать программу, добавив возможность выбора толщины линии по аналогии с цветами. Можно создать кнопку, которая будет определять переменную lineSize в клипе "actions". Добавив в палитру белый цвет, вы дадите пользователю возможность стирать уже нарисованное.


Музыкальный миксер

Исходный файл: Musicmixer.fla

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

Задача проекта

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

Рисунок 7.8 Музыкальный миксер состоит из шести циклов барабанов, шести циклов с басами и шести отдельных звуковых эффектов

Подход

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

Подготовка ролика

Основными элементами ролика являются 18 звуков. В примере MUSICmixer.fla использовались звуки, созданные профессиональным композитором. Вам придется сочинить звуки самому, привлечь к этому друга или коллегу или позаимствовать музыку из любых других источников.
Циклы барабанного боя и басов состоят из коротких звуков, создающих законченные музыкальные фразы. Они должны быть короткими, чтобы не перегружать файл, но достаточными для того, чтобы создать интересный звук.
После импорта 18 звуков во Flash в диалоговом окне Symbol Linkage Properties (рис. 7.9) необходимо установить свойство Export for ActionScript, а также задать идентификатор.

Рисунок 7.9 Настройки диалогового окна Symbol Linkage Properties определяют, каким образом звук будет включен во Flash-ролик

Необходимо создать три различных типа кнопок. В действительности они представляют собой не кнопки, а клипы. Поэтому, чтобы избежать путаницы, мы назовем их "переключателями". Переключатели содержат невидимые кнопки, реагирующие на щелчок мыши. Они состоят как минимум из двух кадров. Первый из них соответствует выключенному состоянию переключателя, остальные - включенному. Так как звуки барабанов и басов представляют собой повторяющиеся циклы, анимация этих двух переключателей воспроизводится непрерывно, пока не будет прекращена повторным щелчком мыши. В отличие от этого анимация переключателя отдельного звука воспроизводится один раз и затем возвращается к состоянию "выключено". Состав анимационных последовательностей вы можете просмотреть в файле Musicmixer.fla.
Кнопки в переключателях - это простые белые фигуры, которые помешаются за другими графическими изображениями, чтобы их не было видно. В примере для переключателей барабанов и басов используется небольшая круглая кнопка, для переключателей отдельных звуков - треугольная. Чтобы было проще размещать кнопки за графическими объектами, создано только два типа изображений кнопок. Шесть копий каждого переключателя помешены на рабочее поле. Их расположение может быть любым (рис. 7.8).

Создание кода

Код назначен кнопкам, которые размешены внутри переключателей. Первый кадр каждого переключателя содержит код для запуска воспроизведения звука. Помимо этого код задает переход клипа к следующему кадру. Кнопка присутствует во всех кадрах клипа. Различные сценарии используются для остановки звука в цикле барабанов и цикле басов.
Самый простой сценарий - у переключателей отдельных звуков. Задача данного сценария - запустить воспроизведение звука и задать его переход к следующему кадру.

on (press) {
// Указываем, что надо проиграть из библиотеки звук
// соответствующий выбранному клипу.
instanceSound = new Sound(),
instanceSound.attachSound(this._name);
instanceSound.start();
// Начинаем анимацию, показывающую, что кнопка выбрана.
gotoAndPlay(2);
}
}

Обратите внимание, что имя звука описывается при помощи синтаксиса this._name. Это значит, что имя клипа будет являться и именем звука Если клип называется "instance 1", код попытается воспроизвести звук с именем "instance 1". Первое имя "instance 1" соответствует имени клипа на рабочем поле, второе имя "instance 1" является именем соответствующего звука в библиотеке. Эта схема работает только в том случае, если имена полностью совпадают.
Преимущество данного способа заключается в том, что один и тот же клип может использоваться на рабочем поле для воспроизведения различных звуков. Имя звука берется из имени копии клипа, а не из переменной ActionScript, что делает такой клип более универсальным.
Анимация начинается после перехода клипа к следующему кадру. В конце анимации клип возвращается к первому кадру, а находящаяся в нем команда stop () остановит его повторное воспроизведение.
В случае отдельных звуков одна и та же кнопка находится во всех кадрax, что дает пользователю возможность запустить воспроизведение нового звука даже во время воспроизведения анимации клипа.
Клипы для басов и отдельных звуков аналогичны. Основное их различие состоит в том, что первый звук должен периодически повторяться. Для этого в команду start требуется добавить два параметра: смещение от начала звука и количество циклов. В нашем случае смешение не нужно следовательно, оставим его значение равным 0. Периодическое повторение звука необходимо, поэтому соответствующий параметр должен иметь очень большое значение.

on (press) {
// Проигрываем звук по названию клипа.
bassloop = new Sound();
bassloop.attachSound(this._name);
bassloop.start(0,9999);
// Начинаем анимацию.
gotoAndPlay(2);
}

Еще одно отличие между отдельными звуками и басами заключается в том, что цикл басов можно отключить. Для этого кнопке переключателя цикла басов начиная с кадра 2 необходимо назначить другой сценарий. Сценарий прекратит воспроизведение звука и вернет ролик к кадру 1.

on (press) {
// Останавливаем проигрывание звука,
bassloop = new Sound();
bassloop.stop(this._name);
// Прекращаем анимацию.
gotoAndStop(1);
}

Сценарии кнопки для цикла барабанного боя немного сложнее. Прежде чем начинать воспроизведение одного такого цикла, необходимо убедиться в том, что другие циклы этой группы отключены. Сценарий проверяет звуки, начиная с "drum loop 1" и заканчивая "drum loop 6", и отключает каждый из них. Он также задает возврат каждого клипа переключателя к кадру 1, чтобы остановить анимацию. После этого запускается воспроизведение выбранного цикла.

on (press) {
// Останавливаем любой другой цикл барабанного боя.
drumloop = new Sound();
for(i=l;i<=6;i++) {
_root["drum loop"+i].gotoAndStop(1);
drumloop.stop("drum loop"+i); }
// Начинаем проигрывать выбранный звук
drumloop.attachSoundlthis._nane);
drumloop.start(0, 9999);
// Воспроизводим анимацию.
gotoAndPlay(2);
}

Другой код кнопки цикла барабанного боя аналогичен коду цикла басов. Он прекращает воспроизведение звука и возвращает клип обратно к кадру 1.

on (press) {
// Останавливаем проигрывание звука
drumloop = new Sound();
drumloop.stop(this._name);
// Останавливаем анимацию.
gotoAndStop(1);
}

К сведению

He забудьте присвоить каждой из 18 кнопок уникальное имя и сопоставить это имя с именем соответствующего звука в библиотеке. Кроме того,название звука необходимо задать в диалоговом окне Symbol Linkage Properties (рис. 7.9).
То, какой будет анимация каждого типа кнопки, решаете вы. В нашем примере кнопки барабанного боя мигают, изменяя свой цвет с белого на черный и обратно, кнопки басов и отдельных звуков увеличиваются. Чтобы обеспечить непрерывное воспроизведение, в последний кадр циклов барабанного боя и басов необходимо вставить команду gotoAndPlay (2). Клипы отдельных звуков после окончания своего воспроизведения должны возвращаться к кадру 1. Первый кадр этих звуков должен содержать команду stop О для того, чтобы их воспроизведение запускалось при первой загрузке ролика.

Другие возможности

Вы можете легко заменить имеющиеся звуки любыми другими. Просто удалите старые звуки из библиотеки и импортируйте на их место ваши собственные. Не забудьте произвести настройку диалогового окна Symbol Linkage Properties.
Вы также имеете возможность изменять количество звуков, например, уменьшать количество циклов барабанного боя и увеличивать количество отдельных звуков. Звуков может быть сколько угодно, главное, чтобы имена копий клипов совпадали с именами соответствующих звуков библиотеки.
Ничто не мешает вам изменить анимацию любого переключателя, Обладая достаточным количеством времени, вы можете отказаться от идеи повторно используемых клипов и создать свой клип для каждого переключателя. Но имейте в виду, что это усложнит вашу задачу, если вы захотите потом как-то еще изменить ролик.


Танцующая лиса

Исходный файл: Dance.fla

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

Рисунок 7.10 Показан фрагмент исходного файла. Лиса находится в процессе танца

Задача проекта

У этой программы есть два режима: запись и воспроизведение. Сначала пользователь использует режим записи и контролирует поведение лисы в режиме реального времени. Он может включить в танец одно из трех разных движений. В перерывах между выбранными движениями лиса исполняет основной танец.
Для завершения записи пользователь может нажать кнопку Done и вернуться в главное меню. Воспроизведение включается кнопкой Playback, после чего в точности воспроизводится записанная последовательность.

Подход

Центральным объектом этой программы является клип "dance". Он содержит всю последовательность танца лисы. Вы можете управлять лисой, перемещаясь к кадру, с которого начинается последовательность, составляющая данное танцевальное па.
Первым делом программа отмечает начало процесса записи. При нажатии кнопки программа фиксирует время нажатия и название движения. Информация помешается в массив объектов следующего формата: {время: значение, движение: значение}.
В начале процесса воспроизведения также отмечается текущее время. Затем программа все время проверяет, не пора ли лисе совершить первое из записанных движений, то, которое является первым элементом массива. Когда этот момент времени проходит, начинается ожидание второго момента времени, и т.д. Специальное танцевальное движение stop используется, чтобы обозначить окончание времени записи. Когда воспроизведение доходит до команды stop, ролик возвращается в главное меню.

Подготовка ролика

Мы должны сделать клип "dance" правильно. В исходном файле он представляет последовательность из 20 кадров, которая разбита на четыре части по 5 кадров. Каждая часть начинается с кадра, имеющего метку, например "dance0". Последний кадр в каждой последовательности не i держит изображения, но содержит команду gotoAndPlay("dance0") Таким образом, когда данная последовательность движений заканчивается, лиса возвращается к повторению последовательности dance0 (основное движение танца). Остальные три метки кадров называются "dance1", "dance2" и "dance3".

Последний кадр каждой танцевальной последовательности содержит только сценарий. Это сделано потому, что, когда выполняется команда gotoAndPlay (), содержимое кадра не отображается.

Основная временная шкала ролика содержит три кадра. Первый кадр помечен как "menu" (меню) и содержит команду stop(). Второй кадр имеет метку "record"(запись) и третий — "р1ауЬаск" (воспроизведение). Ниже мы рассмотрим код для этих трех кадров.
В кадре "menu" содержится две кнопки: Record и Playback. Я использовал один символ из библиотеки как образец для создания кнопок, но поместил на них различный текст. Каждая из этих кнопок совершает переход на соответствующий кадр.
В кадре "record" содержится четыре кнопки. Три из них включают в танец соответствующее движение, и четвертая прерывает процесс записи.
Наконец, кадр "playback" содержит единственную кнопку, останавливающую воспроизведение.

Создание кода

Рассмотрим сценарий кадра "record". Он начинается с инициализации массива и определения времени начала записи.

// Определяем массив.
danceArray = new Array();
// Считываем текущее время.
startTime = getTimer();

Функция danceButton вызывается одной из трех кнопок, расположенных внизу экрана. Они определяют время и название танцевального движения и помещают эту информацию в массив. Они также дают команду клипу "fox" (его библиотечное имя - "dance") к исполнению движения.

// Пользователь нажимает одну из "танцевальных" кнопок,
function danceButton(moveName) {
// Промежуток времени, прошедший с начала проигрывания.
thisTime = getTimer() - startTime;
// Помещаем временной интервал и название движения в массив.
danceArray.push({time: thisTime, move: moveName});
// Показываем движение,
fox.gotoAndPlay(moveName);
}

Когда пользователь нажмет кнопку Done, движение "stop" будет помещено в массив и ролик перейдет к кадру "menu".

// Нажимаем кнопку Done.
function stopRecordO {
// Вычисляем временной интервал.
thisTime = getTimerO - startTime;
// Добавляем в массив.
danceArray.push({time: thisTime, move: "stop"});
// Возвращаемся в главное меню.
gotoAndStop("menu");
}

Рассмотрим сценарий кадра "playback". Он начинается с определения времени начала воспроизведения и присваивания переменной dance-step значения 0. Эта переменная содержит номер следующего в очереди танцевального па.

// Определяем время.
startTime = getTimer();
// Начинаем с шага 0.
danceStep =0;

Клип "actions" вызывает функцию danceFrame, которая проверяет состояние последовательности танцевальных движений. Она вычисляет текущее время и сравнивает его со временем запуска следующего движения.
Когда это время наступает, функция проверяет, не является ли это движение командой stop. Если это так, то последовательность завершается. В противном случае клип "fox" переходит на соответствующий кадр, и переменная danceStер увеличивает свое значение на единицу.

// Вызывается при каждом обращении к кадру
// из клипа "actions".
function danceFrame() {
// Вычисляем время.
thisTime = getTimer() - startTime;
// Проверяем момент запуска следующего движения, if (thisTime >= danceArray[danceStep].time) {
// Определяем движение.
move = danceArray [danceStep] .move;
// Если это "stop", возвращаемся в кадр "menu",
if (move == "stop") {
gotoAndstop("menu");
} else {
// В противном случае отображаем движение танца.
fox.gotoAndPlay(move);
// Увеличиваем переменную.
danceStep++;
}
}
}

К сведению

Три кнопки в кадре "record", инициирующие танец, должны содержать сценарии для вызова функции danceButton. Вот пример для одной из кнопок:

on (press) {
danceButton("dance1");
}

В кнопке Done должен содержаться сценарий для вызова функции stopRecord.

on (press) {
stopRecord();
}

Клип "actions" в кадре "playback" содержит код, вызывающий функцию danceFrame при каждом обращении к этому кадру.

onClipEvent(enterFrame) {
_root.danceFrame();
}

Следует также назначить команду gotoAndstop каждой из кнопок главного меню. В первый кадр главной временной шкалы поместите команду stop(), чтобы остановить анимацию в начальный момент времени.

Другие возможности

В файле примера лиса, выполнив один раз выбранное пользователем движение, возвращается к основному танцу. Вы можете изменить программу таким образом, чтобы лиса повторяла выбранное движение до тех пор, пока пользователь не выберет новое. Этого можно достичь возвращением каждой последовательности кадров, отвечающей за определенное движение, к своей собственной метке вместо "danceO". В таком случае вам может понадобиться отдельная кнопка в кадре "record" для возвращения лисы к ее основному танцу.