ActionScript.org Flash, Flex and ActionScript Resources - http://www.actionscript.org/resources
Actionscript Powered Movement
http://www.actionscript.org/resources/articles/94/1/Actionscript-Powered-Movement/Page1.html
Jesse Stratford
Jesse lives and works in Melbourne Australia. He is the Cofounder of http://ActionScript.org. A Flash enthusiast, teacher, author, freelancer and speaker Jesse's main focus nowadays is managing http://ActionScript.org, but he enjoys participating actively in community and the wider Flash scene when he has time. 
By Jesse Stratford
Published on September 9, 2005
 
Tutorial details:
Written by: Jesse Stratford
Time: 30 - 45 minutes
Difficulty Level: Intermediate
Requirements: Flash 4, 5 or higher.
Topics Covered: How to control objects completely via actionscript or via a mix of user interaction and actionscript.
Assumed knowledge: Instances, paths, drag 'n drop, getProperty(), setProperty(), looping MCs, random().

Page 1 of 5
Tutorial details:
Written by: Jesse Stratford
Time: 30 - 45 minutes
Difficulty Level: Intermediate
Requirements: Flash 4, 5 or higher.
Topics Covered: How to control objects completely via actionscript or via a mix of user interaction and actionscript.
Assumed knowledge: Instances, paths, drag 'n drop, getProperty(), setProperty(), looping MCs, random().

Download the source for the above movie here. (Zipped, PC Flash 5 file).

Believe it or not I get enough questions about making smooth actionscript based tweens to dynamic X and Y positions, and/or random tweens to dynamic X and Y positions, that I've decided to write a tutorial. This tutorial will cover how to make an object move smoothly to a specified place on the stage using Actionscript. This place can be specified by the user clicking, or entering numbers, or can be generated randomly. Let's take a look shall we?

The primary application of this kind of stuff is in games and navigations. Then again I say that about most Actionscript. I've only ever used it in games but I'm sure it can be used in navigations also, somehow :o) Above I've an example of how we can make an object move smoothly and randomly, and later I will show you how we can make it move smoothly to a user-specified position. The best part about these two examples is that they both use the same code (almost) and it's very straight forward.

OK, say you have an object on the stage and you want to move it around randomly. Those of you who are a bit more experienced or creative may also realize that this will require generating random X and Y positions (_x and _y). What most people fall down on is how on Earth to make the animation smooth. We don't want our object to just jump from one _x, _y tuple (a tuple is a group of terms or variables) to another, we want it to animate there. This is deceptively simple also, once you see it done. This tutorial will outline a few methods of achieving the smooth movement effect.

Page 2 of 5
The steps I use are as follows. We'll start with a random movement example:
  1. Where are we moving to? We need two numbers: our target _x and _y. These I generate using the Math.random() method.
  2. Where are we coming from? We need to know where our target is in relation to our current position. This we determine using getProperty.
  3. What's the distance between our target and our current position? This we determine with a simple mathematical equation, since our values are numbers (in terms of _x and _y).
  4. How many steps do we want to take to get there? This is an arbitrary value which will control how fast / smooth your animation is. If you wanted to do it in two steps, it will obviously just jump from one place to another. In my examples I've used 20 steps as it makes for a nice smooth, yet relatively fast tween.
  5. Now we know where we're going to and coming from, how far that is, and how many 'steps' it's going to take. The next thing we need to know is... that's right, how far we should move per step. Again this is just simple maths. If I want to move 20 meters in 20 steps, each step must be about 1 meter long right? Same principle applies here.
  6. "Are we there yet?". Yes, even computers ask annoying questions. To determine if we're there yet I use a counter variable which counts how many steps we've taken. If we're doing 20 and we've taken 18, we're not there! (Are we in India yet? :o)

Sounds simple huh? I think most of you could go off an make your own working example now, but the next problem people face is the syntax because it does get a bit ugly the way some people do it. I've kept it as clean as possible.

Now that we know the logic, let's go back to our example. Grab the source for the movie above. As always, if you can't open my source you're going to have to build it yourself. Those of you with the source can skip this bit. Those without please construct the following:

  • A MC on the main stage with an instance name of 'circle'.
  • A three frame MC (on the main stage) with an instance name of 'controller'.
