Make your own reusable classes using Flash and AS3

First useful class: ClipDragger
Now we're going to write our first truly useful class. Choose File, New, then Actionscript File. This class, when applied to a MovieClip, will make that MovieClip draggable with the mouse. This is a relatively simple thing to do using frame code in a fla file, and chances are you already know how to do it, but I chose it for an example because it is so simple, and we're just getting the hang of classes and adding complexity very gradually.
Type the following into the script window:package com.mysite.mouse {
public class ClipDragger {
public function ClipDragger(clip:MovieClip) {
trace("ClipDragger working");
}
}
}
Now click File, Save As. Navigate to the mysite folder and create a new folder called "mouse." Double click the mouse folder to enter it, and save the file as ClipDragger.as. Next, open a new Flash document. Let's test ClipDragger and see if we get our trace message this time:
import com.mysite.mouse.ClipDragger;
var clipDragger:ClipDragger = new ClipDragger();
When you run this, you will get the following error message:
1046: Type was not found or was not a compile-time constant: MovieClip.
When you’re just starting with classes, you will get a lot of error messages. They’re a fact of life, but as you progress and learn what the problems are, you’ll get fewer and fewer, and you’ll know what to do about them. But you know what? Although you might never get away from them completely, they’re actually a good thing, because this prevents your code from being compiled with a mistake in it. In this case, the problem is that we’ve told Flash that we’re going to be sending the name of a MovieClip as a parameter, and, since our class is in a separate package from everything else, Flash acts as though it’s never heard of a MovieClip! Imagine that! So the solution is to add an import statement that imports the MovieClip class. Change the code in the AS file to the following (add the import line):
package com.mysite.mouse {
import flash.display.MovieClip;
public class ClipDragger {
public function ClipDragger(clip:MovieClip) {
trace("ClipDragger working");
}
}
}
Save the file, and try running the fla file again. Oops, another error message:
1136: Incorrect number of arguments. Expected 1.
The problem here is that we indicated in our class file that we would be passing in the name of a MovieClip instance to drag, but neglected to do it. So, now let’s fix that. In the fla file, draw something on the stage, anything at all will do. Select it and convert it to a MovieClip symbol. Give it an instance name of “myClip” and change the code to the following:
import com.mysite.mouse.ClipDragger;
var clipDragger:ClipDragger = new ClipDragger(myClip);
(NOTE: Make sure you've drawn something, converted it to a MovieClip symbol, that it's on the stage, and that you've given it an instance name of "myClip" in the properties panel)
This should run without any errors, and give you an output window that traces the message “ClipDragger working.” Sorry if all of this seems overly simplistic, but my aim here is to start with simple examples and build complexity very gradually. Besides, if you’ve never programmed with classes before, this should all be starting to make sense to you, possibly for the first time ever. Our ClipDragger class now has the proper communication with the fla file, but obviously, it doesn’t drag anything yet. Let’s move on and add that functionality.
But first, a brief aside: The purpose of any class is to create objects from that class, and objects have properties and methods. Probably you’ve been programming using Flash’s built-in classes for some time now, and you know how to create an object of a class, then call upon the properties and methods of that class to make the instantiated object do things. Each object gets its own copy of every property and method, and the public properties and methods are the ones that we can access from external code.
This is going to be the same thing, only now we’re creating our own class that we can instantiate objects from, and call upon our own properties and methods. So the first modification to ClipDragger will be to give it a property. This property will be of the MovieClip type, and it will be a reference to the MovieClip object that we pass in as a parameter. To achieve this reference, first we declare in the variable list that there is such a property, then in the constructor, we set that property to be equal to the MovieClip that’s passed in.
Note that the name that we give the property ought to be different than the name that we use for a parameter, so we’ll just call the property by the same name, only precede it with an underscore. This way, the two names (“clip” and “_clip") are different, and we can tell at a glance that the one with the underscore is the one that belongs to the class as a private variable. We make the property private because all of the operations that will be performed on it will happen inside this class. There is no reason to expose it to external code. So our class code becomes:
package com.mysite.mouse {
import flash.display.MovieClip;
public class ClipDragger {
private var _clip:MovieClip;
public function ClipDragger(clip:MovieClip) {
_clip = clip;
}
}
}
So, every instance of ClipDragger will have as one of its properties a reference to whatever MovieClip instance we pass to it as a parameter. Let’s go on to make our passed in clip draggable. This can be done simply by adding event listeners to it, which you probably already know how to do in a fla, but may have never tried in the context of a class before, but it’s basically exactly the same thing. The event listeners will be added right inside the constructor, so that every time a new instance of this class is created, the clip that is passed as a parameter will automatically have all the event listeners added to it that it needs to give it drag and drop behavior. First let’s attempt to make the clip drag whenever the mouse is pressed down on it:
package com.mysite.mouse {
import flash.display.MovieClip;
public class ClipDragger {
private var _clip:MovieClip;
public function ClipDragger(clip:MovieClip) {
_clip = clip;
_clip.addEventListener(MouseEvent.MOUSE_DOWN, drag);
}
private function drag(event:MouseEvent) {
_clip.startDrag();
}
}
}
Save this file, then run the fla again. I said “attempt” above because I knew this would generate yet another error:
1046: Type was not found or was not a compile-time constant: MouseEvent.
The problem is that we’re attempting to use mouse events without first importing them. As you write your classes, you’ll start to get the hang of realizing when you need to import another class, and you’ll soon learn all their locations as well. In this case, we need to add this line:
import flash.events.MouseEvent;
Add that import statement to the AS file, and save it again. Each time you alter an AS file, you need to save it, or else when you run the fla, it won’t be using the new changes you’ve made. CTRL-S is a helpful keyboard shortcut for File/Save. Also, you may or may not ever have noticed this, but when a file has changed and it hasn’t been saved in its current form, there is a little asterisk next to the file’s name on the tab in the Flash authoring environment. This is typical of many other applications besides Flash. If you already knew it, sorry to bore you with it, but if you didn’t, you’ve got to admit it’s a handy indicator.
So when you save that file and run the fla, this time you should have a draggable clip. Okay, yes it’s draggable, but it doesn’t drop when you release the mouse button. We’ll add that next.
Here’s another aside: You may already know that to create the drop functionality, you use the MouseEvent.MOUSE_UP event. You may also know that you don’t necessarily want to add this event to the clip itself, but rather to the stage. This is because the user of your program might drag the clip at a high rate of speed, then release the mouse button and, if at that point, the mouse cursor isn’t actually over the clip, the MOUSE_UP event won’t register and the clip will continue dragging. Adding the event to the stage instead takes care of this problem.

