Classes


OOP is based on the concept of a class. A class is a description of what an object should contain. Think of classes as templates. If I need to make a swarm of invading Aliens for a game, all of them must have identical code. As each enemy is spawned, it's better to tell the new movie clip that it is initialized as an instance of the alien group (class). This immediately grants the enemy instance a whole suite of properties and methods that are specifically suited to the work it is there to do in the application.

Class Functionality

For the next several examples, we'll use the idea of a game in which you have several aliens. Although each type of alien has different abilities and attributes, certain characteristics make all of them aliens. By defining a class for aliens, we can say that all aliens need to be able to do the following:

  • Move toward the good guy.

  • Fire a shot at the good guy.

  • Do something when the good guy shoots them.

Aliens might also need to know pieces of information such as these:

  • How far is it to the good guy?

  • How fast do I move?

  • How much damage have I taken?

In the preceding descriptions, the concepts have been broken into two groups: things the object needs to be able to do, and things the object needs to know. For a class, doing something is a method (a function), and knowing something is a property (a variable). All objects are composed of these functions and variables . By defining these features in a class, we begin to make a good definition for what the object is.

So far in this book, we've seen several objects that have many properties and methods. Arrays, for instance, are a type of object we've seen before. When we have an instance of an array, we can call its methods. Because the array is of the Array type, it was created with the functions that push and pop data onto arrays, as well as a method that can sort the array. As far as properties go, there is only one: length . length is a variable that is always updated to reflect the total number of elements in the array. In this case, the function push can do something, whereas the property length knows some information and returns a value when called.

The real power of Flash is evident when we start creating our own classes with properties and methods. Let's start by looking at a simple class. We are going to create a class for aliens with a movement method and a property that holds the speed that the Alien is supposed to move. For now, just follow along without writing anything in Flash. Classes are defined in a specific way, and it will be better if we address that topic separately.

Defining a Class

Classes are not defined within the .fla like all code we have seen so far in this book. Instead, classes are written in separate files and called into the .fla by creating an object of that class's data type. Because the question of where to write and save this file is slightly involved, let's start by getting a good grasp of what syntax is used in a class. Then we can talk about actually writing it in the correct place.

Class Syntax

