convert code in adobe flash 9 live docs to class file

Playing around with ActionScript 3.0 but haven’t bought Flash CS3? Me too. One day I will buy the update, because I like the combination of visual and coding tools. For now, though, my experiments with AS 3 are done using the free flex sdk and textmate (described previously).

Thing is, the code samples in Adobe live docs assume we’re using the Flash IDE to compile it. It’s formatted to be copied and pasted onto a timeline frame. So I thought I’d jot down the steps necessary to get that code into shape for compiling with the sdk.

As an example, I’ll use the code sample provided for the droptarget property (I got there via the AS 3 Language Reference > Movie Clip > Public Properties > show Inherited Public Properties). By the way, download the docs, the online live docs are not very lively, i.e. excruciatingly slow.

The first step is to copy the sample code into a file, let’s name it DropTargetTest.as. Here’s what the sample code starts out like:

import flash.display.Sprite;
import flash.events.MouseEvent;

var circle:Sprite = new Sprite();
circle.graphics.beginFill(0xFFCC00);
circle.graphics.drawCircle(0, 0, 40);

var target1:Sprite = new Sprite();
target1.graphics.beginFill(0xCCFF00);
target1.graphics.drawRect(0, 0, 100, 100);
target1.name = "target1";

var target2:Sprite = new Sprite();
target2.graphics.beginFill(0xCCFF00);
target2.graphics.drawRect(0, 200, 100, 100);
target2.name = "target2";

addChild(target1);
addChild(target2);
addChild(circle);

circle.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown)

function mouseDown(event:MouseEvent):void {
    circle.startDrag();
}

circle.addEventListener(MouseEvent.MOUSE_UP, mouseReleased);

function mouseReleased(event:MouseEvent):void {
    circle.stopDrag();
    trace(circle.dropTarget.name);
}

If you try to compile that, you’ll get an error like this:

Error: A file found in a source-path must have an externally visible definition. If a definition in the file is meant to be externally visible, please put the definition in a package.

Can you tell what that means? It’s about the way AS 3 code needs to be in a package. So first step, add the package code, like this:

package{
    // all that code up there}

And compile again. Next error looks like this:
Error: A file found in a source-path can not have more than one externally visible definition. circle;target1;target2;mouseDown;mouseReleased

Hmmmm. Not sure what that tells us, but we need to put this all into a class anyway, so let’s do that now. So right after the import statements we’ll make a class called DropTargetTest, like this;

package{

    import flash.display.Sprite;
    import flash.events.MouseEvent;
        class DropTargetTest{
            // the rest of the code that comes after the import statements

    }

}

OK, compile again… This time there’s a pile of errors about accessing undefined properties, like this:
Error: Access of undefined property circle.

circle.graphics.beginFill(0xFFCC00);
^
Same for target1 and target2. Plus there’s a couple errors about possibly undefined methods, but we’ll get to that in a sec. First, let’s try something. Let’s separate out the declarations of objects and methods from where we actually use those objects and methods. What we need here is a constructor, the method that creates an instance of a DropTargetTest object. In the constructor we can then do things with the sprites and things we’re creating in this class.

So we’ll declare the variables and methods outside the constructor, giving them an access modifier of private. Then we’ll create a constructor where we’ll move all the code that actually makes things happen with the variables and methods.

Here’s what it looks like:

package{
    import flash.display.Sprite;
	import flash.events.MouseEvent;

	class DropTargetTest{

                // declare circle and co.
		private var circle:Sprite = new Sprite();
		private var target1:Sprite = new Sprite();
		private var target2:Sprite = new Sprite();

		// constructor, where we'll actually do things
		public function DropTargetTest(){
		    circle.graphics.beginFill(0xFFCC00);
			circle.graphics.drawCircle(0, 0, 40);

			target1.graphics.beginFill(0xCCFF00);
			target1.graphics.drawRect(0, 0, 100, 100);
			target1.name = "target1";

			target2.graphics.beginFill(0xCCFF00);
			target2.graphics.drawRect(0, 200, 100, 100);
			target2.name = "target2";

                       	addChild(target1);
		        addChild(target2);
		        addChild(circle);

		        circle.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown) ;
		        circle.addEventListener(MouseEvent.MOUSE_UP, mouseReleased);
		}

                // other methods, in this case callback methods for the circle
		private function mouseDown(event:MouseEvent):void {
		    circle.startDrag();
		}

		private function mouseReleased(event:MouseEvent):void {
		    circle.stopDrag();
		    trace(circle.dropTarget.name);
		}
	}
}

Now compile again. Whew, less than 20 errors, cool. The error now tells us about a possibly undefined method:
Error: Call to a possibly undefined method addChild.
addChild(target1);
^

But wait a minute! Do we have to define addChild?! Yikes, no, that’s a “standard” method that we use to add display objects to the display list. So why doesn’t the compiler let us use that method? Hmmm. It’s not part of our class, that’s for sure. DropTargetTest only defines those 2 callback methods. Aha!

Our class needs to use the methods available to any class using display objects, in this case Sprite. So we’ll have to extend our class, ie make it a subclass of Sprite, so we can use all its handy methods like addChild. Let’s try that.

One the line where we declare our class, we’ll add the code to extend the Sprite class:

    class DropTargetTest extends Sprite {

And now we compile again… Bring on those errors!

Aha, no errors, but a few warnings. And they’re saying something about where the class and some methods will be scoped to:

Warning: class ‘DropTargetTest’ will be scoped to the default namespace: internal. It will not be visible outside of this package.

Same warning for the methods mouseDown and mouseRelease. Scope, hmmm. Sounds like we need to specify more explicitly what kind of access we want the class and these functions to have. Less make them public, like this, adding public to each declaration:

    public class DropTargetTest extends Sprite {

    public function mouseDown(event:MouseEvent):void {

    public function mouseDown(event:MouseEvent):void {

See what the compiler thinks of that…

Bingo! We got a swf compiled from the class file. If only we could add flash file to wordpress hosted blogs so you could see what it looks like. You’ll just have to do the conversion yourself.

So to sum up what we need to do to move from timeline code from livedoc samples to class files:

  1. Add package code.
  2. Add a class declaration. Make sure the class extends Sprite (or MovieClip, if necessary).
  3. Create a constructor.
  4. Separate out variable and method declarations from code that uses them…
  5. …put the code that does stuff with the variables and methods into the constructor.
  6. Make variables private. Make the class and its methods public.

Did I miss anything? Of course it waaaay quicker if you just grab that sample code from the docs and throw it on a timeline frame. But if you’re wanting to work with classes anyway, why not start playing with AS 3 classes?

Advertisements
This entry was posted in flash, actionscript, flex and tagged , , , . Bookmark the permalink.