Motion: Chapter 7 - Learning ActionScript 3.0

by Rich Shupe and Zevan Rosser

This excerpt is from Learning ActionScript 3.0. Learning ActionScript 3.0 gives you a solid foundation in the Flash language and demonstrates how you can use it for practical, everyday projects. The book does more than give you a handful of sample scripts, defining how ActionScript and Flash work. It gives you a clear look into essential topics such as logic, event handling, displaying content, migrating legacy projects to ActionScript 3.0, classes, and much more. Written for those new to the language, this book doesn't rely exclusively on prior knowledge of object-oriented programming (OOP). Instead, it helps you expand your skillset by first focusing on clear, concise examples in the timeline, evolving into OOP examples over time-allowing you to choose the programming approach with which you are most comfortable.

buy button

From your very first experiment to the umpteenth time you've performed a familiar task, moving assets with code can be a gratifying experience. In addition to creating more dynamic work by freeing yourself from the permanency of the timeline, there is something very immediate and pleasing about controlling the motion of a symbol instance purely with ActionScript.

Because programming motion can cover a large number of concepts, we've chosen a few as the main focus areas for this subject. In each area, we offer what we call simplified simulations—that is, we do not maintain that our examples accurately reflect real-world scenarios. We won't be accounting for every possible force that can act on an object in each sample file. On the contrary, we try to present approaches to each topic that are simple enough to integrate into your projects with ease.

In addition to simplifying some topics, we also hope to show that math can be your friend. To some of you, this is a given, but to others, having to deal with numbers is an uphill journey. If you find yourself in the latter category, we hope to smooth over some of the smaller bumps that might be caused by a knee-jerk reaction to the need for math. Understanding just a few small applications of mathematical or scientific principles can really go a long way. You may even find yourself becoming comfortable with these principles and applying them even when there are other ways to accomplish a goal.

In this chapter, we'll look at the following topics:

  • Basic Movement. We'll start with simple movement, updating x and y coordinates using constant velocities, and eventually adding acceleration.
  • Geometry and Trigonometry. We'll then discuss three of the most basic principles of geometry and trigonometry. We'll show you how to determine the distance between two objects, and then how to animate objects in a circular path and point objects at a specific location.
  • Physics. Friction, elasticity, and gravity add a bit of realism to animations, and you may be surprised how easy they are to simulate.
  • Programmatic Tweening. Scripting movement entirely from scratch affords the greatest flexibility but also requires a fair amount of labor. Sometimes, a pre-written method or two can satisfy a basic need for motion. We'll demonstrate ActionScript's Tween class, and its occasional partner in crime, the Easing package.
  • Timeline Animation Recreations. New to Flash CS3 is the ability to copy or export timeline tweens as XML and ActionScript. ActionScript 3.0's new Animator class can read that XML and recreate a timeline animation with ActionScript. We'll show you how to create a simple player for displaying such an animation.
  • Particle Systems. We'll close out the chapter with an applied example covering much of what we've discussed herein, creating a simple particle system—a group of autonomous sprites that, taken collectively, simulate a complex material or environment, such as water, fireworks, or colonies of insects.

Section 7.1: Basic Movement

When discussing scripted motion, a good place to begin is simple incrementing (increasing by a certain amount) or decrementing (decreasing by a certain amount) of x and y coordinates. Whether you realize it or not, you are probably used to working in a Cartesian coordinate system, where unique points are expressed on a single plane of two numbers, typically x and y. However, you are probably used to thinking about positive x values moving to the right and positive y values moving up, the way simple graphs are usually expressed.

The Flash coordinate system differs a bit from the typical coordinate system, in that the origin, or point (0, 0), is the upper-left corner of the stage, and y values increase when moving down. We will mention this again when it is directly applicable to an example, such as in when you control sound volume with your mouse. However, if you try to remember this difference, you will probably have fewer surprises.

To increment or decrement a value, you simply add or subtract a unit from that value. Here are two example ways of doing this:


mc2.x += 10;
mc2.y −= 10;

The first example uses double plus signs to increment a movie clip's x coordinate by 1 and double minus signs to decrement its y coordinate by 1. If you need to add or subtract more than one unit, you can use a plus or minus sign followed by an equal sign to add the amount shown on the right side of the equation to the entity on the left side. The second example cited adds 10 pixels to the x coordinate and subtracts 10 pixels from the y coordinate. In both cases, because the amount added and subtracted is the same, these hypothetical movie clips will move up (subtracting y coordinate values moves a movie clip up) and to the right by 1 pixel in the first example, and move up and to the right 10 pixels in the second example.

