The Document Class

Next, we need to write a document class for our FLA file. In flash, choose File, New, and then ActionScript File. Type in the following:

package {
	import flash.display.*;
	import flash.events.*;
	
	public class Main extends MovieClip {
		
		public function Main() {
			trace("works");
		}
	}
}

This is almost the same structure as before. One difference is that we don't need the ADDED_TO_STAGE and REMOVED_FROM_STAGE event listeners here. The reason is that we are going to be setting this class as the document class. The document class represents the main timeline of the FLA file. As such, it has already been added to the stage automatically. In other words, there will never be a need to detect when this object is added or removed from the stage. It's already on the stage. In fact, this will be the controlling code I talked about earlier, that will be doing all the adding and removing of the other screens!

Inside the constructor, I have just placed a trace command that is simply to get feedback that the document class is indeed linked to the fla file and working properly.

Save the above file as Main.as. Once again, save it to the same folder as the FLA, of course. Next, let's link this file to the FLA file. Go back to the FLA file in Flash, and click somewhere on the area around the stage. This will select the FLA document itself, so that the properties panel says "Document" at the very top.

In the Class field, enter the word "Main" (without the quotes, and don't include the .as file extension.

Press CTRL-ENTER to test the movie. You should get the word "works" traced to the output window. Now we can proceed to use this document class for better things! So, back in the Main.as file, go ahead and delete the trace command. We will now instead use the document class to create an instance of our Intro screen, and put it on the display with addChild(). Notice that we list the variable in the variables list. That way, we can use the variable inside of other functions throughout the class:

package {
	import flash.display.*;
	import flash.events.*;
	
	public class Main extends MovieClip {
		private var intro:Intro;
		
		public function Main() {
			intro = new Intro();
			addChild(intro);
		}
	}
}

Again, save the file, and test the movie. You will notice that the screen does indeed get added to the display, but only occupies the upper left hand quarter of the stage. Three quarters of it is off the stage to the upper left!

This is because we designed the screen with the registration point in the middle. While this makes designing easier (because we can use the align panel for centering things on the stage), on the developing side it might be better if the whole screen had its registration point in the top left. But we can also keep our centered registration point, and just adjust the x and y values with code to center it on the stage. In fact, this will be a great test of the ADDED_TO_STAGE handler in the Intro.as file.

Edit the Intro.as file again. Add the following two lines to the addedHandler function:

package {
	import flash.display.*;
	import flash.events.*;
	
	public class Intro extends MovieClip {
		
		public function Intro() {
			addEventListener(Event.ADDED_TO_STAGE, addedHandler);
			addEventListener(Event.REMOVED_FROM_STAGE, removedHandler);
		}
		private function addedHandler(event:Event):void {
			this.x = stage.stageWidth / 2;
			this.y = stage.stageHeight / 2;
		}
		private function removedHandler(event:Event):void {
			
		}
	}
}

The word "this" is a reference to the object itself. When objects are created from this class, each object gets a copy of all the code in this class. So for each instance created (the word "instance" and "object" are synonymous), the word "this" is a self-reference. Like I said before, there will only be one instance of this screen created, but you should understand how the keyword "this" works. The word "this" does NOT mean this class, it means this instance. The word "this" could also have been omitted, in which case it would be "understood" :

x = stage.stageWidth / 2;
y = stage.stageHeight / 2;

These two added lines would not work if you were to place them in the constructor. You are welcome to place them there, save the file, and give it a try. You will get the notorious "null object reference error." Let's understand why. First, our class inherits from the MovieClip, so it is a MovieClip. As such, it inherits all of the properties and methods of the MovieClip class. One of those properties is the "stage" property. The stage property for a MovieClip instance that is not on the display list will have a null value. There are two ways to get a MovieClip instance onto the display list: by dragging it physically from the library to the stage at authoring time, and by creating it with code and adding it with code, specifically the addChild() command. In either case, the stage property goes from being null, to being an actual reference to the main stage object. But in the case of the one that is created with code, there is that small space of time in between the object's creation (the "new" command) and it's being added to the display list (the "addChild" command) during which the stage property is still null. But the moment the object is added with addChild(), its stage property is "filled out" (or given a value) and now refers to the actual stage. It is the ADDED_TO_STAGE event that detects this very moment that the addChild happens from the outside code.

So, to sum up, and to make it relevant to what we are doing, when the controlling code says:
intro = new Intro();
...the constructor of the Intro class runs. And when outside code says:
addChild(intro);
...the addedHandler function inside the Intro class is triggered and runs. In our application, we will only be using the new command once, as we will only be making one instance of the Intro screen. But addChild() and removeChild() might run any number of times, depending on how many times the user clicks the buttons to switch screens. Having these events that detect when addChild() and removeChild() happen from the outside means that we can do whatever kind of housekeeping we want inside these functions.

Unlike timeline frames, class files are a scope of their own. This means that you can reuse the same variable names and function names in your other classes. Only the variable names and function names within the same class have to be unique from each other. This is what makes things all very nice and modular. With a few minor changes to the document class, you can expand your program by adding more screens, or taking them away. There is never a need to worry that things might clash with each other. Classes are all nice and encapsulated that way. By default, they don't share information with each other, and later I will show you how to make them share with each other just the information you want.