Frame 1 has the following actions:
[as]loops = 0;
_root.target_x = Math.random()*450;
_root.target_y = Math.random()*300;
_root.xdiv = (_root.target_x-_root.circle._x)/20;
_root.ydiv = (_root.target_y-_root.circle._y)/20;
[/as]
Frame 2 has the following actions:
[as]loops++;
_root.circle._x += _root.xdiv;
_root.circle._y += _root.ydiv;[/as]
Frame 3 has the following actions:
[as]loops++;
_root.circle._x += _root.xdiv;
_root.circle._y += _root.ydiv;
if (loops<20) {
gotoAndPlay(2);
} else {
gotoAndPlay(1);
}[/as]

That is all.

Page 3 of 5

Before we go any further, let me explain why I'm using a looping movieclip. Those of you using Flash 4 don't have many options really. In Flash 5 we could use an enterFrame clip event but there isn't any clean way of stopping a loop of that form, meaning when you want your ball to stop, you're going to have to use another conditional and you'll be using some additional overhead for each new frame your movie hits. Those of you using Flash MX who have read my Intervals tutorial might see this is another great application for Intervals. I'm not using them here though because showing this method makes the tutorial more universal, and you're all smart enough cookies to make the necessary changes if you decide to use Intervals, I'm sure.

OK, now you all have a working source file, so let's take a look at how it works. All the script is in the controller clip so we'll just go frame by frame through that:

What it does and how (line by line):

Frame 1:

[as]loops = 0;
_root.target_x = Math.random()*450;
_root.target_y = Math.random()*300;
_root.xdiv = (_root.target_x-_root.circle._x)/20;
_root.ydiv = (_root.target_y-_root.circle._y)/20;
[/as]
  1. Sets our counter variable, loops, to zero. This happens at the start of each new random positioning, but not during the tween itself.
  2. Variable target_x, the X position (_x) to which we intend to move, equals a random number up to 450 plus 50. This will vary depending on the dimensions of your movie and how far you want the clip to move.
  3. As above, for Y position.
  4. Variable xdiv equals our target _x minus our current _x, divided by 20. This is the distance we will move our object by each frame, to achieve a smooth tween. If you want to change the number of steps from 20 you may, but you must change all 20's to your other digit.
  5. As above for _y.

Going back to our rules for random movement, we've now established the fundamentals. We know where we are, where we're going, how many steps it's going to take, and how big each step will be. Now it's time to start stepping! That's where frames 2 and 3 come in.

Frame 2:

[as]loops++;
_root.circle._x += _root.xdiv;
_root.circle._y += _root.ydiv;
[/as]
  1. Increments variable loops by 1, to show that we have taken one more step.
  2. Sets the _x of our target clip to it's current _x plus the established step distance. Note that the step distance may well be a negative number if we're moving right to left, or from the bottom to the top of the screen. This wont matter though because you can add a negative number using the plus operator and it's still a valid operation. Eg. 2 + (-1) = 1.
  3. As above for _y.

So now our object has moved a few pixels in the x and y directions. Basically we just have to keep moving it until it reaches its target. We determine if it's yet reached its target in Frame 3. Note that the first 3 lines of Frame 3 are the same as those in Frame 2. This is so we get some movement every frame, and it makes our tween more smooth.

Frame 3:

[as]loops++;
_root.circle._x += _root.xdiv;
_root.circle._y += _root.ydiv;
if (loops<20) {
gotoAndPlay(2);
} else {
gotoAndPlay(1);
}
[/as]
  1. As in Frame 2.
  2. As in Frame 2
  3. As in Frame 2
  4. Conditional statement. Test if our counter variable, loops, is still less than 20. "Are we there yet?" If loops is less than 20, we're not there yet, so we;
  5. Loop back to frame 2 and step again.
  6. Otherwise we;
  7. Go back to Frame 1.

And of course, in frame 1, we generate another random target and the whole process starts over!.

"That's all very well Mr. Jesse, but I don't want to just move a ball randomly around the screen. I have this scenario where I want a user to input a location (via clicking there or entering values in a text field) and then I want the object to move to that location! Can you help me too?"

Surely can. Let's take a look, over the page.


Page 4 of 5

Click anywhere on the stage below and watch it happen.

Grab the source for this one here. (Zipped, PC Flash 5 file).

In the example above, our obedient little clip moves where-ever we tell it. And it's smart too, if we tell it to move somewhere else while it's still moving, it does just that, but it doesn't get confused with how many steps it's taken already. Clever little circle! Let's take a look at the code.

This one is handled by the same mechanism as the random mover. The differences here include:

  1. Our target isn't random any more; it's supplied by the user.
  2. Once it gets to where it's going, it stops until the user tells it to go somewhere else.

So, instead of having a random() function generate our target _x and _y, we read them in when the user clicks somewhere. I've done this with an invisible draggable button with the following code:

