Writing a class to control a library symbol

view all »


Most of us, when we start working with Flash, do everything on the timeline. And that’s fine. Plenty of superb applications have been created in that way.

But as soon as your program goes beyond the very simple, putting all of your code on the timeline can make things more complicated than they need be. Finding the particular piece of code you want to edit can be tricky, and if you return to an application some time after you first wrote it, simply working out how it works can cause a few headaches.

The alternative is to create your own classes, and put your code in class files.

In this tutorial I want to show you one example of writing your own class. I’m going to show you how and why you might write your own class to control a library symbol.

One of the many things I love about Flash is that it’s turned me into an artist.

Here’s my latest creation. A fish:

Flash Fish

Pretty awesome, eh? OK, I must admit nobody’s ever going to mistake it for a Rembrandt but if you could see my usual standard of drawing you’d have to concede that it’s not bad.

In fact, I’m so pleased with it I decided to store it in my Library just in case I ever want to do anything with it.

So to start the tutorial, open a new .fla file, draw your own fish, and use Convert To Symbol (f8) to save it as a movie clip in your library with the name Fish. (In the Convert To Symbol dialogue box, check the Export For ActionScript box and name the Class ‘Fish’ also.)

convert to symbol

Now delete the fish that’s on the stage so that you have a .fla file that’s completely empty apart from the Fish symbol in the library. Set the background colour to a nice pale blue – that’s going to be the water for our Fish to swim around in.

In the Actions panel for frame 1 of your .fla file, write the following code:

var myFish:Fish = new Fish( );
addChild(myFish);

Save your .fla file under the name FishTester.fla

We started off by saying that we wanted to write our own class for our fish. That means we’re going to put in one place, all the code that will allow our fish to do all the fishy things that fish do.

It’s worth pointing out that actually, we already have a Fish class. Why? Because Flash created one for you as soon as you decided to store your Fish symbol in the library. Without it, the code you’ve just written on the Actions panel of frame 1 wouldn’t work. It’s because Flash created that Fish class for you that you can use

new Fish( )

to magic up a new instance of the Fish class anytime you want.

But that’s all you can do with your class at the moment.

We want to do more. And for that, we need to write our own Fish class which will effectively replace the class that Flash produced.

OK, let’s jump in and take a look at our Fish class.

Open up a new Flash file by clicking on FILE >>>NEW and selecting ActionScript File.

Flash Screenshot

In your empty ActionScript file type the following code

package
    {
    import flash.display.*;
    import flash.events.*;

    public class Fish extends MovieClip
    {

      public function Fish( )
       {

       }

    } // end class
} // end package

Save this file in the same directory as your FishTester.fla file, but give it the name Fish.as

(For now, it’s essential that you save it in the same directory as FishTester.fla, and just as important that you give it exactly the same name as the library symbol.)

You may be thinking that our Fish class looks a little, well, empty.
That’s because it is. But listen, we want our fish to DO something. (It’s called ActionScript for a reason, right?)

Before we go any further let’s just point out four things about the structure of our class.

First, that word ‘package’ is just a way of gathering together all the classes that we might need in our project. In this simple case we haven’t given our package a name, but we could do if we wanted to. We might call it ‘FishProject’ and use the same package name every time we wrote a class that we were going to use in that project. For now, to keep things simple, we won’t give our package a name.

Secondly, we know that our class is going to need code that has already been written by those awesome coders at Adobe, so we make a point of mentioning that fact with two ‘import’ statements. They’re just a way of saying, “Look, for this class to work properly, we’re going to need access to all of the display and events code written by the Flash developers.”

The third thing to note is that we’ve made a point of saying our Fish class ‘extends’ the MovieClip class. That’s just a fancy way of saying that our Fish is going to be a MovieClip, able to do all of the things that MovieClips can do, PLUS it’s going to be able to do the very specific things we’re going to add in this class file.

