Flash AS3 - Drag and drop multiple objects to multiple targets

前端 未结 2 1849
刺人心
刺人心 2021-01-26 10:32

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

2条回答
  •  隐瞒了意图╮
    2021-01-26 10:44

    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.

提交回复
热议问题