Dragging a Movie Clip

You can handle dragging a movie clip using two different techniques: with the mouseMove event or with the startDrag/stopDrag methods . Although youll be using the former for the examples in this chapter, lets look at how to use the mouseMove event for dragging first. It will give you some experience in handling the mouseMove event and a deeper understanding of how events work.

Dragging with mouseMove

By manually handling the mouseMove event, you can update the movie clips position to match the mouse cursors each time the mouse moves. Its worth noting that this is the only way to drag more than one object at a time. You sometimes run into this when making a custom cursor out of a movie clip. The cursor needs to follow the mouse position around, but what if you want to drag something, too? One solution is to use mouseMove for the cursor, and leave the usual drag methods (startDrag/stopDrag) free for normal dragging. So its a nice little technique to have under your belt, even if you dont use it on regular basis.

The strategy is this: On the mouseDown event, you want to set up a mouseMove handler. This handler will just set the balls x and y positions to equal the current mouse position. On the mouseUp event, you remove that handler.

You can use the file you just created for mouse events, and change the code on frame 1 to this ( ch07_02.fla ):

 ball.onPress = function() {       ball.onMouseMove = drag; } ball.onRelease = function() {       delete ball.onMouseMove; } function drag() {       ball._x = _xmouse;       ball._y = _ymouse; } 

The onPress method causes the drag method to be called every time the mouse moves, and the onRelease method deletes that as a handler.

If you test this example, youll notice several problems. One is that the ball sometimes gets stuck to the mouse, even after you release the mouse. This is because the mouse refreshes its position at a much faster rate than the movie clip, which can move only once per frame. Thus the mouse can get ahead of the movie clip, and sometimes when the mouse button is released, the mouse cursor is outside the graphical area of the clip. If this is the case, onRelease will not register. Fixing this is as simple as adding the following method:

 ball.onReleaseOutside = function() {       delete ball.onMouseMove; } 

This causes the ball to be released when the mouse button is released, no matter where the mouse cursor is.

You might have also noticed one other problem with this setup. If you click on the edge of the ball and start dragging it, youll see that it suddenly jumps and centers itself on the mouse cursor. This is because youre setting the balls x and y positions to exactly equal to the mouse position. You could do some fancy footwork to get around that, finding the offset of the mouse to the ball when the mouse is pressed, and adding that to the balls position as you drag. Ill leave that as a project for you, if youre interested in pursuing it. But Im going to move on to the usual method of dragging a movie clip.

Dragging with startDrag/stopDrag

All movie clips have built-in methods called startDrag and stopDrag , which handle all of the functionality of the method I just described (in what was an educational detour , I hope), and then some. About the only drawback is that it allows for dragging only a single movie clip at a time.

The concept is pretty simple. In your press handler, you call startDrag . In the release handler, you call stopDrag . You still need to make an onReleaseOutside method.

startDrag can be called without any parameters. You can take the file youve been using for this chapters examples and change the code on frame 1 to this (in ch07_03.fla ):

 ball.onPress = function() {       ball.startDrag(); } ball.onRelease = function() {       ball.stopDrag(); } ball.onReleaseOutside = function() {       ball.stopDrag(); } 

Pretty simple, eh? Test this, and youll also notice that the snapping problem is gone. The ball will drag from whatever position you clicked on it. If you actually want it to snap to the center though, you can do so by passing true to the first parameter of startDrag :

 ball.startDrag(true); 

You can also limit the dragging to a rectangular area by passing in coordinates for the left, top, right, and bottom of the area you want to be able to drag in. Here is the full syntax for startDrag :

 startDrag(lockCenter, left, top, right, bottom) 

Combining dragging with motion code

At this point, you know pretty much everything about simple dragging and dropping in Flash. Unfortunately, in the process, youve reverted back to a static object that just kind of sits there unless youre dragging it. Lets add some velocity and maybe even some acceleration and bouncing.