And finally, note that at the heart of our class there’s a special function called Fish ( ). That function – which at the moment is completely empty – is called the constructor. It’s special in the sense that every time we create a new instance of our Fish class, the constructor will automatically be called, and any instructions we’ve placed in there will be executed.

Let’s get our constructor to do two things.

First, let’s get the constructor to decide where the fish will be placed on the stage. Add the following code:

        public function Fish( )
       {
          // the fish decides where it starts
           this.x = Math.floor(Math.random( )*550); // 0 - 549
           this.y = Math.floor(Math.random( )*400); // 0 - 399
       }

Notice that my stage is 550 pixels wide x 400 pixels deep.

If you’re using different dimensions you’ll need to change the constants in that code to match the size of your stage.

And secondly, let’s get the constructor to send us a short message as soon as the fish has been placed on stage. Add a trace statement so that your constructor looks like this:

 public function Fish( )
        {
            // the fish decides where it starts
            this.x = Math.floor(Math.random( )*550); // 0 - 549
            this.y = Math.floor(Math.random( )*400); // 0 – 399

            trace(“Your new fish is in position”);
}

Save your class file and then test your movie.

Trace in flash

You should see that trace statement in the Output panel, proving that your class file is working.

Every time you run the movie, the fish will appear on stage in a different position.

Notice that you haven’t had to change anything on the timeline. All of your changes are occurring in the class file.

Now let’s add an instance variable. An instance variable is a variable which we define in such a way that every instance of the class (every Fish in our case) will have its own version of the variable.

We’re going to want our Fish to swim. But if we have more than one Fish on screen at the same time, life’s going to be more interesting if they swim at different speeds. So we’ll make ‘speed’ an instance variable. Then one Fish might have a speed of 10 and another might have a speed of 50 (or whatever). Different Fish, different speeds, different values of their instance variable.

Declaring an instance variable couldn’t be easier.

Add the following line of code at the top of your class file, like so:

    public class Fish extends MovieClip
   {
        var speed:int; // how fast the fish is moving

public function Fish( ) // constructor
      {
          …..
       }
}

Save your class file and test your movie.
Declaring that instance variable seems to have made no difference. The fish is still stationary. That’s because we haven’t yet added any code that makes the fish move. Let’s do that now by adding a method.

A method is a function. It’s a chunk of code, within the class, which causes the Fish to do something.

Edit your class file so that it looks like this:

package
{

    import flash.display.*;
    import flash.events.*;

   public class Fish extends MovieClip
   {
       var speed:int; // how fast the fish is moving

        public function Fish( ) // constructor
        {
            // the fish decides where it starts
            this.x = Math.floor(Math.random()*550); // 0 - 549
            this.y = Math.floor(Math.random()*400); // 0 - 399

          // give the fish a speed, picked at random
          speed = Math.floor(Math.random()*5) + 1; // 1 - 5

            // add an event listener to keep calling the
            //'move' function
            addEventListener(Event.ENTER_FRAME,move);

} // end constructor
        function move(e:Event):void
       {
          // make the fish move
           this.x += speed;

      } // end move

    } // end class

} // end package

We’ve made a number of changes.

We’ve declared a class variable called ‘speed’.
We’ve got our constructor to decide what the value of ‘speed’ will be.
We’ve also got our constructor to add an event listener so that every time our movie enters a new frame, the move function (or method) gets called.
We’ve added the move method itself.

Notice that the move method itself is not part of the constructor. It’s a separate function. We can have as many functions as we want within one class, each with its own pair of curly brackets.

Save your class file and test your movie.

In fact, test your movie a few times and notice that although the speed of the fish varies, it always swims left to right. We definitely want to change that. It’s going to be more fun if some fish swim left to right and some swim right to left. We might also mention that as a rule fish don’t just swim out of the tank when they reach the far end, so that’s something else we want to alter.

