hanan essam
hanan essam

Reputation: 1

Restore dragged movieclips to their original position as they are dragged outside the stage in action script 3

I am creating a drag and drop the game for kids and I realized that when the kid drags a movie clip by mistake outside the stage the movie clip hangs where it is dragged onto and doesn't return back to its original position or it overlaps over other movie clips.

Thanks in advance

the code I am basically using is:

     * square_mc.addEventListener(MouseEvent.MOUSE_DOWN, pickUp2);
     square_mc.addEventListener(MouseEvent.MOUSE_UP, dropIt2);
     function pickUp2(event: MouseEvent): void {

    square_mc.startDrag(true);
   event.target.parent.addChild(event.target);
   startX = event.currentTarget.x;
   startY = event.currentTarget.y;
}
    function dropIt2(event: MouseEvent): void {
    square_mc.stopDrag();
     var myTargetName:String = "target" + event.target.name;
     var myTarget:DisplayObject = getChildByName(myTargetName);
    if (event.target.dropTarget != null && event.target.dropTarget.parent == 
        myTarget){

    event.target.removeEventListener(MouseEvent.MOUSE_DOWN, pickUp2);
    event.target.removeEventListener(MouseEvent.MOUSE_UP, dropIt2);
    event.target.buttonMode = false;
    event.target.x = myTarget.x;
    event.target.y = myTarget.y
} else {

    event.target.x = startX;
    event.target.y = startY;

    }
 }*

Upvotes: 0

Views: 114

Answers (1)

Nbooo
Nbooo

Reputation: 865

What you need to do is to preserve the initial position of the clip somewhere and then use it. Basic algorithm I can think of can look as follows: 1 - player starts dragging a clip, init position is saved 2 - player releases the clip. Two outcomes are possible: (a): the clip is on the right position or (b): it is misplaced. In case (b) you just need to assign initial coordinates back to the clip.

Very simple example:

private const initialCoords: Dictionary = new Dictionary();

private function saveInitialCoords(clip: DisplayObject): void {
    initialCoords[clip] = new Point(clip.x, clip.y);
}

private funciton retreiveInitialCoords(clip: DisplayObject): Point {
    return initialCoords[clip]; // it would return null if there is no coords
}

UPD: As it was pointed by @kaarto my answer might be irrelevant. If the issue is to keep the dragging movieclip within some bounds I usually use something like this:

private var currentTarget: DisplayObject; // clip we're dragging currently
private var areaBounds: Rectangle = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight); // you might want to ensure stage is not null.

private function startDrag(e: MouseEvent): void {
  // I'll drop all checks here. Normally you want to ensure that currentTarget is null or return it to initial position otherwise
  currentTarget = e.currentTarget as DisplayObject;
  saveInitialCoords(currentTarget);
  addEventListener(MouseEvent.MOUSE_MOVE, checkAreaBounds);
}

private funciton stopDrag(e: MouseEvent): void {
  // some checks were dropped.
  if (clipIsOnDesiredPlace(currentTarget)) { 
    // do something
  } else {
    const initialCoords: Point = retreiveInitialCoords(currentTarget);
    currentTarget.x = initialCoords.x;
    currentTarget.y = initialCoords.y;
  }
  currentTarget = null;
  removeEventListener(MouseEvent.MOUSE_MOVE, checkAreaBounds);
}

private funciton checkAreaBounds(e: MouseEvent): void {
  // you might need to convert your coords localToGlobal depending on your hierarchy
  // this function gets called constantly while mouse is moving. So your clip won't leave areaBounds 
  var newX: Number = e.stageX;
  var newY: Number = e.stageY;

  if (currentTarget) {
    if (newX < areaBounds.x) newX = areaBounds.x;
    if (newY < areaBounds.y) newY = areaBounds.y;
    if (newX + currentTarget.width > areaBounds.x + areaBounds.width) newX = areaBounds.x + areaBounds.width - currentTarget.width;
    if (newY + currentTarget.height > areaBounds.y + areaBounds.heght) newY = areaBounds.y + areaBounds.height - currentTarget.height;


    currentTarget.x = newX;
    currentTarget.y = newY;
  }
} 
... somewhere ... 
// for each clip you're going to interact with:
for each (var c: DisplayObject in myDraggableClips) {
  c.addEventListener(MouseEvent.MOUSE_DOWN, startDrag);
  c.addEventListener(MouseEvent.MOUSE_UP, stopDrag);
}

Another option (if you don't want to limit the area with some bounds) is to use MouseEvent.RELEASE_OUTSIDE event and return a clip to it's initial position once it gets released:

stage.addEventListener(MouseEvent.RELEASE_OUTSIDE, onMouseReleaseOutside);

private function onMouseReleaseOutside(e:MouseEvent):void {
    // return clip to it's position.
}

More info you can find in documentation: https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/MouseEvent.html#RELEASE_OUTSIDE

Upvotes: 1

Related Questions