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

Исходный файл: 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 дает пользователю возможность перетаскивать части тела лисы в любое место экрана