As we start discussing speed, velocity, and acceleration, it might help to have a little background that you can relate to the code. Speed, or how fast an object is moving, is a scalar quantity. That means it is a value that can be expressed with a magnitude alone, such as 80 miles per hour. Velocity is the rate of change in movement, and is a vector quantity. It must be expressed with both a magnitude and a direction. In contrast to the definition of speed, velocity can be described as how fast in a particular direction, such as 80 miles per hour, South-South-East. Acceleration is also a vector quantity and is the rate of change in velocity.

These distinctions are subtle but helpful when it comes to getting from point a to point b. An easy way to remember each property is to think of your own movement. You can move very quickly, alternating one step forward and one step backward. This will give you speed but (from a simple way of looking at things) an overall velocity of 0. If you switch to always moving one step forward, you may move at the same speed but now have a constant velocity. If you increase your speed over time, while continuing to move forward, your velocity increases, giving you acceleration.

This is not terribly important if you just want to create a basic animation. However, as you begin to build more complex systems, it may help to understand what is required to meet your goals, and it may help you create more realistic simulations.


Figure 7-1: Simulated movement of a movie clip, at a constant velocity, down and to the right

Later on, we'll show you how to express a direction using an angle. For now, however, the direction of movement will be dictated by whether you increase or decrease x and y coordinates—that is, velocity is often implied in, or can be extrapolated from, simple code. For example, if you remember that positive x values move an object to the right, you can specify a velocity merely by incrementing an x coordinate.

Breaking out this change into a variable can make this clearer and easier to work with. For instance, if you think of always adding a velocity to a movie clip's position, you not only simplify your operator use, but you also need to add only a positive value to move in a positive direction, or add a negative value to move in a negative direction.

This code creates a ball from a library movie clip included in this lesson with the linkage identifier class Ball. It then adds 4 pixels to the ball's x and y coordinates each time the enter frame event occurs. This means the ball moves down and to the right, as depicted in multiple frames in Figure 7-1.

1 var   ball:MovieClip = new Ball();
2  ball.x = ball.y = 100;
3  addChild(ball);
5  var xVel:Number = 4;
6  var yVel:Number = 4;
8  addEventListener(Event.ENTER_FRAME, onLoop, false, 0, true);
9  function onLoop(evt:Event):void {
10      ball.x += xVel;
11      ball.y += yVel;
12  }

Because the updated values are always 4 pixels, the ball is said to have a constant velocity. If you think of the onLoop() function executing once per second, the velocity would be 4 pixels per second, South-South-East. However, the function is executed every time the playhead enters the frame, so it's tied to the temp (frame rate). A frame rate of 20 frames per second (fps), therefore, would yield a velocity of 80 pixels (approximately one inch on a 72-pixel-per-inch monitor) per second. Let's see what happens if we vary the velocity over time.


Changing the velocity over time adds acceleration to an object. Consider the previous example of a constant velocity of 4 pixels down and to right. At 20 frames per second, this constant velocity (equivalent to 4 + 4 + 4 + 4, and so on) would take 3 seconds to move 240 pixels. However, if we accelerate the object 1 pixel per function execution, the changing velocity would look like 4 + 5 + 6 + 7 + 8, and so on. At that rate, using our 20 fps frame rate, the velocity would reach 23 pixels per iteration, and the ball would travel 270 pixels, in only one second. Acceleration is the compound interest of movement!

To realize this change, all you have to do is increment the velocity by the acceleration (rate of change of velocity) every time the function executes. Start with typed variables with initial values in lines 7 and 8, and then use them to increment the velocity in lines 15 and 16. This yields the effect of moving 4 pixels the first time, adding 1 to the velocity, moving 5 pixels the second time, adding 1, and so on.

1 var ball:MovieClip = new Ball();
2   ball.x = ball.y = 100;
3   addChild(ball);
5 var xVel:Number = 4;
6 var yVel:Number = 4;
7 var xAcc:Number = 1;
8 var yAcc:Number = 1;
10 addEventListener(Event.ENTER_FRAME, onLoop, false, 0, true);
11 function onLoop(evt:Event):void{
12     ball.x += xVel;
13     ball.y += yVel;
15     xVel += xAcc;
16     yVel += yAcc;
17 }
Figure 7-2: Acceleration increasing the velocity over time, simulated by increased movement in each frame

