I have multiple objects to drag to multiple targets. I have a code without error. I am using multiple functions. But I wonder if I pass the objects and the specific target with
Despite the fact Vesper's answer is already accepted, I think it to be far too brief and insufficient, on top of that it doesn't actually answer how to design a system where any number of objects could be dropped to any number of targets, without substantial changes to the code.
// Unlike the Object class, that allows String keys only
// the Dictionary class allows you to store and
// access data by the object instance.
var theValids:Dictionary = new Dictionary;
// We'll store the original (x,y) coordinates here.
var theOrigin:Point = new Point;
// The Sprite class is the superclass of MovieClip, furthermore,
// the startDrag method defined for Sprite class, so unless you
// create your own dragging code, you are bound to use Sprites,
// while you cannot drag SimpleButtons and TextFields this way.
// We'll store the current dragged object here.
var theObject:Sprite;
// This first argument is the object you want to be draggable.
// The "...targets:Array" means you can call this method with
// any number of arguments, the first one is mandatory, the
// rest will be passed in a form of Array (empty Array if you
// call this method with a single argument).
function setupDraggable(source:Sprite, ...targets:Array):void
{
// Make the object draggable.
source.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
source.mouseChildren = false;
source.mouseEnabled = true;
source.buttonMode = true;
// Keep the list of the object's targets so it can be
// retrieved later by the key of the object itself.
theValids[source] = targets;
}
// Ok, let's setup the objects and link them to their designated
// targets. The whole point of the rest of the code is to make
// this one part as simple as it possible: you just edit
// these lines to tell which one objects go where.
// This object can be dropped to a single target.
setupDraggable(obj_1 , target1);
// These objects can go to two targets each.
setupDraggable(obj_10, target1, target10);
setupDraggable(obj_2 , target2, target20);
// This one object can be dropped to any of targets.
setupDraggable(obj_20, target1, target10, target2, target20);
// The MOUSE_DOWN event handler.
function onDown(e:MouseEvent):void
{
// Get the reference to the object under the mouse.
theObject = e.currentTarget as Sprite;
// Keep the object's initial position.
theOrigin.x = theObject.x;
theOrigin.y = theObject.y;
// Put the dragged object on top of anything else.
// We are operating in the parent context of all these
// objects here so there's no need to address anObj.parent.
setChildIndex(theObject, numChildren - 1);
// Start dragging.
theObject.startDrag(true);
// Listen to the MOUSE_UP event, which could happen offstage
// and out of the dragged object, so the only reliable
// way is to listen it from the Stage. That's why we
// are keeping theObject reference as an additional
// variable, without relying on event's data.
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
}
// The MOUSE_UP event handler.
function onUp(e:MouseEvent):void
{
// Unsubscribe the MOUSE_UP event handler.
stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
// Stop the dragging process.
theObject.stopDrag();
// Let's assume there could be more than a single collision.
// We need to figure the one target that is closest.
var theTarget:DisplayObject;
var theDistance:int = 100000;
// Store the dragged object position so we can
// measure distances to the valid collisions, if any.
var thePlace:Point = theObject.localToGlobal(new Point);
// Now, the magic. Lets browse through the
// valid targets and see if there's a collision.
for each (var aTarget:DisplayObject in theValids[theObject])
{
if (theObject.hitTestObject(aTarget))
{
// Let's see if the current collision is closer
// to the dragged object, than the previous one
// (if any, that's what initial 100000 for).
var aPlace:Point = aTarget.localToGlobal(new Point);
var aDistance:int = Point.distance(aPlace, thePlace);
if (aDistance < theDistance)
{
theTarget = aTarget;
theDistance = aDistance;
}
}
}
// If there's at least one collision,
// this variable will not be empty.
if (theTarget)
{
// Make the object non-interactive.
theObject.removeEventListener(MouseEvent.MOUSE_DOWN, onDown);
theObject.mouseEnabled = false;
theObject.buttonMode = false;
// Glue the dragged object to the center of the target.
theObject.x = theTarget.x;
theObject.y = theTarget.y;
}
else
{
// If we're here, that means there was no valid collisions,
// lets return the object to its designated place.
theObject.x = theOrigin.x;
theObject.y = theOrigin.y;
}
// Clean-up. Remove the reference, the object is no longer
// being dragged, so you won't need to keep it.
theObject = null;
}
P.S. I didn't test it, but I think I put enough comments to explain the whole idea.