You already have a nice setup for velocity, gravity, and bouncing in the ch06_05.fla file from the previous chapter. Thats a good starting point. It would seem logical to simply add your drag-and-drop code to that code. Lets try it. You should end up with something like this ( ch07_04.fla ):

 init(); function init() {       bounce = -0.7;       gravity = 0.5;       top = 0;       left = 0;       bottom = Stage.height;       right = Stage.width;       ball = attachMovie("ball", "ball", 0);       ball._x = Stage.width / 2;       ball._y = Stage.height / 2;       vx = Math.random() * 10 - 5;       vy = Math.random() * 10 - 5; }  ball.onPress = function()   {   ball.startDrag();   }   ball.onRelease = function()   {   ball.stopDrag();   }   ball.onReleaseOutside = function()   {   ball.stopDrag();   }  function onEnterFrame(Void):Void {       vy += gravity;       ball._x += vx;       ball._y += vy;       if (ball._x + ball._width / 2 > right)       {             ball._x = right - ball._width / 2;             vx *= bounce;       }       else if (ball._x - ball._width / 2 < left)       {             ball._x = left + ball._width / 2;             vx *= bounce;       }       if (ball._y + ball._height / 2 > bottom)       {             ball._y = bottom - ball._height / 2;             vy *= bounce;       }       else if (ball._y - ball._height / 2 < top)       {             ball._y = top + ball._height / 2;             vy *= bounce;       } } 

As you can see, all that youve added to the original code is the handlers for onPress , onRelease , and onReleaseOutside .

If you test this now, youll see the problem immediately when you start to drag. Yes, the dragging works, but the motion code is working at the same time. The result is the feeling that the ball is slipping out of your hand. You need some way of switching on or off the motion code, so that it doesnt happen while youre dragging. The simplest way to do this is to set a variable called dragging to true or false when you start or stop dragging. First, of course, you need to declare the variable in the init function:

 dragging = false; 

Then you set it in your onPress , onRelease , and onReleaseOutside handlers:

 ball.onPress = function() {  dragging = true;  ball.startDrag(); } ball.onRelease = function() {  dragging = false;  ball.stopDrag(); } ball.onReleaseOutside = function() {  dragging = false;  ball.stopDrag(); } 

Now, in your onEnterFrame method, you simply check the dragging variable. If its false , you can do all your normal stuff. You could phrase this something like this:

 if(dragging == false) 

But there is an even more concise way. The ! , or NOT operator, converts true to false and false to true . Thus, you can say:

 if(!dragging) 

This is read, If not dragging. . ., which means pretty much what it sounds like as an English phrase. (Its always great when your code becomes that readable!) So, your onEnterFrame function becomes this:

 function onEnterFrame(Void):Void {       if(!dragging)       {             vy += gravity;             ball._x += vx;             ball._y += vy;             if (ball._x + ball._width / 2 > right)             {                   ball._x = right - ball._width / 2;                   vx *= bounce;             }             else if (ball._x - ball._width / 2 < left)             {                   ball._x = left + ball._width / 2;                   vx *= bounce;             }             if (ball._y + ball._height / 2 > bottom)             {                   ball._y = bottom - ball._height / 2;                   vy *= bounce;             }             else if (ball._y - ball._height / 2 < top)             {                   ball._y = top + ball._height / 2;                   vy *= bounce;             }       } } 

When you test this, youll see that youre getting closer, but youre not quite there yet.

When you start dragging, all youre doing is dragging. When you drop the ball, the motion code resumes where it left off. The main problem now is that the velocity also resumes where it left off. This sometimes results in the ball flying off in some direction when you release it, which is pretty unnatural . You can easily fix that by just setting vx and vy to zero, either when you start dragging or when you stop. Either one works, as long as it is done before the motion code resumes. Lets put it in the start drag section:

 ball.onPress = function() {  vx = 0;   vy = 0;  dragging = true;       ball.startDrag(); } 

That takes care of the problem and leaves you with a fully functional drag-and-drop, with integrated velocity, acceleration, and bouncing. You can see the full code listing in ch07_05.fla .

Just one issue remains: When you drop the ball, it falls straight downno more x-axis motion. Although this is the correct behavior, its a bit boring. If you could actually throw the ball and have it fly off in whatever direction you threw it, that would be some heavy-duty interactivity. Well, thats exactly what youre going to do next .



Foundation ActionScript. Animation. Making Things Move
Foundation Actionscript 3.0 Animation: Making Things Move!
ISBN: 1590597915
EAN: 2147483647
Year: 2005
Pages: 137
Authors: Keith Peters

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net