[as]on (release) {
_root.target_x = _root._xmouse;
_root.target_y = _root._ymouse;
_root.xdiv = (_root.target_x-_root.circle._x)/20;
_root.ydiv = (_root.target_y-_root.circle._y)/20;
if (_root.running == true) {
_root.controller.loops = 0;
}
_root.controller.gotoAndPlay(2);
}
[/as]

Notice that this button takes the place of our Frame 1 in the random mover example. Let's examine the code.

What it does and how (line by line):

  1. Standard button 'on' command.
  2. Variable target_x equals the _x of the mouse when clicked.
  3. As above for _y.
  4. Variable xdiv equals the difference between the current position and the target, divided by 20, just like in our previous example.
  5. As above for ydiv.
  6. If variable running is True (we'll talk about this variable later);
  7. Variable loops equals zero. So now we must take 20 more steps... Like I say, we'll talk about this later.
  8. Tell 'controller' to go to and play frame 2.

This last line, begins our controller clip looping. The controller clip in this example is very much like that of the previous example; it goes ahead and increments the _x and _y until we've taken the right number of steps. However, we have to include some extra code for this scenario: What if the user clicks one place, and before our movie clip gets there, clicks another? Well our obedient little clip wants to go to the latest place, but it's already taken maybe 5 steps and it's been told to only take 20 steps. So it has 15 steps left, but each step is 1/20th the distance to the target. The result? It wont reach the second target. This is where the extra code comes in.

The variable running is true while our controller clip is looping. Once the looping is finished, it's set back to false. So if someone clicks this invisible button while the controller is looping (while the circle is moving), we must set the number of moves available back to 20 so as not to confuse our little circle. This is the reason for the code on the button which states:

[as]if (_root.running == true) {
_root.controller.loops = 0;
}
[/as] So now we can get back to the fatController. His structure has changed slightly from our Random example. We'll examine that over the page.

Page 5 of 5

What it does and how (line by line):

Frame 1:
[as]stop();
loops = 0;
_root.running = false;
[/as]
  1. Stop all actions. Yup, he's still a lazy fatController.
  2. Variable loops equals 0. This sets the number of moves to do back to 20.
  3. Variable running is false, since this clip is stopped and thus is not telling our circle to do anything.
Frame 2:
[as]_root.running = true;
loops++;
_root.circle._x += _root.xdiv;
_root.circle._y += _root.ydiv;
[/as]
  1. Variable running is now true because we are back to telling the circle to do stuff.
  2. Variable loops increments, since we're about to take one step.
  3. Sets the _x of our 'circle' to it's current _x plus one step's value.
  4. As above for _y.

Frame 3:

[as]loops++;
_root.circle._x += _root.xdiv;
_root.circle._y += _root.ydiv;
if (loops < 20) {
gotoAndPlay(2);
} else {
gotoAndStop(1);
}
[/as]
  1. Increment loops variable.
  2. Sets the _x of our 'circle' to it's current _x plus one step's value.
  3. As above for _y.
  4. If variable loops is less than 20, ("Are we there yet!?");
  5. Loops less than 20, we're not there yet, loop to frame 2 and play.
  6. Otherwise, loops must be greater than or equal to 20, so we're there!;
  7. Go back to frame 1 of the fatController.

So frames 2 and 3 loop between each other until we reach our chosen destination, at which point they jump back to frame 1 and the clip stops.

And if the user clicks while it's in motion? Well since running == true, it sets the number of moves back to 20, sets the xdiv and ydiv variables to their new values and off it goes again! Smart users could implement this technique in a Mouse Chaser with Delay sort of scenario. Just have a looping MC which continually gets the mouse _x and _y and sets them as the target for the clip... But that's for another tutorial. Cheers!

Jesse Stratford [email:jessestratford@actionscript.org] is the Co-Master of ActionScript.org and a freelance Flash developer and teacher. He is based in Australia and enjoys all things Flash.

NB: If you have comments or feedback please feel free to email me, but please do not email me Flash questions; the forums are provided for that purpose and you will get a faster answer by posting you question there.

If you have found this tutorial helpful, I hope that you will take 30 seconds to visit The Hunger Site where, with just one click you can make a free donation of food to a starving person in a third-world country. We do not benefit financially from this action; it is purely an act of charity.
This tutorial is protected by International Intellectual Property Rights laws and may not be reproduced or redistributed in full or part, without the prior written consent of the author. Unauthorized reproduction of this tutorial or its contents may result in prosecution. I've worked hard on this tutorial, please don't steal it.