Okay, here is a tutorial about making basic spaceship-like movement in Flash with ActionScript. There's probably a bunch of mistakes and typos so let me know if find anything wrong / badly explained / not explained at all.
[size=200]Making a Spaceship Fly in Flash[/size]
Written by Haydn Ewers
Resources
IntroductionThis tutorial will show you how to make simple spaceship-like movement in
Flash. No previous knowledge of ActionScript or programming is required, but
a basic knowledge of Flash and computing is recommend. A little knowledge of
trigonometry would be useful as well. Although written of Flash MX this tutorial
will also work in Flash MX 2004 and Flash 8.
Putting it TogetherCreate a new Flash document
File > New. Set the size of the stage
to whatever you want by selecting
Modify > Document. I used 500px
by 500px. You’ll probably want to bump-up the framerate at the same time to
about 25fps. Click
OK to close the dialogue box.
If the Library panel isn’t visible open it by selecting
Window > Library.
Press the
New Symbol... button in the bottom left corner of the Library
panel. In the resulting dialogue box enter
myShipSymbol_mc in the Name
field. The Type should be set to
Movie Clip. In the Linkage section (you
may need to press the
Advanced button) select the Export for
ActionScript option.
When you select this option the
Export in first frame option should be
automatically set. Click
OK to close the dialogue box.

Fig. 1 – The Document Properties dialogue box
There should now be a Movie Clip in your Library called
myShipSymbol_mc.
If the
myShipSymbol_mc symbol isn’t already, open it by double-click
the
myShipSymbol_mc Movie Clip’s name in the Library panel. Draw your
spaceship into the open Movie Clip. You can have your ship look like whatever
you want – as long as you keep it centred in the Movie Clip. (The centre of
the movie clip is marked with a small cross. If you can’t see it try zooming
out the show more of the work space.) Make your space ship about 100px by 100px
(otherwise it will be too big to fit on the screen). When you’ve finished drawing
you spaceship return to the Main Stage by pressing the
Back button located
on the left-hand side above the Timeline.

Fig. 2 – The Create New Symbol dialogue box
Select the blank Keyframe on
Layer 1 in the Timeline. Open the Actions
panel by selecting
Window > Actions. If you haven’t changed the original
settings the Actions panel will open in Normal Mode. To work in Expert Mode,
which allows you to type freely, select
Expert Mode form the Actions
panel's pop-up menu. Enter the following code into the Actions panel:
Code:
this.attachMovie("myShipSymbol_mc", "myShipInstance_mc", 0);
myShipInstance_mc._x = Stage.width/2;
myShipInstance_mc._y = Stage.height/2;
myShipInstance_mc.xMove = 0;
myShipInstance_mc.yMove = 0;
myShipInstance_mc.accel = 1;
myShipInstance_mc.onEnterFrame = function() {
if (Key.isDown(Key.UP)) {
this.xMove += this.accel*Math.sin(this._rotation*(Math.PI/180));
this.yMove -= this.accel*Math.cos(this._rotation*(Math.PI/180));
}
if (Key.isDown(Key.LEFT)) {
this._rotation -= 5;
}
if (Key.isDown(Key.RIGHT)) {
this._rotation += 5;
}
this.xMove *= 0.95;
this.yMove *= 0.95;
this._x += this.xMove;
this._y += this.yMove;
};
If you test your movie now (
Control > Test Movie) you should be
able to fly your spaceship around. If you can’t you’ve most likely made a typo
when entering the code.
The TheoryThe spaceship’s movement (not its position) is kept by the
xMove and
yMove values.
These values define how fast it is moving on the x and y coordinates. For example,
if the value of
xMove is 10 and the value of
yMove is
0 the spaceship will be moving 10px to the right each frame. Alternatively if
yMove has
a value of 10 and the
xMove has a value of 0 the spaceship will move
down the screen 10px per frame. You’ll notice that the y coordinate is opposite
to that of standard coordinate geometry. This is because on screen position
is measured from the top-left corner.
Each time the code is executed we check to see if the up arrow is being pressed.
If it is being pressed the values of
xMove and
yMove are
increased by a value based on the direction the spaceship is heading and the
value of
accel. (See fig. 3)

Fig. 3 – How the ship moves in 2D
To do this we need to employ some trigonometry. As you can see the parameters
we’re working with can be represented as a right angle triangle. (See fig. 4)