The effect is a rapid acceleration of the ball along its set direction. Figure 7-2 illustrates this effect by depicting the increasing distance between ball positions.

The opposite of acceleration, deceleration can be simulated by decreasing the velocity. Later on, we'll use this technique, in part, to illustrate gravity, and we'll also look at a more sophisticated deceleration technique to simulate friction.

Section 7.2: Geometry and Trigonometry

While many people find geometry and trigonometry intimidating, the small investment required to understand a few basic principles in these disciplines can pay large dividends. For example, what if you needed to find the distance between two points, or rotate one object around another? These small tasks are needed more often than you may think, and are easier to accomplish than you may realize.


Figure 7-3: Calculating the distance between two points using geometry

Let's say you are programming a game in which a character must be pursued by an enemy and must exit through one of two doors to safety. However, the enemy is close enough that the character must choose the nearest exit to survive. The player controls the character, but you must make the game challenging enough for the enemy to catch the character if the player makes the wrong decision. To do that, the enemy must know which exit is closest.

To determine which of two objects (the doors) is closest to a given point (the enemy), you need only one formula called the Pythagorean theorem. Simplified, the theorem says that the length of the longest side of a right triangle is equal to the square root of the sum of the squares of the horizontal and vertical sides. For our needs, this can be determined by finding the differences between the two x values and two y values, and then checking the square root of the sum of those two squares. Figure 7-3 illustrates both descriptions.

To determine the distance between two points in ActionScript, you must calculate the difference between the x values of both points and multiply that difference by itself (squaring the value). Then do the same thing with the y values (squaring that difference, as well). Finally, following the Pythagorean theorem, use the Math object to return the square root of that sum.

function getDistance(x1:Number, y1:Number, x2:Number, y2:Number):
    Number {
    var dx:Number = x1-x2;
    var dy:Number = y1-y2;
    return Math.sqrt(dx * dx + dy * dy);

Here is an example usage of our getDistance() function, seen in the accompanying distance2.fla source file. It compares the distance between ball0 and ball1 to the distance between ball0 and ball2:

var dist1 = getDistance(ball0.x, ball0.y, ball1.x, ball1.y);
var dist2 = getDistance(ball0.x, ball0.y, ball2.x, ball2.y);
if (dist1 < dist2) {
    trace("ball1 is closest to ball0");
} else {
    trace("ball2 is closest to ball0");

Movement Along an Angle

Earlier we discussed velocity as a vector quantity because it combined magnitude and direction. However, the direction in the previous example was determined by changing x and y coordinates. Unfortunately, such a direction is easily identifiable only when moving along simple paths, such as along the x or y axis. A much better way to indicate a direction is to specify an angle to follow.

Before we discuss angles and their different units of measure, it will help to understand how angles are indicated in the Flash coordinate system. As you might expect, angles are commonly referenced using degrees, but it's important to note that 0 degrees is along the x axis pointing to the right. The 360-degree circle then unfolds clockwise around the coordinate system. This means 90 degrees points down along the y axis, 180 degrees points left along the x axis, and so on. This is depicted in Figure 7-4.

Figure 7-4: How Flash angles (a) and radians (b) are calculated

Now that you have a correct point of reference, the next important concept to understand is that most of ActionScript, like most computer languages and mathematicians, does not use degrees as its preferred unit of measurement for angles. This is true for just about all common uses of angles, except for the rotation property of display objects and one or two somewhat more obscure items (such as a method of the MatrixTransformer class also used to rotate display objects). These entities use degrees as measure angles and to remain comfortable and familiar to users. The remainder of ActionScript uses radians: A radian is the angle of a circle defined by moving along the outside of the circle only for a distance as long as its radius, as seen in 7-4. One radian is 180/PI degrees, which is approximately 57 degrees.

While some of that may prove helpful, or even interesting, for our purposes we don't need to memorize this information. Instead, all we need to do is remember that there is a formula handy for our conversion needs. Converting degrees to radians is accomplished by multiplying the original angle in degrees by (Math.PI/180). Conversely, radians can be converted to degrees by multiplying the original angle in radians by (180/Math.PI). In the upcoming example, we'll write a utility function for this purpose that we can use throughout the rest of our examples.

Pages: 1, 2, 3, 4

Next Pagearrow