Let’s introduce another class variable, called ‘direction’.
Direction will have one of two values.
+1 means the fish is swimming from left to right, and -1 means right to left.

How will we decide which direction to give our fish? We won’t. We’ll let the constructor make that decision.

Make the following changes:

Declare the class variable Direction, immediately underneath the declaration of ‘speed’.

var direction:int;

and add the following code to our constructor

// choose an initial direction for the fish
      if(Math.random( ) < 0.5)
     {
          direction = 1;  // 50% of our fish will start off
//moving left to right
     }
  else
   {
          direction = -1; // the other 50% will start off moving
 //right to left
 }

change the ‘move’ function so that it reads as follows:

            this.x += speed * direction;

Notice that if direction = -1, the move function now moves the fish from right to left, which is what we want.

delete that trace statement telling us that our fish is in position. We don’t need it anymore.

Save your class file and test your movie.

Test your movie a few times and notice that fish moving right to left seem to be swimming backwards. That’s not behaviour we’d wish to encourage, obviously, but it’s due to the fact that our library symbol has the fish facing to the right, so that’s how it appears on stage.

We need to add something to our constructor function so that if the initial direction is -1 (right to left) we ‘flip’ the fish round before it starts moving, so it’s facing in the right direction.

We can flip any symbol by setting its scaleX value to -1.

Once we’ve made that change, the part of our constructor which sets the initial direction should look like this:

// choose an initial direction for the fish by ‘flipping a coin’
   if(Math.random( ) < 0.5)
   {
      direction = 1;  // 50% of our fish will start off
//moving left to right
   }
  else
  {
     direction = -1; // the other 50% will start off moving
 //right to left
// and they need to be facing the right way before they start
this.scaleX *= -1;
}

Save your class file and test your movie.

OK, it would be nice to think that at this stage you’re itching to get more than one fish on stage at the same time.

Let’s go back to our Actions panel on frame 1 of our timeline.

All we have there at the moment is this:

var myFish:Fish = new Fish( );
addChild(myFish);

We haven’t changed that since right at the start of our tutorial.

Let’s change it now.
Let’s be terribly reckless and have TWO fish swimming around.

Add the following code to your Actions panel:

var mySecondFish:Fish = new Fish( );
addChild(mySecondFish);

In fact, let’s really throw caution to the wind and have THREE fish.

Add the following code to your Actions panel:

var myThirdFish:Fish = new Fish( );
addChild(myThirdFish);

Save your .fla file and test your movie.

One class, many instances of that class.

However, I’m sure that like me you’re not happy about fish being able to simply swim out the side of the tank like they’re doing at the moment. Let’s stop that happening by modifying our move function. Every time a fish moves, let’s test to see if it’s bumped up against the sides of the tank, and if it has, let’s turn it round and set it swimming back the other way.

Firstly we need to change our ‘move’ function so that it reads as follows:

function move(e:Event):void
{
      //make the fish move
      this.x += speed * direction;

     // has it reached either side of the tank?
   if(this.x < 0 || this.x > 550)
    {
          // change direction
       turnRound();
    }

}  //end move

(And again, that figure of 550 refers to the width of my stage.)

Notice also, that for this part of our class to work as we want it to, the registration point of our Fish symbol – in other words the point on the Fish which we’re referrring to when we talk about the Fish’s x and y coordinates (marked with a black ‘+’ when you look at the Fish symbol in Edit mode) – needs to be on the tip of the Fish’s nose. If you need to change that, right click on the Fish symbol in the library, click Edit, and drag that black ‘+’ over to the tip of the nose. Then exit Edit mode,

Our new move( ) function calls another function, turnRound( ) if and when we need to turn a fish round.

Here’s what that function looks like.

