Post new topic Reply to topic  [ 8 posts ] 
Author Message
 
 Post subject: Making a Spaceship Fly in Flash
PostPosted: Fri Sep 15, 2006 10:08 pm 
New Dev

Joined: Sun Jul 16, 2006 6:54 pm
Posts: 32
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

Introduction

This 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 Together

Create 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.

Image
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.

Image
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 Theory

The 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)

Image
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)

Image
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 Code

I’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.

Conclusion

Hopefully 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


Offline
 Profile  
 
 
 Post subject:
PostPosted: Fri Sep 15, 2006 11:31 pm 
Regular Dev

Joined: Tue Jul 18, 2006 8:37 pm
Posts: 162
Location: Adelaide
wow mate you work quick.

i havnt tried it yet but will as soon as i get time


Offline
 Profile E-mail  
 
 
 Post subject:
PostPosted: Mon Sep 18, 2006 11:57 am 
User avatar
Site Admin

Joined: Sat Jul 15, 2006 7:42 pm
Posts: 2851
Location: Adelaide
That is fantastic Hadyz, really well written and really really cool! :)

Keep up the great work!

:smt041


Online
 Profile My Photo Gallery  
 
 
 Post subject:
PostPosted: Tue Sep 19, 2006 10:12 am 
Forum VIP

Joined: Sun Jul 16, 2006 5:59 pm
Posts: 275
Location: Adelaide, South Australia
GO CODER BOY!!!! :D Good work with the tutorual. Damn fast worker. :D

StickMan


Offline
 Profile E-mail  
 
 
 Post subject: Hell yeh
PostPosted: Wed Sep 20, 2006 10:38 am 
Forum VIP

Joined: Wed Jul 19, 2006 9:32 pm
Posts: 381
Hey this tutorial looks great Finch, you are great at explaining things. I was never really good at trig and stuff in highschool your diagrams help a bunch to undrestand whats going on.

Maybe in the next tutorial the ship could shoot at something... gotta love the old arcade games.


Offline
 Profile  
 
 
 Post subject:
PostPosted: Wed Sep 20, 2006 10:40 am 
User avatar
Site Admin

Joined: Sat Jul 15, 2006 7:42 pm
Posts: 2851
Location: Adelaide
Yeah awesome idea Impaler.....Asteroids is coming to mind....... :)


Online
 Profile My Photo Gallery  
 
 
 Post subject:
PostPosted: Sun Jul 22, 2007 9:04 pm 
User avatar
Moderator

Joined: Tue Jun 26, 2007 7:08 pm
Posts: 1020
Location: United Kingdom
Amazing tutorial there, EXTREMELY detailed, smashing work!

Might have a try of this in a minute :D probably make it crash and all aliens run out and fall n die :( lol so evil :D


Offline
 Profile My Photo Gallery E-mail  
 
 
 Post subject:
PostPosted: Thu Jul 26, 2007 5:05 pm 
New Dev

Joined: Sun Jul 16, 2006 6:54 pm
Posts: 32
Thanks. I might get around to writing a follow-up tutorial sometime soonish.


Offline
 Profile  
 
Display posts from previous:  Sort by  
Quick reply
  
Post new topic Reply to topic  [ 8 posts ] 



Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron



Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Portal by phpBB3 Portal © phpBB Türkiye