We start with the keyword class followed by the name of the class ”in this case, Alien . After that, we place the curly braces that indicate where the beginning and end of the class definition are.

 class Alien {      //we'll add content here in a moment } 

After that, we can put in the property speed and initialize it to a value of 5. Our movement method will use this later to move five pixels per call. Notice that the line must start with var when defining an instance variable within a class.

 class Alien {      //this property will be initialized in each instance of Alien      var speed = 5; } 

Next, we are going to start adding the functions. First, we need to add a special type of function called a constructor . A constructor runs when a new instance of Alien is created. Because we are working on a simple class now, our constructor is going to be empty.

 class Alien {      //this property will be initialized in each instance of Alien      var speed = 5;      //the constructor is called when a new instance of this class is made      function Alien (){           //this space intentionally left blank ;)      } } 

Flash knows that this function is the constructor because the function name is the same as the class name. Technically, if you include the constructor, Flash's compiler automatically makes a blank constructor on its own.

In the rest of the class definition, you define properties and methods that will be added to your new object when instantiated . In the constructor, you place code that will occur at run-time. For instance, if you want to pass in parameters to your new Alien object, such as its name, initial position, or any other information, you specify these as arguments in the constructor function and then assign them to properties within the constructor function.

Last, we add a move function. For our simplified movement method, let's add the speed variable to the current _y position of the current movie. In the end, our new class Alien will look like this:

 class Alien {      //this property will be initialized in each instance of Alien      var speed = 5;      //the constructor will be called when a new instance of this class is made      function Alien (){           //this space intentionally left blank ;)      }      //this method will be initialized in each instance of Alien      function move() {           _y += speed;      } } 
Caution  

We can't access the function or variable inside the constructor. We can only use what is in the instances that the constructor produced.

Saving a Class Definition

Now that we know what a basic class looks like, we need to talk about where to write them before we can see them in action. Previously, I mentioned that you need to define classes in a particular way. This way is by placing the class definition in an external .as file (.as stands for ActionScript). An .as file is a text file that Flash looks for when it needs a class. Actually, you can only use the syntax for class definitions in .as files; if you tried to define a class in the .fla, you would get a compiler error like the one in Figure 9.1.

click to expand
Figure 9.1: The Output panel tells you that you cannot define a class within the .fla.
Tip  

Because .as files are plain text files, you can write them in whatever text editor you like. Flash provides its text editor for convenience.

In the .as file, you can define only one class. You must write additional classes you want to define in separate files. To create an .as file, go to Flash, choose the File menu, and select New. When the menu appears, select ActionScript File and click OK. A new panel pops up that looks a lot like the Actions panel. While you are working in this file, all your other panels become gray. When you return to an .fla, the panels return to their normal state.

In the text file's panel, you can write the class definition. All the syntax coloring should work as it does in the Actions panel. Write the previous class for Alien in the new file.

 class Alien {      //this property will be initialized in each instance of alien      var speed = 5;      //the constructor is called when a new instance of this class is made      function Alien (){            //this space intentionally left blank ;)      }      //this method will be initialized in each instance of alien      function move() {            _y += speed;      } } 
Tip  

Making variable, class, or function names that are only different based on strict case (that is, alien , Alien , aliEn ) is discouraged. Never use case to differentiate names.

Save your document with the name Alien.as. Make sure that the name of your class and the name of your file have matching capitalization. Flash finds the class definition by looking for a file that has the same name as the class. In Windows and Macintosh, file names are not case sensitive. In Flash, case is strict. This means that Aliens and aliens are different classes to Flash even though your computer can't distinguish between Aliens.as and aliens.as when trying to load the class file.

Where you save the file is an interesting question. For now, just choose a directory where you would create a new .fla for making an alien invader game. You can always put your .as file in the same directory as the .fla that will use the class definition.

You can put your .as file in a few places. Flash has a list of places it searches when trying to use a class. Flash starts by looking in a directory that was created at install in your system directory. The classes there are predefined classes that ship with Flash; you shouldn't place your own class files here. After that, Flash looks at the directory where the .fla is that is trying to use the class. For now, save your class file wherever you want. Just be sure that you can find it again because we will be saving an .fla in the same directory shortly.

Class File Locations

As a preference in Flash, you can set up any directory on your computer to be checked for a class file. As you start to make more applications, you will realize that you are largely using the same classes repeatedly. By setting up a central class directory for yourself, you can place your common classes there and have access to them from any movie where you need them. To set up this preference, go to the Edit menu and select Preferences (see Figure 9.2). From there, click on the tab labeled ActionScript at the top right. At the bottom is a box labeled Language. Select the button labeled ActionScript 2.0 Settings.

click to expand
Figure 9.2: Preferences panel with ActionScript. Settings dialog box open .

Here, you can add your own directories where classes should reside. You can also change the order that the directories are searched by using the arrow buttons in the dialog box. Provided you haven't changed these settings on your own already, you should see two entries. The first is a way for Flash to refer to the directory in the system directory where the predefined classes are stored. After that, you should see a . (dot) entry. This just means the same directory that the current file is in. If you want to add a directory to hold classes you are likely to reuse, click the plus sign and then use the target button to browse to the folder you want to select.

After your entry is in the list, you might want to use the arrow buttons to change the order that Flash checks for class files. You should probably leave . near the top of the list. By making the current directory a high priority, you are always able to make a custom class for a particular application without disturbing the generic class in your custom folder. By searching the local directory first, you can find the custom class first, and the search will stop before it looks anywhere else.

As you create classes in the future, give some thought as to how often you would use that exact class. If the answer is several times, you might want to write the class once and place it in a central folder. If the class is highly specialized, it might make better organizational sense to keep it with the .fla. Keep in mind that if you want to give someone else your .fla, you must also give the person all the appropriate class files. Ease of portability might also play a role as you think of how to organize your class files.

Using Classes in Flash

Now that we have a class file and we know many places to save it, it's time to get to the core of the issue: how to use it. Up until now, we have had all our code in the .fla, so this begs the obvious question: How do we get our class into Flash? I've mentioned that Flash looks for the file in a prioritized fashion, but we haven't really gotten to how to start the searching process.

The answer to this question is both simple and complex. The short answer is that you don't have to do anything. The somewhat more involved answer is that when you export a movie that tries to make use of a class that it doesn't already know, Flash automatically searches for the file. Flash's compiler knows where the file should be by that list of directories in the preferences, but it also knows what the file name will be because the file name has to match the class name (plus the .as file extension). That's why it's essential that you're careful about capitalization and making sure the names match exactly.

Let's see this in practice by creating a new .fla with an instance of our Alien class in it. Start by opening a new file and immediately saving it. Make sure that it is in the same directory as the Alien.as file. Why is it important to save the file right away? Well, before you save an .fla, any tested movies are created in a temporary folder that won't have access to the class file. Because this would cause some problems, it's best to avoid the issue. Actually, if the file isn't there, the instance created would be undefined . This is unfortunate because it will be harder to tell if a class is missing.

Instantiating Classes with new

We can create a new instance of a class in the latest version of Flash in two major ways. We saw the first way ”using the keyword new ”earlier in this book. With new , we can create a variable that is of the Alien type. When we test the movie, this new instance will have access to the speed property and move method. The code for creating the instance myFirstAlien of the class Alien is as follows :

 myFirstAlien = new Alien() 

As you can see, this is the same as creating a new instance of an array or any other object that can be instantiated. To test that myFirstAlien does indeed have the variable and function, let's try tracing out the value of the variable speed in myFirstAlien . Just add the following code below the code that created myFirstAlien :

 trace(myFirstAlien.speed) 

If you try testing the movie, the Output panel should now say 5 . We could call our move method, but this object doesn't have a meaningful _y to modify. That's because I intended this class to be used on a movie clip.

Associating Classes with Symbols

Flash has a new feature that lets you directly associate a symbol with a class, which is a nice time saver. If you add the symbol to the stage, whether manually in the editing environment or at run-time by ActionScript, it can have all its variables and functions predefined. In Flash MX, associating a class with a symbol was only available through ActionScript for duplicated and attached movie clips using registerClass . In the class files that are associated with symbols, you can define event handlers such as onEnterFrame or onRelease .

To associate a symbol with a class, create a quick drawing of an alien. Make the drawing into a movie clip. Now open your Library panel, select your Alien movie clip, right-click it, and choose Linkage. In the pop-up that appears, if you have any of the Linkage check boxes selected, you can specify a class in the AS 2.0 Class text field. Please go ahead and type Alien here. Give the symbol the identifier alienMC . If you want, you can close your Library panel now. From here, we are going to add code to frame 1 of the main timeline.

To instantiate the Alien movie clip, we use attachMovie as usual. When the movie is on the stage, it immediately has access to everything that any member of the Alien class would. Therefore, in frame 1, write the following code. (If you still have the code from when we used new , go ahead and comment it out now.)

 _root.attachMovie("alienMC"," myFirstAlien", 1); trace(myFirstAlien.speed); 

With the trace action, your Output window should say 5 again. Because we now have a movie that has a useful _y property in it, we can make good use of the move method in the Alien class. Let's add one more line below the preceding two that will make myFirstAlien run the move method every frame.

 myFirstAlien.onEnterFrame=myFirstAlien.move; 

The potential of what you can do with classes should be becoming clearer now. This, however, is just scratching the surface. Many more elements make this a useful tool in Flash. Next, we are going to cover the topic of inheritance by extending classes into more specific uses. After that, we'll be finished with the main high-level concepts of the chapter and will focus on the many smaller but important features within the class definitions.

Extending Classes

The class we created in the previous section was intended to be a fairly generic description of an alien. Now we can make additional classes that extend this class to make it more specific and more useful. To extend a class, we make a class and tell it that everything in this class is in addition to whatever class we are extending. If you think of any broad category of objects in real life ”let's say fruit, for instance ”you can make a definition that would fit all fruit. You could then make a new category for apple where you can add definitions that are specific to apples while keeping all the attributes of what it is to be a piece of fruit.

In the previous section, we created the Alien class, which is a pretty broad group of beings. If we wanted to create several specific aliens, it would be redundant to make many similar classes. Most likely, the aliens are going to share many elements; however, the small differences are what will make each alien unique. As an example, let's say that we have three types of aliens:

  • Fallers. These aliens have average mobility and armor .

  • Zappers. These aliens are stationary creatures that can fire an organic cannon on the good guy. Their armor is superior to other aliens.

  • Shrinkers. These aliens have average mobility and light armor. However, when these aliens die, they immediately send two smaller copies of themselves .

Creating Custom Aliens

From these descriptions, we can make a broad range of assumptions about what it is to be an alien, and then we can extend that definition into the three different types. To start out, though, I need to make some modifications to our original Alien class. I want to add a few more features than were originally needed when showing the syntax of a basic class. Here is the new definition; make the same changes in your Alien.as class file.

 class Alien extends MovieClip{       var speed = 5;       var armor = 10;       function Alien (){ //constructor       }       function move() {            _y += speed;       }       function takeHit(amount) {            armor -= amount;            if (armor<0) {                die();            }       }       function die() {            this.removeMovieClip();       } } 

In the first line, you can see all that is required to extend a class. In the last section, we made an instance of the Alien class by setting the class to Alien in the Linkage window for the movie. By doing that, we've sort of told the movie clip to stop being a movie clip and start being an Alien . There seem to be certain parts of movie clips that survive the transition to Alien , but none of the movie clip methods are available anymore. What we are doing here is saying that Alien is actually a subclass of the MovieClip class.

We never had to define MovieClip . The class definition was installed in our system directory when Flash was installed. By making Alien a subclass of MovieClip , we are saying that Alien should have all the properties and functions that any other movie clip does. This is called inheritance . Alien inherits the methods attachMovie , hitTest , and gotoAndStop from its superclass. Think of the superclass as the _parent of the class. We are going to cover a lot more on extending classes, but for now, let's look at what else has been put into the new class definition.

You should recognize speed and move from the original class, but I've added a few other important elements. Because Alien is now going to be a broad description with specific extensions, I want to set up Alien as the default alien. The values for speed and armor are normal in the universe of this game. If speed and armor are not defined in the subclass, the defaults will be inherited from Alien . Also, the manner set up here for the alien to move, take damage, and die are considered usual. As we extend the classes, we can change some of these default assumptions to better suit each of the alien types.

One other element I would like to mention here is the takeHit method. Although the attacking object could do its damage by directly accessing the alien's armor, it is better to have a method that the attacker can access. This way, we can look at the Alien class and see how things work while also being able to assume that no element of the game will fiddle with the settings of the alien without going through this controlled entry point.

With the new Alien class that inherits from the MovieClip class, and subclasses of aliens inheriting from Alien , it's important to keep in mind that what one class inherits from its parent it passes along to its children. Figure 9.3 shows a diagram of how this inheritance overlaps. MovieClip is available to Alien , and both are available to each type of alien. Notice, though, that Faller , Zapper , and Shrinker do not have access to each other because they are not in a parent child relationship to each other.

click to expand
Figure 9.3: Each of the subclasses inherits from its parent, Alien . The subclasses have the features of MovieClip because Alien inherits from MovieClip .

Fallers

Now that we have our new Alien class, we can start looking at our specific aliens. First, we have the Fallers. These aliens are average in every way. Because they don't have special abilities or extra armor or speed, we don't need to extend the class. When we want to make a Faller, we just use the Alien class.

Zappers

Next, we have the Zappers. These aliens are different from the generic aliens in several ways. Zappers need to have their armor increased by a fair amount because they aren't going to move. That immobility means we need to adjust their speed and give them the ability to fire. For the sake of simplicity, I am going to assume that another script is going to call the function that will fire the shot.

Start a new ActionScript file in Flash and save it with the name Zapper.as in the same directory where the Alien.as file is. Because Zapper is a subclass ”a class that is extending another class ”the syntax for defining the class will look a lot like our new Alien class definition. We start by describing the class we are currently making.

 class Zapper extends Alien { } 

After defining the name of the class, you use the keyword extends and then the name of the superclass (the class being extended). If you use the syntax checker in Flash's text editor, it tries to find the superclass's file; if it can't find the file, it generates an error in the Output panel.

Already, the Zapper class has everything that the Alien class has by inheritance from its superclass. It also has everything from the MovieClip class. This is because Alien inherits methods from MovieClip and Zapper in return inherits everything. We don't want to use the inherited speed value of 5. Instead, we need to set the value to 0 so that move can be called in the fashion that is normal for all aliens. If the speed is 0, though, no motion will occur. By our writing the speed variable in the subclass, the value inherited from the superclass is superceded.

 class Zapper extends Alien {      var speed = 0; } 

Next, we need to increase the armor for the Zapper class. We could use the same method that we did with speed, but I think it would be better to make armor for Zapper a relative number to the default. If we set the value of armor here to 20 and then we decide to make the default armor 30, we would put Zapper at a distinct disadvantage . My preference would be to take whatever value is in the Alien class and double it.

Variable declarations in classes have to be compile-time constants. This means that Flash has to have a definite meaning for all expressions when making an instance variable. For instance, you can say 2+3 or even var1*var3 (provided that these variables are already defined in this class or superclass). You can't do things like use += or function calls within these variable declarations. Because what we really need to do is multiply the armor value from the superclass times 2 and store that in the armor variable, we need to find somewhere else to put this code.

The place for this code is in the constructor function. Here, we can place whatever code we want, and at run-time, the code will execute when a Zapper is instantiated. In the constructor, there is an implied call made to the function super that handles the inheritance from the superclass. If you want to, you can write it in, but if you omit it as I'm doing, Flash automatically calls it for you. Unlike in our previous constructor, we are going to add some code here. At this point, we have inherited the value of the armor. Now we can do a simple bit of math to double it.

 class Zapper extends Alien {      var speed = 0;      function Zapper() {           //super() is implicit here           armor *= 2;      } } 

The only thing we have left to do to Zapper is add a function for when the alien wants to fire a shot. I'm going to call this function fire . Zapper doesn't inherit a function called fire , but that is okay. In this case, we are extending on what the Alien class can do to have additional features in Zapper .

 class Zapper extends Alien {       var speed = 0;       function Zapper() {            armor *= 2;       }       function fire() {            //add some code that fires at the good guy       } } 

What happens in the fire function isn't really important here; we are just going to assume it is some fancy code that does what we need it to. That's it for Zapper . It inherited move and die from the Alien class, and because we don't need to alter these in any way from the superclass, we don't need to do anything else in this class.

Shrinker

Last, we have the Shrinker alien class. For Shrinker , we need to modify the armor property and set up the die function to do Shrinker 's extra step of replication before it dies.

With a dividing alien, I don't think I want to give it any chances of defending itself. The challenge with an enemy like that is pure numbers . An armor of 0 should be good. Because 0 isn't really a relative number, as in the case of the armor for the Zapper , I'm okay with just setting the value as a variable declaration outside the constructor. To begin the Shrinker class, open a new .as file and save it in the same directory with the other two class files and make sure that it is called Shrinker.as. The basic elements of the class should look like this:

Tip  

Luckily, even if you misname the file by accident , the syntax checker in Flash gives you an error alerting you that you have a mismatch between the class name and the file name.

 class Shrinker extends Alien {      var armor = 0;      function Shrinker() {      } } 

Nothing in that block of code should be surprising now. We've seen the equivalent of each element in Zapper . Next, let's talk about how a Shrinker alien should perish. After the alien is hit once (the armor is 0, after all), the Shrinker should call a function that makes two smaller copies of itself, and then it should die in the normal way. With Zapper , we saw that we could modify the value of an inherited property by placing code in the constructor. We can also achieve the illusion of modifying the original die function within the Shrinker subclass.

Just to get it out of the way, we should write a function that is a stub for the whole replication process. For now, let's call it createSmallerShrinker . Just like with fire , what goes on in that function isn't really important to this chapter; therefore, I'm going to add another "insert miracle here" step.

 class Shrinker extends Alien {      var armor = 0;      function Shrinker() {      }      function createSmallerShrinkers() {            //add some code to create new Shrinkers      } } 

To make Shrinker 's die step work correctly, we need to call createSmallerShrinkers and then run the die function of the superclass. To do this, we need a way to refer to the superclass Alien . We accomplish this by using the keyword super . super followed by a dot and then a function name from the superclass calls that function even if a function with the same name is defined in the subclass. This means that Shrinker can have its own version of die that calls createSmallerShrinkers . While still in the die function, we can make a call to the die function of Alien .

 class Shrinker extends Alien {      var armor = 0;      function Shrinker() {      }      function die() {           createSmallerShrinkers();           super.die();      }      function createSmallerShrinkers() {           //add some code to create new Shrinkers      } } 

By doing this, we have tacked on Shrinker 's extra functionality to the beginning of the regular die function. When this method is called, it will be as if we had manually copied all the code from the Alien class. The benefit here, though, is that we don't have to maintain the code twice. Any changes made in Alien are reflected in Shrinker automatically.

To instantiate these subclasses, you go to the library in the .fla of the game and select the art for each of the alien types. You can then go to the Linkage window as before and type in the class names.

Multiple Inheritance

Caution  

Flash is a bit inconsistent about how it takes away the MovieClip class attributes. Although the movie doesn't have the default functions, the properties and event handlers remain functional.

You now know how to make a class, extend the class, and then choose what to inherit, overwrite, or modify from the superclass. This chain of inheritance can go deep. Just as all the types of aliens are inheriting from Alien , which inherits from MovieClip , you could continue extending the classes further as long as you have differentiations within the category.

As deep as inheritance can go, it has a few other limitations. Classes can only inherit directly from one class, which means that you cannot have a class extend two classes at once. An example of this that I briefly touched on was when we assigned a class directly to a symbol in the library. The symbol can't inherit from the MovieClip class and the Alien class unless you set up the hierarchical relationship of having Alien first inherit from MovieClip .

In the end, most classes that you would attach to a movie clip through the library would not also be a class that you would use in a non-movie clip setting. If that is the case, then setting up the inheritance to MovieClip is an easy workaround.

With the basics of how classes come together, let's go over some of the extra options you have when working with classes. Flash's ActionScript 2.0 gives us several tools to control data within classes.




Macromedia Flash MX 2004 Game Programming
Macromedia Flash MX 2004 Game Programming (Premier Press Game Development)
ISBN: 1592000363
EAN: 2147483647
Year: 2004
Pages: 161

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net