function turnRound( ):void
{
     // flip the fish round to face the other way
     this.scaleX *= -1;

    // change direction
  this.direction *= -1;

In your version of the Fish class, change the move( ) function and add this turnRound( ) function.

Save your Fish class and test your movie just to be sure that everything’s working OK. It’s still not perfect – the fish disappear off stage for a fraction of a second when we turn them round, so it looks as though they jump outside the tank, but we’ll leave that for the moment.

Let’s make another change to our Fish class. Notice that at the moment all of our Fish are the same size. That’s because they’re all instances of the symbol in the library. We drew that once, and all instances will be identical copies of it. But we can use our class to alter the size of our Fish, using the scaleX and scaleY property.

Add the following lines to your constructor function:

// choose a size for the fish
setScale();

and add the following function to the Fish class:

function setScale():void
{
   // choose scale factors for the fish
   this.scaleX = Math.random( ) + 0.5;  // between 0.5 - 1.5
   this.scaleY = Math.random( ) + 0.5; // between 0.5 - 1.5
} // end setScale

Save your Fish class file and test your movie.

Notice how the setScale( ) function not only changes the size of our Fish, but also their shape, too, because we use different values for scaleX and scaleY. Some fish end up long and thin, others short and fat. (These Fish are almost human … )

At this stage you may be thinking, well, this is all well and good, but there’s nothing here that I couldn’t simply code on the timeline. And you’re right. But only up to a point. If our application got more and more complicated – and let’s face it, it could hardly be any simpler than what we’ve got so far – then continuing to code everything on the timeline could get very messy.

Let’s take a quick look at how writing your code in classes can really pay dividends when it comes to adding a little more complexity to your application.

Fish are living creatures. They breathe. To show that they’re alive, we might want them to give off bubbles of air every so often.

What would be the quickest way to add that sort of feature? Easy – create a Bubble class.

You already know something of what it will look like.

Here’s my version:

package
{

    import flash.display.*;
    import flash.events.*;

   public class Bubble extends Sprite
    {
        public function Bubble(startX:int, startY:int)
// constructor
        {
            // draw a circle
            this.graphics.lineStyle(1,0x000000); // 1 pixel
//wide, black
            this.graphics.beginFill(0xadebf8);
// same colour as the water in my tank (ie. the
//background colour of my .fla file)
            this.graphics.drawCircle(startX,startY,5);
           this.graphics.endFill();

           // add an event listener to move bubble upwards
          addEventListener(Event.ENTER_FRAME,move);

       } // end constructor

      function move(e:Event):void
     {
           // move the bubble upwards
            this.y -= 5;
        }

} // end class

} // end package

It’s much simpler than the Fish class. But it contains the package statements, and an import statement, and it has a constructor. The constructor of the Bubble class does two things – draws a circle (which is the bit involving all those graphics statements) and adds an event listener which causes the move( ) function to be called.

Notice that the move( ) function I’m talking about here is not the move( ) function we saw in the Fish class, but a separate move( ) function which is part of the Bubble class. The move( ) function in the Bubble class simply moves the Bubble 5 pixels towards the top of the stage.

Create your own version of the Bubble class by opening another ActionScript file, copying the above code, and saving the file under the name Bubble.as in the same directory as your FishTester.fla and Fish.as files.

So now we have two classes. A Fish class and a Bubble class. But if you test your movie you won’t see any Bubbles. For that to happen we need to get the Fish to breathe out. How? Simple. We’ll add another function to the Fish class.

function breatheOut( ):void
{
    // create a bubble
    var myBubble:Bubble = new Bubble(this.x, this.y);
    // add it to the stage
    MovieClip(root).addChild(myBubble);
}

Notice that the constructor in the Bubble class takes two parameters, which serve as the starting coordinates of the bubble when it’s placed on the stage.
When we call the breatheOut( ) function in the Fish class, we pass the Bubble class the Fish’s own coordinates. That way, when the Bubble appears on stage it looks as though it’s coming out of the Fish’s mouth.

How often do we call this breatheOut( ) function?

Well, that’s up to you, but I decided to call it only occasionally so I added this code to the Fish’s move( ) function:

// breathe out occasionally!
   if((this.x > 20  &&  this.x < 22) || (this.x > 250  &&
this.x < 252) || (this.x >500  && this.x < 502))
{
   breatheOut();
}

Every time we move the Fish, we check to see whether its x coordinate is within one of three narrow ranges, and if so, we get the Fish to give off a Bubble.

And that’s the end of our very simple FishTester application. You’ve created two classes, and got them working together. Notice once again that there’s very little code on the timeline.

Maybe you’d like to go back to the Timeline and create a whole tank of fish.
If so, delete the code that you currently have in your FishTester.fla file and replace it with the following:

var Fishes:Array = new Array( );
for(var f:int = 0; f < 20; f++)
{
Fishes[f] = new Fish( );
}

Save your .fla file and test your movie.

I’m sure there are lots of ways you could improve your Fish and Bubble classes.

What about altering the way a fish’s initial position is chosen so that they always start off completely inside the tank (instead of starting off outside the tank and swimming into it through the side!)?
What about altering the way fish turn round, so that they stay strictly within the bounds of the tank?
What about changing things so that the greater the fish’s speed, the more often it breathes out?
What about altering the Bubble class so that Bubbles are not all the same size?

Whatever changes you make, I hope you’ll agree that having your code in classes makes things much easier than if you worked entirely on the timeline.

Have fun!

Tutorial by Sam Pollard

Sam Pollard is a Maths tutor in Leeds, UK.
His main interest in Flash is creating games to promote the teaching and learning of Mathematics.
You can see his latest efforts at www.sampollard.net

Did you find this tutorial useful? Do you have any questions about the tutorial or a request for another? Please sign up now and post your comments below!

Vote in HexoSearch Help me out by voting for this tutorial

Did this post help you? If so help us continue to grow and Digg this page or Share on Twitter!

If you haven't already, sign up to our RSS feed or register to recieve updates direct to your email!

10 Responses to “Writing a class to control a library symbol”

  1. yang

    Great tut. Really comprehensive.

  2. zilchvortex

    Awsome tut Sam is there anychance you could make a trigonometry tutorial

    thank you
    josh.


  3. Thanks for the feedback guys. Much appreciated. Not sure exactly what the next tutorial will be about but I’ll certainly add Trigonometry to the list. Thanks again.

  4. Robert Anthony

    Nice tutorial; however, I cannot seem to get the symbol to appear. I created a simple object called “Circle”, saved it to the library, along with correct linkage identifier and class (Circle.as). But it does not show up when I compile the FLA. Any suggestions on what I am doing wrong?

  5. Seasons

    Hi Sam
    Great tutorial! I am trying to use it as a part of a small school project I am trying to build. I have one problem, I am trying to use this as a part of the project so when I write

    public class Game extends MovieClip{

    public function Game( ){
    // the fish decides where it starts
    this.x = Math.floor(Math.random( )*500); // 0 - 499

    Because of “this” the whole screen shifts to a random place. I have created the Fish movie clip. Can I not just try and add that name in somewhere, so it knows which movieclip to randomize?


  6. we could do if we wanted to. We might call it ‘FishProject’ and use the same package name every time we wrote a class that we were going to use in that project. For now, to keep things simple, we won’t give our package a name.


  7. great tutorial sam .thanks for the coding it will help me alot thank you sam once again.you got anything about FLEX the upgrade version.
    kids internet games

  8. john

    hi

    am stuck on the turnRound function. i can’t get the fish back on the stage and flip direction


  9. I love how the tutorial started out. Very indepth and explanitory! but I noticed as the tutorial proceeded that you stopped explaining everything. I would have loved if the indepth attitude continued, I think that If so, it would make this blog much more valuable and more cherished than other tutorial sites.


  10. It’s cool. What is the salary of a flash programmer? It is interesting job..

Leave a Reply