Итак, перед нами стоит задача, а точнее две:
1.) Перетаскивание большого количества (от нескольких штук до нескольких десятков или даже сотен) визуальных объектов (как правило, это MovieClip-ы и Sprite-ы) по сцене флеш-ролика.
2.) Проверка пересечения перетаскиваемых объектов с другими объектами на сцене флеш-ролика. При этом, если пересечение состоялось, то запускается одно действие (например, перетаскиваемый объект встаёт в координаты области пересечения), а если нет - другое (например, перетаскиваемый объект возвращается в первоначальные координаты).
В моём примере перетаскиваться будут три мувиклипа (да, я ленивый сукин сын). Эти MovieClip-ы будут называться весьма незатейливо: mc_1, mc_2 и mc_3 (да, у меня ещё и с фантазией очень плохо).
Для проверки пересечения создадим ещё два мувика: hit_mc_1 и hit_mc_2.
Всё это добро (пять мувиков) лежит внутри мувиклипа-контейнера по имени ... ТА-ДАМ! ... container.
Результат:
Переходим к коду. А код у нас будет следующим...
Код ActionScript 2.0:
var obj:Object = {mc_1:{startX:0, startY:0, hitAreaMc:"hit_mc_1"}, mc_2:{startX:0, startY:0, hitAreaMc:"hit_mc_1"}, mc_3:{startX:0, startY:0, hitAreaMc:"hit_mc_2"}};
var mc:MovieClip;
for (var prop in obj)
{
mc = MovieClip(container[prop]);
obj[prop].startX = mc._x;
obj[prop].startY = mc._y;
mc.onPress = onPressFunc;
mc.onRelease = onReleaseFunc;
}
function onPressFunc()
{
this.startDrag(true);
}
function onReleaseFunc()
{
var mc:MovieClip = MovieClip(this);
var mc_hit:MovieClip = MovieClip(container[obj[mc._name].hitAreaMc]);
mc.stopDrag();
if (mc_hit.hitTest(mc._x,mc._y,true))
{
mc._x = mc_hit._x;
mc._y = mc_hit._y;
}
else
{
mc._x = obj[mc._name].startX;
mc._y = obj[mc._name].startY;
}
}
Код ActionScript 3.0:
var obj:Object = {
mc_1:{startX:0, startY:0, hitAreaMc:"hit_mc_1"},
mc_2:{startX:0, startY:0, hitAreaMc:"hit_mc_1"},
mc_3:{startX:0, startY:0, hitAreaMc:"hit_mc_2"}
};
var mc:MovieClip;
for (var prop in obj)
{
mc = container.getChildByName(prop) as MovieClip;
obj[prop].startX = mc.x;
obj[prop].startY = mc.y;
mc.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownFunc);
mc.addEventListener(MouseEvent.MOUSE_UP, onMouseUpFunc);
}
function onMouseDownFunc(event:MouseEvent):void
{
var mc:MovieClip = event.target as MovieClip;
mc.startDrag(true, new Rectangle(0,0,550,400));
}
function onMouseUpFunc(event:MouseEvent):void
{
var mc:MovieClip = event.target as MovieClip;
var mc_hit:MovieClip = container.getChildByName(obj[mc.name].hitAreaMc) as MovieClip;
mc.stopDrag();
if (mc_hit.hitTestPoint(mc.x,mc.y,true))
{
mc.x = mc_hit.x;
mc.y = mc_hit.y;
}
else
{
mc.x = obj[mc.name].startX;
mc.y = obj[mc.name].startY;
}
}
Результат:
Вся соль в том, что все важные данные мы храним в ассоциативном массиве obj. И, вместо того, чтобы нудно прописывать код для каждого перетаскиваемого объекта, мы просто вносим необходимые данные в массив obj. Код получается более компактным и понятным. При этом, код в любой момент можно модифицировать под любые ваши задачи. Кстати, именно поэтому я и использую ассоциативный массив: его можно безболезненно изменить и в нём удобно хранить данные любого типа.
В нашем примере массив obj состоит из трёх элементов. Каждый элемент содержит набор свойств, описывающих поведение отдельного перетаскиваемого объекта. Например, следующий фрагмент:
mc_1:{startX:0, startY:0, hitAreaMc:"hit_mc_1"}
переводится примерно так:
мувиклип_mc_1:{координаты_по_оси_x:0, координаты_по_оси_y:0, целевой_мувиклип:"hit_mc_1"}
Естественно, если перед вами стоят иные задачи, то и список свойств будет иной. Моей же задачей было показать только принцип работы. Надеюсь, я справился :-)
Скачать исходники к данному уроку можно по следующей ссылке - скачать исходники (под Adobe Flash CS5).
Дополнение № 1. Добавляем плавности.
Знаю, некоторым в моём примере не хватает плавности при перемещении объектов в назначенные им координаты. Но это не проблема. Особенно, если морально-этические соображения позволяют вам использовать библиотеку TweenLite от GreenSock. Изменения в коде будут незначительными:
Код ActionScript 2.0:
import com.greensock.*;
var obj:Object = {mc_1:{startX:0, startY:0, hitAreaMc:"hit_mc_1"}, mc_2:{startX:0, startY:0, hitAreaMc:"hit_mc_1"}, mc_3:{startX:0, startY:0, hitAreaMc:"hit_mc_2"}};
var mc:MovieClip;
for (var prop in obj)
{
mc = MovieClip(container[prop]);
obj[prop].startX = mc._x;
obj[prop].startY = mc._y;
mc.onPress = onPressFunc;
mc.onRelease = onReleaseFunc;
}
function onPressFunc()
{
this.startDrag(true);
}
function onReleaseFunc()
{
var mc:MovieClip = MovieClip(this);
var mc_hit:MovieClip = MovieClip(container[obj[mc._name].hitAreaMc]);
mc.stopDrag();
if (mc_hit.hitTest(mc._x,mc._y,true))
{
TweenLite.to(mc, 0.4, {_x:mc_hit._x, _y:mc_hit._y});
}
else
{
TweenLite.to(mc, 0.4, {_x:obj[mc._name].startX, _y:obj[mc._name].startY});
}
}
Код ActionScript 3.0:
import com.greensock.*;
var obj:Object = {
mc_1:{startX:0,startY:0,hitAreaMc:"hit_mc_1"},
mc_2:{startX:0,startY:0,hitAreaMc:"hit_mc_1"},
mc_3:{startX:0,startY:0,hitAreaMc:"hit_mc_2"}
};
var mc:MovieClip;
for (var prop in obj)
{
mc = container.getChildByName(prop) as MovieClip;
obj[prop].startX = mc.x;
obj[prop].startY = mc.y;
mc.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownFunc);
mc.addEventListener(MouseEvent.MOUSE_UP, onMouseUpFunc);
}
function onMouseDownFunc(event:MouseEvent):void
{
var mc:MovieClip = event.target as MovieClip;
mc.startDrag(true, new Rectangle(0,0,550,400));
}
function onMouseUpFunc(event:MouseEvent):void
{
var mc:MovieClip = event.target as MovieClip;
var mc_hit:MovieClip = container.getChildByName(obj[mc.name].hitAreaMc) as MovieClip;
mc.stopDrag();
if (mc_hit.hitTestPoint(mc.x,mc.y,true))
{
TweenLite.to(mc, 0.4, {x:mc_hit.x, y:mc_hit.y});
}
else
{
TweenLite.to(mc, 0.4, {x:obj[mc.name].startX, y:obj[mc.name].startY});
}
}
Результат:
Как-то так.
Контейнер, в данном случае, это просто мувиклип, внутри которого сложены все другие объекты-мывиклипы. Этот мувиклип-контейнер имеет имя container. Вроде, логично.