Monday, 11 April 2011

Drag and drop in AS3 part 3

This is an addition to part 2 of the Drag and drop tutorial. In part 2 I modified the original code, so that multiple objects could use the same startDrag() and stopDrag() methods using the ‘event.target’ property. Since, then I have also created a drag and drop puzzle tutorial which also use the same functionality.

In this tutorial I will create a simple matching game using three targets and three draggable objects. In the game you match the draggable objects to the responding targets.


Drag and drop in AS3 part 3

Step 1

Open a new AS3 file. Then select the Rectangle tool and draw three targets on the stage like below. Convert each of the targets into movie clips (F8) with the centre registration point selected and give them the instance names: hitTarget1, hitTarget2 and hitTarget3 accordingly.



Step 2

Select the Oval tool and draw the draggable objects like below. Convert each of the targets into movie clips (F8) with the centre registration point and give them the instance names: drop1, drop2 and drop3 accordingly.




Step 3

On the timeline insert a new layer called ‘AS’ then open the actions panel and enter the following code:

//Array to hold the target instances, the drop instances,
//and the start positions of the drop instances.
var hitArray:Array = new Array(hitTarget1,hitTarget2,hitTarget3);
var dropArray:Array = new Array(drop1,drop2,drop3);
var positionsArray:Array = new Array();


//This adds the mouse down and up listener to the drop instances
//and add the starting x and y positions of the drop instances
//into the array.
for (var i:int = 0; i < dropArray.length; i++) {
dropArray[i].buttonMode = true;
dropArray[i].addEventListener(MouseEvent.MOUSE_DOWN, mdown);
dropArray[i].addEventListener(MouseEvent.MOUSE_UP, mUp);

positionsArray.push({xPos:dropArray[i].x, yPos:dropArray[i].y});
}

//This drags the object that has been selected and moves it
//to the top of the display list. This means you can't drag
//this object underneath anything.
function mdown(e:MouseEvent):void {
e.currentTarget.startDrag();
setChildIndex(MovieClip(e.currentTarget), numChildren - 1);
}

//This stops the dragging of the selected object when the mouse is
//released. If the object is dropped on the corresponding target
//then it get set to the x and y position of the target. Otherwise
//it returns to the original position.
function mUp(e:MouseEvent):void {
var dropIndex:int = dropArray.indexOf(e.currentTarget);
var target:MovieClip = e.currentTarget as MovieClip;

target.stopDrag();

if (target.hitTestObject(hitArray[dropIndex])) {
target.x = hitArray[dropIndex].x;
target.y = hitArray[dropIndex].y;
}else{
target.x = positionsArray[dropIndex].xPos;
target.y = positionsArray[dropIndex].yPos;
}
}
Here are some extras to spice up this game. I have created a button to reset the drop objects when they are all on the respective targets.
reset.addEventListener(MouseEvent.CLICK, backObjects);

function backObjects(e:MouseEvent):void{
for(var i:int = 0; i < dropArray.length; i++){
if(dropArray[i].x == hitArray[i].x && dropArray[i].y == hitArray[i].y){
dropArray[i].x = positionsArray[i].xPos;
dropArray[i].y = positionsArray[i].yPos;
}
}
}

I have also added a scream sound effect when the drag object is on the correct target. You will need to import a sound effect into the library then right click on the audio file and select properties, check the export to Actionscript button and give it a class name. For more information on sounds in Actionscript 3, checkout some of my audio tutorials.
function playSound(SoundName:Class):void{
var sound = new SoundName();
var channel:SoundChannel = sound.play();
}

To play the sound effect, add the following line of code inside the If statement of the mUp function.
playSound(TheNameOfTheClass);

Step 4

Test your movie clip Ctrl + Enter. You should now have a simple matching game.



You can download the source files here.

36 comments:

Tony 15 February 2012 at 11:59  

Great tutorial. I can't get the reset button to work though.

iliketo 16 February 2012 at 02:31  

@Tony

Post your code.

Aranid 29 February 2012 at 23:06  

Very nice tutorial. may i ask how to modify the game like disabling the dragging of the drop object once they are in the right place, and also a function that will determine that all the objects are now on their respective places a counter sort of. Thank you so much for this great tutorial by the way.

iliketo 1 March 2012 at 03:06  

@Aranid

You can disable the drop object by removing the mouse down listener. As for the determining the objects are in their respective places, look at the backObjects() function. This should get you started.

Teacher 24 March 2012 at 08:34  

