||Creating Basic Animation in Macromedia Director
Author: Ken Loge
Level: Beginner to Intermediate
This article describes two of the most common methods used to create basic animation effects in Director and may be helpful if you are just beginning to explore some of Director's advanced animation capabilities, or if you are starting to make use of Lingo scripts in your movies.
The image below is used as an example for this article. If you want to use it without downloading the example movies you can RIGHT-CLICK the image and save it as a file for the exercises that follow.
There are two example Director movies you can download for the exercises below. Both movies are in a Director MX 2004 format, but should load into Director MX as well.
Keyframe Balloon Animation
Scripted Balloon Animation
In case you're new to Macromedia Director and animation, here is a brief glossary of some of the terms used in this article.
Cast - The database of media assets used in a Director movie.
Channel - Similar conceptually to a "layer" in a paint program, a channel allows a sprite associated with that channel to have unique control parameters that can be manipulated independently from other channels. A Director movie may have up to 1000 channels.
Frame Rate - The number of frames per second (FPS) of graphic content that are draw to the screen.
Keyframe - A "snapshot" of one or more sprite properties, such as screen position, at a specific point in time.
Linear Interpolation - To 'interpolate' means to calculate a new value in between two known values. Linear interpolation creates new values at equal distances along a line between two known values. When you animate objects with the Score or Stage and set the key positions of a sprite, Director computes the in-between (tweened) points to determine how the sprite moves from one keyframe to the next.
Lingo - The built-in scripting language for Director.
Score - The layout space for sprites, similar in appearance to a spreadsheet. The score contains up to 1000 channels and a virtually unlimited number of frames.
Sprite - 1) A cast member that has been placed in the Score, and consequently can be seen on the Stage. 2) Any graphically manipulable or programmable object that has been placed in the Score.
Stage - The window of presentation where all visible action takes place.
Tweened Frame - Animation that is automatically generated by the computer when it is given at least two keyframes. Tweened animation is usually generated by means of linear interpolation.
The Director Coordinate System
The cartesian coordinate system is one of the most fundamental and important concepts to understand when you begin to work with 2-D graphic software. The purpose of a coordinate system is to provide a form of notation to describe a spatial position, or point.
The image on the left shows a representation of Director's coordinate system. A two-dimensional coordinate system like this always assumes the horizontal ( X ) value is shown before the ( Y ) value, so the upper left part of the screen is (0, 0), indicating 0 pixels on the X-axis, and 0 pixels on the Y-axis. If the screen were 800 pixels across and 600 pixels high, the bottom right corner of the image would have (800, 600) as the coordinates. The middle of the screen would be (400, 300).
The green lines show the direction each respective axis increases in value. The X-axis increases in value toward the right, and the Y-axis increases in value from top to bottom.
Methods of Animation
Macromedia Director provides powerful and versatile tools for creating animation. Typically, there are two methods developers use to animate in Director: 1) Keyframe animation, and 2) Scripted animation. We will go over each animation method briefly.
Keyframe animation in Director is an extension of traditional cel-based animation where the animator draws "key" poses that define the action or movement within a scene. The keyframe method translates nicely to a visual paradigm in a computer interface, so it should come as no surprise that programs such as Director, Flash, and powerful 3-D animation applications like Maya, Softimage, and Animation Master make extensive use of keyframe animation tools. Keyframe animation in Director involves placing sprites in various channels in the Score and using Director's timeline animation tools to alter sprite position, size, rotation, and other visible qualities of each sprite to achieve the desired effect.
For many animation needs keyframing is effective and relatively easy to work with because each sprite can be modified visually. However, as useful as keyframe animation can be it is not without disadvantages. Keyframe animation is only as versatile as the tools the software provides to work with it, and the tools are sometimes not enough. For example, keyframe animation in software frequently makes use of linear interpolation, which finds intermediate positions from one or more specified screen coordinates. To gain more animation precision using keyframes requires more keyframes. At some point there may be so many keyframes that the animation process becomes counterproductive. Another disadvantage of keyframe animation is that it is not particularly well suited for games, where complex logical conditions often determine the visible actions of sprites. Here are some considerations to take into account when thinking about keyframe animation.
Consider creating keyframe animation when:
- The animation task is relatively simple.
- The animation is relatively short in duration.
- There are few cyclic (looped) animation needs.
- You don't need interactivity, such as that required by a game.
- You have to create an animation in a hurry.
Let's look at an example of how a simple animation task might be handled using the keyframe animation tools in Director. Suppose our task is to animate a hot air balloon so it moves across the screen from left to right in a straight line.
Here's the process we could use to accomplish this:
- Using Director's keyframe animation tools we drop the image of the balloon into sprite Channel 1 in the Score.
- While still using the Score window we extend the sprite over some number of frames, say 10. (Depending on the settings your copy of Director has, your sprite may span more or fewer frames by default.)
- We select just the last frame of the sprite by OPTION+Clicking on the last frame of Sprite 1 in Channel 1 (Macintosh), or ALT+Clicking the frame of Sprite 1 in Channel 1 (Windows) in the Score window.
- Reposition the balloon in the Stage window where we want it to end up, and let Director fill in the tweened frames.
The image below shows how the 10 frames of animation might be displayed on the Stage using this technique. The blue dot near the center of the balloon image represents the initial keyframe for the balloon. The small black dots along the line represent the intermediate (tweened) frames, and the larger red dot at the right represents the final (end) keyframe. Essentially, the blue and red dots represent a "snapshot" of various sprite properties such as horizontal and vertical position, rotation, size, etc. (In the image of the Score above, the white dots at the beginning and end of the "Balloon" sprite represent the sprite's first and last keyframes, and show the same information as the image below, but in a different visual style.)
In the example above, Director uses the "snapshot" positional information from the keyframes to determine the tweened frames by computing the absolute distance the sprite must move, and dividing that distance by the number of frames over which the movement occurs. The end result is that the sprite ends up in the position below.
A keyframe approach works nicely for this kind of simple animation, but how do we slow down the balloon? If you've run the "Keyframe Balloon Anim.dir" movie you probably noticed that the balloon moves too fast, and "jerks" across the screen. Let's try to slow it down and smooth out the balloon's movement.
Using Director's keyframe animation tools we can move the last keyframe to a position further away from the initial keyframe so there is less movement per frame. Since Director uses linear interpolation we know that by adding more tweened frames the end result will be that the balloon will appear to move more slowly between the keyframe positions. If we stretch out the duration of the balloon's keyframes so they are 50 frames apart, the balloon's Stage representation would look like the image below.
Notice how many tiny black dots there are between the keyframes. Each dot is showing us a representation of a tweened frame, and since there are 50 of them now the display is much more dense. Our score looks different too. Sprite 1 now requires a span of 50 frames just to slow down the movement of the balloon.
Slowing the balloon down even more would necessitate dragging the last keyframe of the balloon sprite even further to the right in the timeline, or slowing down the overall frame rate of the movie. In a more intricate animation, with multiple sprites, the Director timeline can become downright unwieldy if you rely solely on the Score. When animating in the Score with keyframes becomes an exercise in patience, it's time to consider another approach: scripted animation.
Lingo and Scripting
Before we go any further, let's address a couple of overall issues relating to Lingo, and computer programming and scripting at large.
- Lingo is just as much a programming language as any other. Don't let anyone tell you otherwise. Scripting and programming are virtually the same thing. The main difference is that the code for a scripting language like Lingo can be written faster and is usually easier to work with.
- Programming is an art form and a language, and as such you have to work with Lingo on a regular basis to improve your skills with it.
- The better able you are to be simple, the easier you may find it is to learn to program. Part of the process of learning a scripting language like Lingo is understanding how stupid the computer really is, and trying to make your brain think in tiny little specific steps. Lingo is like a newborn child, and you can't assume it knows much at all. It needs a good parent and teacher. Start out writing simple scripts and you'll be surprised to find that advanced scripts are really just comprised of lots of small ideas that work in concert.
- Lingo scripts are read by the machine from top to bottom, left to right. The Lingo instructions you write will be interpreted in that order.
- Lingo indents specific lines of code to help you see how they are related. Lines that indent to the same "indent" level are part of the same code "block." If a line that should be part of a code block does not automatically indent, you probably have a syntax error, which means you mistyped something, spelled a Lingo keyword incorrectly, or left out something that Lingo needs to figure out what you're trying to get it to do. Sometimes Lingo gets mixed up, and won't indent a legitimate line of code. You can hit the TAB key on a line of Lingo code that doesn't indent correctly, and it will indent if it's written correctly.
When precise sprite choreography is required in your animation, Lingo is often the best solution. Scripted animation is commonly used for game development where animated sprites must react, in real time, to the user's actions, and perform their pixel gymnastics based on complex logical conditions.
Animating with Lingo has many advantages. Primarily, Lingo removes virtually all restrictions pertaining to the movement and actions of each sprite. If a developer can dream up a series of movements for a sprite, the chances are that it can be accomplished with a series of Lingo statements. Lingo animation also breaks away from the restrictions of timeline based animation where subtle sprite property changes can be difficult to realize. The only disadvantages for using Lingo to animate is that it requires some proficiency with the language, and it is sometimes a more time consuming process than Score and timeline animation. Other than that you are only limited by your imagination and how well you can spin the propeller on your head to make Lingo work for you.
Consider creating scripted animation when:
- The animation task is relatively complex, or requires precise movement.
- You have multiple cyclic animation sequences that need to play repeatedly.
- You need the artwork to be interactive, and respond to user input.
- The animation task would be too tedious to create by hand with keyframes. For example, a moving star field, snow, or rain.
- You need a reusable graphic manipulation system that can be modified.
- Your artwork needs to have random qualities such as speed of movement, or animated textures.
Now let's put Lingo to work and see how we might use a "Scripted Animation' solution to move the balloon across the screen.
First, download and open the "Scripted Balloon Anim.dir" Director file, or download the Balloon graphic from above and import it into Director. You don't need the balloon graphic per se, as any graphic will do, but the balloon image is well-suited for this exercise, so the assumption is that you're using it.
First, drop the balloon cast member into Channel 1 of the Score window.
||Notice in the example to the left how the last keyframe of the sprite in Channel 1 shows a white rectangle, rather than a circle. The white rectangle tells you that no "end" keyframe has been set. This is what you want. The reason for this is that we want to control the movement of the balloon sprite with Lingo, and we therefore do not need to set keyframes to animate the balloon.
Next, let's look at the property inspector to see where the balloon image is currently located. Use the "/" divide key on the number pad of your keyboard to toggle the visibility of the property inspector. Note: Make sure the "Num Lock" light is 'Off' on your keyboard so the number pad keys work as controls for your Director movie.
||The property inspector is one of the most useful panels in the Director interface, as it shows you at a glance various sprite properties, such as horizontal and vertical position, the ink mode, etc. Right now we're most interested in the "X" value of the sprite, which tells us where the sprite is located horizontally (i.e., on the X-axis) of the current Stage window. You can see that the balloon is positioned at 94 pixels from the left edge of the screen. This is a good general area for the balloon to start from. If you want to snap your balloon graphic to a position, type in a number in the "X:" field, then hit the TAB key.
Our next task is to add Lingo code to the balloon sprite so it moves across the screen from left to right. To do this on a Macintosh with a single button mouse, CONTROL + CLICK the sprite and choose "Script..." from the popup menu. On a Macintosh with a right mouse button, or on a Windows computer, right click the sprite and select the same "Script..." option from the popup menu. When the Script window opens you should see something that looks like the image below:
The Script window is where you store the commands your sprite will follow. You can have a virtually unlimited number of scripts in a Director movie. Each script usually contains one or more "handlers."
A handler is a block of Lingo code that responds to a specific message and executes any number of Lingo statements that are a part of that handler. In the example on the left, a basic handler was already created for us.
This handler will respond only to a "mouseUp" message, which means it will only operate if the user pushes the mouse button down, then lets go of the button. Mouse messages are among the most commonly needed input for interactive movies, but in this example we will drive the animation with a different message called "exitFrame."
To control a sprite with Lingo you must refer to the channel where that sprite lives. In this example, the balloon sprite lives in Channel 1, so we first tell Lingo that we're going to alter some property of sprite Channel 1:
Once we have established the specific sprite, we need to determine what property of the sprite we want to work with. To do this we specify the sprite, then we type a period to tell Lingo that we are going to specify a property of that sprite, followed by the property we want to work with. The "locH" property of a sprite allows the developer to both view the current horizontal ('X') location of a sprite, as well as set it's horizontal position. To prepare the sprite for our assignment of it's horizontal position we will write this statement:
In Lingo the equals '=' operator is used to assign a value, or to check a logical statement or condition. In our animation example we want to use the equals operator to set the position of our sprite. In the simplest case we can simply add an equals operator to the end of the previous statement, and type in a number, like this:
sprite(1).locH = 300
This will immediately set the current horizontal position of Sprite 1 to 300 on the screen. If incorporated into the current handler it would look like this:
on mouseUp me
sprite(1).locH = 300
This makes the sprite jump to a horizontal position 300 pixels from the left side of the stage, as soon as the mouse button is clicked. This might be considered a kind of animation, but it's not very interesting. What we need is a handler that will move the balloon sprite continuously across the screen. There are many methods you can use to move a sprite in Director, but In the above example our sprite jumps to a position instantly, and we don't get to have the fun of watching it traverse the space across the screen. Here's a modification of the above script that's closer to what we want:
on mouseUp me
sprite(1).locH = sprite(1).locH + 10
The modified script takes the current horizontal position of Sprite 1 and adds 10 to it each time the mouse button is clicked, effectively causing it to move to the right. This will animate the Balloon sprite, but it has at least two problems.
- To move the sprite to position 300 on the screen would require 30 mouse clicks!
- The sprite only moves if the mouse button is clicked.
What we need is a way to have the sprite move all by itself, without the need for the mouse to be clicked. To do this we'll change the mouseUp message to an exitFrame message. The exitFrame message is automatically sent out when the playhead is finished drawing the current frame. There are many messages Director automatically sends out, but exitFrame is one of the most useful for driving animation. Remember, a message is what activates a handler. If we change the above script to use an exitFrame message, rather than a mouseUp message, we will automatically move the sprite across the screen as the exitFrame messages are sent. The number of times the exitFrame message is sent out per second depends on the frame rate setting. You can view or change the current frame rate of your movie by typing CONTROL + 2. Usually, the frame rate will be 30 by default when you start up Director.
Copy the following script to your balloon sprite and run your movie to make your sprite move across the screen.
on exitFrame me
sprite(1).locH = sprite(1).locH + 10
Note: Using exitFrame to drive the animation of sprites is a good idea because the message is sent out repeatedly for every frame that Director draws. You can think of Director as having a built-in high speed virtual artist that can draw so fast that your eyes see what the virtual artist draws as animated. You can adjust the speed at which Director renders frames, but the default value of 30 frames per second should be more than adequate to provide the illusion of motion.
If you want to slow down the speed at which the balloon moves across the screen, try adding a smaller number to the current position of the sprite. For example, changing the '10' to a '1' moves the Balloon 1 pixel every time a frame is drawn. At 30 frames per second (FPS) the sprite will move 30 pixels every second. Previously, the balloon would move 300 pixels per second. Conversely, you can increase the number to make the sprite move even faster.
We have finally gotten the Balloon Sprite to move across the screen, but there's a problem you've probably already noticed. Once the sprite crosses the screen it keeps going. What would be more interesting is to have the sprite continuously move across the screen, not just one time. Fortunately, this is an easy problem to fix. We need to add what is called a "conditional statement" to our handler. A conditional statement creates a logical condition that when true will allow us to change what happens. In this example we want the horizontal position of the sprite to eventually cause the sprite to start again at the left side of the screen. Here's the solution:
on exitFrame me
sprite(1).locH = sprite(1).locH + 10
if sprite(1).locH > 720 then
sprite(1).locH = -100
The conditional statement adds three lines to our handler. Here's a breakdown of the conditional statement:
if sprite(1).locH > 720 then
If the horizontal location of sprite(1) is greater than 720 Lingo will execute the next line of code.
sprite(1).locH = -100
Move the sprite to a horizontal position of -100 on the screen. Using a negative number will make the sprite appear to emerge from the left side of the screen. If you want the sprite to start again from the visible part of the screen change the -100 to a positive number.
This line simply makes Lingo go to the next line in the handler, and informs Lingo that the current logical condition is done. Since there's only an "end" line after the "end if," the handler will start over from the top as many times as the exitFrame message is sent. Since the frame rate of our movies is 30, the exitFrame message will be sent 30 times per second automatically. This makes the balloon move 60 pixels per second because we add '2' to the current position of the balloon, until it goes past horizontal position 720 on the screen. Once the balloon is past the right edge of the screen it will immediately jump to a position offscreen on the left side and cross right again and again, until the movie is stopped.
on exitFrame me
sprite(1).locH = sprite(1).locH + 2
if sprite(1).locH> 720 then
sprite(1).locH = -100
Improving the Animation Script
The above animation script is simple and fairly flexible. By changing some of the numbers in the script many possibilities begin to emerge. The next best thing we can do to this script is make it work on any sprite it is attached to, not just Sprite 1. To do this we can substitute 'me.spriteNum' wherever sprite(1) is written in the script. The changed script looks like this:
on exitFrame me
sprite(me.spriteNum).locH = sprite(me.spriteNum).locH + 2
if sprite(me.spriteNum).locH> 720 then
sprite(me.spriteNum).locH = -100
Essentially, the me.spriteNum statement forces Lingo to talk to whatever sprite channel number is currently attached to the script. For example, if the script is attached to a sprite in channel 10, the above script will work. If it's attached to a sprite in channel 5, the script will work. 'me.spriteNum' extracts the sprite number and makes it relative to whatever sprite channel the script is part of. It's a little more work to write, but it makes the script even more versatile.
What's the Point?
The final modification we'll make to the script is to make it easier to change the direction the sprite will move horizontally and vertically. Director has a special function and data type called a point, which has both a horizontal and vertical component. The point data type can be used to set both the horizontal and vertical positions of a sprite at once, or to perform mathematical operations that change the sprite's position.
Sprites have many properties, and in this article we have only explored the .locH property. Sprites also have a .locV property, which changes the vertical position of the sprite, and a .loc property that allows both the horizontal and vertical properties to be assigned the value of a point. To set our balloon sprite to a specific point on the screen the script might look like this:
sprite(1).loc = point(100,100)
The above statement would immediately move sprite 1 to screen point 100, 100. We can use points to make our original animation code even more versatile by rewriting the animation code so an X (horizontal) value of the point data type is added to the current location of the sprite to get the same net animation effect as before. However, using this method makes it very easy to move the sprite from right to left by simply adding a negative number to the current position.
This moves Sprite 1 two pixels to the right every time it is executed:
sprite(1).loc = sprite(1).loc + point(2,0)
This moves Sprite 1 two pixels to the left every time it is executed:
sprite(1).loc = sprite(1).loc + point(-2,0)
This moves Sprite 1 two pixels down every time it is executed:
sprite(1).loc = sprite(1).loc + point(0,2)
This moves Sprite 1 up and to the right by two pixels every time it is executed:
sprite(1).loc = sprite(1).loc + point(2,-2)
You can begin to see how truly versatile a Little Lingo can be. On your own, try writing a scripted animation that:
- Moves a sprite forward then backward across the screen.
- Moves a sprite up and down on the screen.
- Zig zags a sprite across the screen.
- Moves a sprite in a "box" pattern around the screen.
When you feel comfortable animating a single sprite with Lingo, try animating more than one sprite. Using the method shown in this article allows multiple sprites to move simultaneously, at different speeds, and at different directions. You have up to 1,000 sprite channels to work with. Hmm. Imagine the possibilities...