Fig. 4 – A right-angle triangle can be drawn to represent the ship'smovement
So when calculating the xMove we can say the sine of the theta equals the
adjacent divided by the hypotenuse (
sin(t) = a/h) and therefore the
hypotenuse multiplied by the sine of the theta equals the adjacent (
h*sin(t)
= a). Or as it’s written for Flash to understand
a = h*sin(t).
The yMove is calculated in pretty much the same way as the
xMove except
cosine is used instead of sine (
cos(t) = o/h). You’ll notice in the
final code that this value is subtracted from the yMove instead of added. This
is because of the reverse y coordinate discussed earlier.
As you can also see in the final code we also multiple the rotation (or theta)
by pi divided by 180. The reason for this is that Flash measures rotation in
radians. You don’t really need to know all the details of this, but instead
of measuring angles as a value between 0 and 360 Flash sees it as a value between
-pi and pi. To perform the conversion from degrees to radians we simply multiple
the degrees by the amount of radians in one degree (
pi/180).
So after calculating the amount to increase both the x and y movement by we
then need to actually position the spaceship. To do this we add it’s movement
to it’s previous position. So, for example, if the spaceship’s x coordinate
is 25 and its x movement is 5 we need to set its x coordinate to 30.
The problem with this is that the spaceship will keep increasing speed unchecked.
(
xMove and
yMove will have another value (calculated from
the
accel and
rotation) added to their values’ each frame.)
To remedy this with can apply some decay to the x and y movement. We do this
by multiplying both by a 0.95. This reduces there value by 5% each turn creating
an easing effect.
Another way we could have made the ship 'fly' would have been to add the values
we worked out for the x and y movement directly to the x and y coordinate (e.g.
increasing the x coordinate by
h*sin(t)). This would, however, have
the down side of only moving the spaceship when we were applying power. There
would be no drift when the user releases the keys.
The CodeI’m going to go through the code line by line and explain what each line does.
For more information about any of the methods, objects or properties used here
you can look them up in the ActionScript Dictionary that comes with Flash.
Code:
attachMovie("myShipSymbol_mc", "myShipInstance_mc", 0);
The code
attachMovie is a method (of the MovieClip object) that
is used to add Movie Clips from the Library to the Stage on-the-fly. The three
parameters passed to the
attachMovie method (
"myShipSymbol_mc", "myShipInstance_mc",
0) tell it that:
- the Symbol in the Library is called myShipSymbol_mc
- the instance (an instance is what a copy of a Movie Clip symbol on the
Stage is called) will be myShipInstance_mc
- the new instance’s depth should be 0
(The depth of a Movie Clip determines how it is displayed. Movie Clips that
have higher depths are drawn in front of those with lower depths.)
The semicolon
; at the end of the line tells Flash that the action
ends there. Every action written in ActionScript should be ended with a semicolon.
Code:
myShipInstance_mc._x = Stage.width/2;
In the next line of code
myShipInstance_mc refers to the Movie
Clip that we just attached to the main timeline.
The
. (dot) operator is used in Movie Clips to access nested (or
child) Movie Clips, Variables or Properties. The dot operator is also used with
objects to get or set the properties, execute methods and create data structures.
In this example we are accessing a Property (
_x).
The
_x is a property of the MovieClip object that defines the horizontal
position of the Movie Clip on the Stage. For example if the
_x is
set to 25, the Movie Clip’s centre (this is the cross we centred the spaceship
over earlier) will be 25px from the left-hand side of the Stage.
The
= operator sets the left-side of the statement to the value
of the right. In this case the right-side is
Stage.width/2.
The
Stage object is used to access the movie’s stage (the part
you actually see). The
width property of the
Stage object
holds the horizontal size of the Stage in pixels. (This will probably be the
same as the value you entered when you said how wide you wanted your Flash document
to be.) The
/ operator divides the value on the left with the right.
So if your movie is 500px wide
Stage.width/2 will be interpreted
as 250 (
500/2). By doing this your spaceship will start in the centre
of the screen.
Code:
myShipInstance_mc._y = Stage.height/2;
This statement does the same as the previous one, but on the y axis (vertically).
Code:
myShipInstance_mc.xMove = 0;
As you can see this line is similar to the previous two. The main difference
is that in this statement a variable, not a property, is being set. Properties
are pre-defined characteristics. Variables, on the other hand, are defined by
you and can be whatever you want as long as it’s name does not conflict with
a keyword or object already defined. You can call a variable
billTheFireman_36 and
Flash wouldn’t care. There are some rules when naming variables:
- the first letter must be a letter, underscore (_) or dollar sign
($)
- all other characters must be letters, numbers, underscores or dollar signs
So the
myShipInstance_mc Movie Clip now has a variable inside of
it with the name xMove and a value of
0.
Code:
myShipInstance_mc.yMove = 0;
myShipInstance_mc.accel = 1;
The next two lines are the same as the previous one, except that the create
variables called
yMove and
accel with the values 0 and
1 receptively.
Code:
myShipInstance_mc.onEnterFrame = function() {
This line tells Flash that we are defining a function that will be assigned
to the
onEnterFrame Event Handler of our
myShipInstance_mc Movie
Clip. Event Handlers are invoked when a particular event occurs. For example
the
onEnterFrame Event Handler in a Movie Clip is invoked before
each frame is displayed.
The
function keyword is used to define functions. In this case
it is followed by a pair of empty parenthesis (
()) to show that no
parameters are passed to the function.
The curly brace (
{) is used here to signify the start of the block
of code that will make up the function.
You’ll notice that there is not a semicolon at the end of this line. That
is because there is more code to come after this line that is part of the same
action.
Code:
if (Key.isDown(Key.UP)) {
We now move into the code that makes up the function. All of the code within
the curly braces (that we defined in the previous line) will be executed when
the
onEnterFrame Event Handler is invoked.
The
if statement is used by Flash to make decisions. When reading
an if statement Flash evaluates what is inside the parenthesis and if it returns
true executes the code within the curly braces following the parenthesis. For
example if you wrote
if (true) Flash would always execute the commands
inside the if statement because
true always returns true.
In our spaceship example we are checking if
Key.isDown(Key.UP) is
true.
Key, like
Stage, is a predefined object in Flash.
The Key object contains methods and variables used to read user input. The
isDown method
of the
Key object assesses the value of the parameter passed to it
and returns true if the corresponding key is down. The
Key.UP property
contains the value of the up arrow key (38). We could have written
Key.isDown(38) instead,
but
Key.isDown(Key.UP) is easier for us humans to read.
Code:
this.xMove += this.accel*Math.sin(this._rotation*(Math.PI/180));
This action increases the value of the xMove variable in the
myShipInstance_mc Movie
Clip based on the rotation of the ship and the amount we defined in
accel earlier.
The
this keyword refers to the current Movie Clip that contains
a script or, when a method is called, a reference to the object that contains
the called method. In this example, because our code is in a method, this refers
to the object that contains the method –
myShipInstance_mc.
You may also be wondering what the
+= is. This is an addition assignment
operator. This compound operator automatically adds the value on the left to
the right. For example both
a = a + b and
a += b do the
same thing.
The
Math.sin() method returns the sine of the angle that is passed
to it. Here we pass
this._rotation to the method to get the sine
of the rotation of the spaceship. The rotation is converted from degrees to
radians by multiplying it by
Math.PI/180.
Code:
this.yMove -= this.accel*Math.cos(this._rotation*(Math.PI/180));
This line basically the same thing as the pervious, except that it works on
the
yMove variable. As discussed earlier we use cosine instead of
sine and also subtract the value from
yMove instead of add.
Code:
if (Key.isDown(Key.LEFT)) {
this._rotation -= 5;
}
if (Key.isDown(Key.RIGHT)) {
this._rotation += 5;
}
These two if statements check if the left arrow or right arrow keys are down.
If they are the spaceship is rotated by 5º via the
_rotation property
in the required direction.
Code:
this.xMove *= 0.95;
this.yMove *= 0.95;
These two lines are used to create the easing effect on the movement. Each
time the code is executed the movement will decrease by 5%. The
*= operator
assigns the value of the left multiplied by the right to the left (
a =
a * b is the same as
a *= b).
Code:
this._x += this.xMove;
this._y += this.yMove;
The
_x and
_y properties of the ship are increased by
the value of the two movement variables. By repeating this each frame we can
create a smooth animation of the ship moving around the screen.
Code:
};
The curly brace tells Flash that this is the end of the function declaration
that we began earlier. There is also a semicolon because this is the end of
the action.
ConclusionHopefully you now have a better understanding of how basic interactivity is
achieved in Flash. I recommend that you play around with this script to see
how different changes affect the result. You may also like to attempt some of
these challenges:
- make the rotation ease like the movement does
- make the down arrow move the ship in reverse
- make the ship move faster when the space key is held down