function mUp4(t:MouseEvent):void {
var dropIndex4:int = dropArray4.indexOf(t.currentTarget);
var target4:MovieClip = t.currentTarget as MovieClip;

target4.stopDrag();

if (target4.hitTestObject(hitArray4[dropIndex4])) {
target4.x = hitArray4[dropIndex4].x;
target4.y = hitArray4[dropIndex4].y;
this.playSound5(hdtb);
t.currentTarget.addEventListener(MouseEvent.MOUSE_DOWN, mdown4);
t.currentTarget.addEventListener(MouseEvent.MOUSE_UP, mUp4);

I changed code like this. And now when it is right place it doesnt move. But now when I push reset button I cant move the drag and drop objects... Can you help me?

iliketo 24 March 2012 at 11:14  

@teacher

make sure you have the correct reset code, and why have you re-added the mouse up and down listeners?

Teacher 24 March 2012 at 17:36  

Sorry, I sent you the wrong codes. I want to remove the mouse eventlistener. I sent codes again with reset button code...
function mUp(e:MouseEvent):void {
var dropIndex:int = dropArray.indexOf(e.currentTarget);
var target:MovieClip = e.currentTarget as MovieClip;

target.stopDrag();

if (target.hitTestObject(hitArray[dropIndex])) {
target.x = hitArray[dropIndex].x;
target.y = hitArray[dropIndex].y;
this.playSound(SoundName);
e.currentTarget.removeEventListener(MouseEvent.MOUSE_DOWN, mdown);
e.currentTarget.removeEventListener(MouseEvent.MOUSE_UP, mUp);
}else{
target.x = positionsArray[dropIndex].xPos;
target.y = positionsArray[dropIndex].yPos;
this.playSound(SoundName2);
}
}

reset.addEventListener(MouseEvent.CLICK, backObjects);

function backObjects(e:MouseEvent):void{
for(var i:int = 0; i < dropArray.length; i++){
if(dropArray[i].x == hitArray[i].x && dropArray[i].y == hitArray[i].y){
dropArray[i].x = positionsArray[i].xPos;
dropArray[i].y = positionsArray[i].yPos;
}
}
}

iliketo 26 March 2012 at 12:16  

@teacher

If you want to remove the mouse event listeners, you will need to re-add them when you press the reset button because the objects won't move as the mouse event listeners have been removed.

Teacher 30 March 2012 at 07:21  

Thanx a lot I solved the problem with your help... Now I want to change the sounds in every correct drop. Your codes have only one sound, I want to add multiple sounds and in every correct drop it will play a different sound. How can I do it? I know you will help me and I will be gratefull to you...

iliketo 31 March 2012 at 02:37  

@Teacher

You need to use the playSound() function. Make sure you have three different sounds in the library.

Teacher 31 March 2012 at 03:11  

I did it but it plays sounds together. I dont know how to write the array for the playSound. Can you write it? My code is below:
function playSound(SoundName:Class):void{
var sound = new SoundName();
var channel:SoundChannel = sound.play();
}

iliketo 1 April 2012 at 05:04  

@Teacher

You create a new array and add the functions inside it.

Teacher 1 April 2012 at 14:13  

I'm new in this as3 and also flash. What I succeed is with your codes. So I don't know how to write the array. I looked lots of examples but I didn't add different sounds.. Can you write an array example for playing different sounds? If you write the array, I'll be gratefull to you again...

iliketo 2 April 2012 at 11:19  

@Teacher

Please look at the code above for an example of how to create a new Array.

If I provide you with the code you won't learn anything - You must try yourself.

Raphaelle 12 April 2012 at 19:25  

This is a great tutorial, anyway i have an error if i do this in an as file. hope u can help me. thanks.

iliketo 13 April 2012 at 13:30  

@Raphelle,

It’s difficult for me to help if you don’t post the error message.

qieda 24 May 2012 at 06:24  

Thank you very much. It works!

Tootsies Toots 21 September 2012 at 01:33  

Hi.

This is a great tryout for a drag and drop game. I actually like this hitTarget method. Anyway I have a problem unsettled. I created 2 games of it, the 1st one in frame 1, the 2nd in frame 2. There's a button in frame 1 that ofcourse, leads to the 2nd frame.

Now, when playing the 1st game, everything was fine. I clicked on the next button, the 2nd game appears. BUT... the things that I dragged in the 1st game were still visible in the 2nd game. How to fix this?

iliketo 21 September 2012 at 12:05  

@Tootsie,

You need to set the content on frame 1 to invisible when you go to frame 2. Use the visible = false.

Tootsies Toots 22 September 2012 at 02:38  

@iliketo

Where do I put the code? In the action layer of 1st frame or 2nd frame?

iliketo 23 September 2012 at 09:41  

@Tootsie,

Are you joking! You shouldn’t be using Flash if you don’t know something this simple.

DonKho 1 October 2012 at 20:48  

thanks for the tutorial bro.
it helps a lot.

Pbrem 30 October 2012 at 07:40  

I have a question, I'm currently creating a drag and drop in Flash CS6, I have a script like this one that's been used before.

Now my problem is that i need to be able to let one drag object to be capable of being correct in multiple hitarea's. I can't seem to be able to use the same instance name multiple times in order to make it function so I'm clueless.

Any way you could help? thanks

iliketo 4 November 2012 at 03:20  

@Pbrem,

It should work. Can you please post up your code?

Pbrem 6 November 2012 at 00:44  

@iliketo

var dragArray:Array = [drag_rolvolwassen, drag_rolouderlijk, drag_rolkinderlijk];
var matchArray:Array = [drop_rolvolwassen, drop_rolouderlijk, drop_rolkinderlijk];
var volArray:Array = [0, 0, 0, 0, 0, 0, 0, 0,0 ,0 ,0 ,0]


I wont lie that I have little to no experience of AS but I'm currently set to the task to solve it on my own here with my internship. when I apply one of the given instance names to multiple symbols on the stage (do mind that these are all different symbols) the script will only respond to one instance at a time rather than every symbol i've given the instance name.

iliketo 6 November 2012 at 12:36  

@Pbrem

Where's the rest of the code? Can you clarify exactly you are trying to achieve.

Pbrem 7 November 2012 at 00:58  

I'm not sure if I should post the entire code because it's rather big. the code also includes a check button to see if you've placed the drags on the right drop and has a dynamic text block showing something when you've got it all right or wrong

Basicly what I want to achieve is; there's like 3 images in the scene. they all have 4 seperate drop areas next to them. and there are 12 drags in the stage that contain words to match the images personality wise. so yeah there are 4 words for each image. so what I want is that if you drag 1 of the 4 correct words to one of the 4 hitareas of an image, that it doesn't matter which hitarea you choose as it's going to be correct in any of the 4 hitarea's as long as it's placed near the right image.

so I need to know how you can make one hitarea reqognize multiple drags being correct when placed on.

iliketo 7 November 2012 at 13:09  

@Pbrem,

Try Using the 'Logical AND operator' inside the if statement to detect multiple drags.

For example:

if ( target.hitTestObject(hitObject1) && target.hitTestObject(hitObject2) ){

}

Pbrem 8 November 2012 at 01:22  

Hmmm I made some attempts with the script line you mentioned but it seems I'd have to modify the entire thing or have to add allot of these if's.

But I did find out a bit more about the script itself as it basicly tries to match the var's that I copied in my earlier posts. the matchArray's and such. From what I'm seeing, I need to find a way to add multiple targets to one bracket, or add something in the lines to make it ignore part of the instance name. because appearently it does know how to define the instance just by the name after 'drag_' and 'drop_' so I wonder if there's a way to add something in the instance name that makes me able to add something like _01 and _02, behind the 'rolvolwassen' for example while reqognizing them as the same definition in the script.

Do you have any suggestions or idea's if that is possible?

PS: I hope any of this makes sense to begin with.

iliketo 8 November 2012 at 12:55  

@Pbrem,

modify the entire thing or have to add allot of these if's.

Use a For Loop.

Supha Issarang 2 March 2013 at 19:09  

How would I do if I want the object invisible after drop in the right target ?

iliketo 3 March 2013 at 12:18  

Supha,

Use the visible property.

Fatih Ggg 26 October 2013 at 04:41  

Hello it is a great tutorial, tahnx for all of them...
Your code plays only one sound can we add multiple sounds? If we can add con you show how can I add? I'm newbie in AS3

iliketo 26 October 2013 at 06:20  

@Fatih,

Look at the end of Step 3. You need to use the playSound() function. Make sure you have three different sounds in the library.

Fatih Ggg 29 October 2013 at 04:24  

I did it but always plays the same sound... What I want is we have three targets and I want to add 3 different right answer sound and three different wrong answer sound... How can I do it?
I tried to write a sound array bu I douldnt succeid it... Can yo help me?

iliketo 2 November 2013 at 02:32  

@Faith,

Obviously, if you have not modified the code it will play the same sound.

Look at how I created hitArray and dropArray, you replicate this for your sound arrays. Then in the mUp function you need to write code in the ‘if’ statement.


  COPYRIGHT © 2014 · ILIKE2FLASH · Theme by Ourblogtemplates

Back to TOP