1. week 1
  2. week 2
  3. week 3
  4. week 4
  5. week 5
  6. week 6
  7. week 7
  8. week 8
  9. week 9
  10. week 10
  11. week 11
  12. week 12
  13. week 13

Saturday, October 16, 2010

Fall 2010 week 5:
—10/13: Wed 12:25pm - 3:25pm &
—10/15: Fri 6:00pm - 9:00pm

Hi Everyone,

GREAT class this week. I am very impressed with your determination. Some of you, however (and you know who you are) are not doing enough to pass the class, so you need to step it up and make a sincere effort to do the work. Many of you spent a lot of time trying to figure out how to do a drop-down menu. Although it may seem like wasted effort to some of you, trying to figure something out, even if you're not 100% successful, is very useful when working with code. It's hard work, but learning how to be more efficient, more logical, more rational is what writing code is all about. With that, most of you also need a lot of practice looking for your errors. You need to learn HOW to look for your mistakes. Most errors have to do with inconsistent naming practices. Be careful there.

This week for homework, you will begin working on the most essential thing you will get out of this class, classes. Learning about classes and how they operate is absolutely essential if you want to progress with ActionScript. If you want to learn more, and if you haven't done so already, please read the chapter(s) in your books that deal with classes.

Carter-



  1. WEEK 6
    1. Classwork
      • LINK    class files
    2. Homework
      • EXERCISE 1    please have the following ready for class next week:
        1. At least one COMPLETED Mockup in Illustrator or Photoshop;
        2. Your COMPLETED Bubble diagram;
        3. Your List of project;
        4. At least 2 OTHER SITES with aspects that you want to include in your own portfolio site;
    3. Midterm—this is due at the beginning of our next class:
      • Exercise 1:    Do ALL the steps below as your midterm project. Create a class with properties, functions and methods.

        1. We'll use our first project as an analogy: a music player.
        2. This is how you would create a music player class:
          public class MPlay {
          }
        3. While that may seem simple, it's really quite useless without properties or methods or actions; but there are one or two more things you need to do first if you want to be able to actually use a class such as this. The first of these is that a class must be a part of what is called a package. A package is really just a group of classes.
        4. Many packages are custom made, but there is a default package which we will use to start with.
          package {

             public class MPlay {
             }

          }
        5. The other, perhaps more important thing besides the fact that classes must come within packages, is that class definitions must be typed in separate ActionScript 3.0 documents; and that when you save them, the name of that ActionScript documents must have the same name as the classes. This means that the actions panel in a Flash .fla file will not suffice.
        6. Open up Flash if you haven't already, and instead of clicking on ActionScript 3.0, choose Actionscript File, and type the above little piece of script.
        7. Save that file as the same name of our class MPlay.as.
        8. Now, create a new Flash File (ActionScript 3.0), and before you do anything, save this file into the same folder as your .as file with the name of MPlayEx_01.fla.
        9. In this file, create an actions layer and in that layer type the following actions:
          var myMPlay:MPlay = new MPlay();
          trace(myMPlay);
        10. Save this file again, and test it (cmd-enter). Your output should be:
          [object MPlay]
        11. What this is telling you, as I was trying to get to in class on Wednesday when we were working with objects, is that you have just created an instance of the MPlay class. The next step is to get it to do something, and for that we will first need to give it properties and then endow it with some methods.
        12. As mentioned, we must first endow our new class with properties (characteristics or qualities in normal English). What we have in our .as file is what is known as a class definition because we are creating or actually defining our class. It stands to reason that when defining our class, that we mention some of its characteristics, or, in ActionScriptese, properties.
          package {

             public class MPlay {

               public var mVolume:int = 10;

             }

          }
        13. In this example, you will notice that property definitions are identical to defining variables. The reason for this is that properties are variables! It's just that they are variables that belong to a particular object rather than variables that are essentially free agents. We have defined both the property and the class as public so that both will be available to all parts of this ActionScript and the scripts in your .fla documents.
        14. Once you save that file, go back to the .fla file and see what you get when you try to get some output from the new property:
          var myMPlay:MPlay = new MPlay();
          trace(myMPlay.mVolume);
        15. Save this file, and test it again. This time, your output should be the volume level, 10. If necessary, you may also modify the property in the .fla file, once it has been set up by the class in your .as file. Just add a bit of code which will set the volume to a different number, making it louder. For example, set it at 15, and then trace the output again:
          var myMPlay:Mplay = new MPlay();
          trace(myMPlay.mVolume);
          myMPlay.mVolume = 15;
          trace(myMPlay.mVolume);


          Your output after this addition should now be 15.
        16. But that is only ONE property. Your objects may have as many properties as your programme requires, and of any kind. To your class in the .as file, add some new properties as follows:
          package {

             public class MPlay {

               public var mName:String = "";
               public var mVolume:int = 10;
               public var mTList:Array;
               public var mTCurrent:int = 0;
               public var mMix:Boolean = false;

             }

          }


          Above, I've added a name property so that the 'user' may give a name to the particular music player. There is an array, mTList, to hold the list of songs within the player; there is another integer, mTCurrent, to hold the current track number, the song that is currently being played by the player; and there is a property of type boolean, named mMix. This is for later use to mix up or shuffle the tracks so that they play in a random order.
        17. Now, your MPlay instance, which is your .fla file, can manage and maintain a number of pieces of data, or information. These are the properties that you set up in your class:

          var myMPlay:MPlay = new MPlay();
          myMPlay.mName = "Carter's Music Player";
          myMPlay.mVolume = 15;
          myMPlay.trace =
            ["The XX: Crystalized", "Fever Ray: If I Had a Heart",
               "Crystal Castles: Celestica", "Animal Collective: My Girls",
               "Bat for Lashes: Moon and Moon", "New Order: Crystal",
               "Cut Copy: Hearts on Fire", "Of Montreal: Gronlandic Edit",
               "Janelle Monae: Many Moons", "The Rapture: Get Myself Into It"];

          myMPlay.mMix = true;


          It should be obvious what I've added to the class instance in the .fla file: I have given it a name, and then I've populated it with some songs I'm listening to right now (try some of them out, I think they're pretty great, but don't laugh if you don't like them) within an array. This way of populating an array is known as literal notation. You will notice when/if you test your movie right now that there is no output (unless you have errors, and then you still don't have output but error notations). Now is the time, then for us to get this music player to do something. This is where methods come in. Methods are really actions. Methods are just like the play(); and stop(); actions, only they belong to an object.
        18. Adding method definitions is the same as adding property definitions: you place them within the class definition in your .as file. In essence, they are functions, but functions of an object. This means that you declare them by using the function keyword; however, like properties, you need to specify what's known as an access attribute, such as the default that we've been using, public:

          package {

             public class MPlay {

               public var mName:String = "";
               public var mVolume:int = 10;
               public var mTList:Array;
               public var mTCurrent:int = 0;
               public var mMix:Boolean = false;

               public function play():void {
                 trace("Playing: " + mTList[mTCurrent]);
               }


             }

          }


        19. Now, your instance of this player class in your .fla file (or any other instance you create) will have a play method available to it. Let's see how this works by modifying our code in our .fla file to call on this method:

          var myMPlay:MPlay = new MPlay();
          myMPlay.mName = "Carter's Music Player";
          myMPlay.mVolume = 15;
          myMPlay.mTList =
            ["The XX - Crystalized", "Fever Ray - If I Had a Heart",
               "Crystal Castles - Celestica", "Animal Collective - My Girls",
               "Bat for Lashes - Moon and Moon", "New Order - Crystal",
               "Cut Copy - Hearts on Fire", "Of Montreal - Gronlandic Edit",
               "Janelle Monae - Many Moons", "The Rapture - Get Myself Into It"];
          myMPlay.mMix = true;
          myMPlay.play();


          When testing your movie at this point, you should see (if you use the same tracks as I have), you should see Playing: The XX - Crystalized as your output.
        20. Great, now that we've got the first method complete, let's move on to the second method to make the player skip to the next track, whether your player is in shuffle mode or not.

          package {

             public class MPlay {

               public var mName:String = "";
               public var mVolume:int = 10;
               public var mTList:Array;
               public var mTCurrent:int = 0;
               public var mMix:Boolean = false;

               public function play():void {
                 trace("Playing: " + mTList[mTCurrent]);
               }

               public function next():void {
               }


             }

          }


        21. Let's recall that our MPlay class has a mMix property. Therefore, what we would like to do is to choose a random track, that is ONLY if this property is set to true, which at this point it has been. To do this, we must use the Math.random(); method. This method returns a random number between 0 and 1. That doesn't seem useful does it? Some strange number like .2, or .5, or .8? How can that help us when we have 10 tracks? Well, we can multiply that random number between 1 and 0 by our total number of tracks. That would mean .2 becomes 2, .5 becomes 5, and .8 becomes 8 (.2 * 10 = 2; .5 * 10 = 5, .8 * 10 = 8), and all those resulting numbers are between 0 and 10, our total number of tracks!!!. We must round the number to the nearest whole number (integer) also, however, because what if we get a random number like .35? This would result in 3.5 if we multiplied it by 10, and 3.5 is neither 3 nor 4, but somewhere right in the middle. As a result, we can only use numbers without decimals. To round numbers to the nearest whole, we need to use the Math.floor() method. Let's figure this out:

               public function next():void {
                 /*
                   below we place an if statement which contains
                   our mMix property;
                   recall that mMix contains a boolean value of
                   true/false;
                 */

                 if (mMix) {
                 }


          Whatever is placed into the parentheses following the if keyword will be evaluated on whether it is true or false. If it is true, then any statements between the { } brackets that follow will be run. If it evaluates to false, then it skips any statements between the { } brackets.

        22. Now, since our mMix property is set to true by default in our class definition, then the statement that we place between the { } brackets will be run. So, let's evaluate how that statement will function:

               public function next():void {
                 if (mMix) {
                 /*
                   Math.random() will find a number between 0 & 1,
                   and that number is multiplied by the number
                   of tracks in our Array (mTList.length).
                 */

                   mTCurrent = Math.random() * mTList.length;
                 }

               }

        23. But that does not solve our problem of the decimals as mentioned above. What we'll get if we use the equation as it is, is a number with a decimal in it. In order to eliminate the decimal (because we need whole numbers, integers), we must use that Math.floor(); method as mentioned:

               public function next():void {
                 if (mMix) {
                 /*
                   below Math.random(); is placed between the
                   parenthesis of the Math.floor() method;
                   Math.floor() will round whatever is between
                   its parentheses;
                 */

                   mTCurrent = Math.floor(Math.random() * mTList.length);
                 }

               }



        24. The above would only work in one condition, if the mMix property is set to true. That is, it will only work if we set the player so that it will shuffle our tracks around randomly; however, what if we do not want that? What about the condition in which the mMix is set to false. That is a 2nd condition, or the alternative. In ActionScript parlance, we call this the else portion of the if/else statement. In the else portion we would NOT want it to be a random selection, but for the selection to come in numerical order. In that case, we simply add one to the track number. To do that we simply use the increment operator (++). On the other hand, we must also have the option of returning to zero (0) if we have reached the last track, currently the tenth one.

               public function next():void {
                 if (mMix) {
                   mTCurrent = Math.floor(Math.random() * mTList.length);
                 } else {
                   if (mTCurrent == mTList.length - 1) {
                    mTCurrent = 0;
                   } else {


          In the else portion of the if/else statement, there are here again two possibilities that we have to consider: have we reached the end of the tracklist (i.e. the last track number), in which case we must start at the beginning again at zero (0) (above), or can we continue to just add one to the current track number by incrementing (++) it (below)?

                     mTCurrent++;
                   }
                 }
                 play();
               }



        25. Let's give this new method with the multiple if/else statements a go; but first, we have to create something to trigger it:
          1. In your .fla file, create a simple movieclip out of a rectangle or circle, or whatever you want by selecting it, choosing convert-to-symbol.
          2. Give it a name, select movieclip as type, and then click okay.
          3. Give this new movieclip the instance name of next_btn.
          4. Add the following code above the existing code:

          function onNextClick(evt:MouseEvent):void {
             myMPlay.next();
          }
          next_btn.addEventListener(MouseEvent.CLICK, onNextClick);


          Clicking on the button should result in the random change of tracks. This is because we have the mMix property set to true by default (recall, we set it this way in our class).

        26. Try using another instance of that movieclip that you just created and make it activate a back/previous method of your own creation that goes backward to the track before the current track (this is a rather difficult thing to figure out, especially if the mMix is set to true, which means the list of songs is going to be all mixed up, so all I really want to see is a good try — don't get stuck here: move on so you can finish up the rest and come back when you have time).

        27. When creating a custom class, as we have done, it simply means that you are creating a completely original class, one that does not already exist as part of the ActionScript library of classes written into the language and Flash application.

          When creating an instance of one of your custom classes, you will usually initialize it to make even your instance unique from others. Taking our current example of a music player, you may want to initialize it by giving it its own name, by giving it a beginning track, or by setting it to shuffle or not.

          Any actions such as these that are to be taken care of at the start, at the moment when an instance of an object is created, need to be handled by what's known as the class's constructor. A constructor is a special method (function of your class) that is performed on each new instance of your class at the moment that it is created. It has the same name as the class of which it is a part, and the parameters (its properties & methods) indicate which information needs to be provided when creating a new instance of that class.

          Sometimes you will not want to have to provide information for ALL the properties simply to initialize an instance; but, rather, only on a selection of those properties. One of the problems that we currently have in our class is that when we create a new instance in an .fla file, we have to initialize ALL the of the properties indicated in the .as file's class definition. Wouldn't it be much more efficient and convenient if only a certain select few properties had to be defined in the instance, such as it's name and the level of the volume?

          Behind this is the notion that you will be able to initialize the new instance of the class object with those few properties (instead of all of them, which can be dozens and dozens depending on the class), so that it's ready to start working. Below, you will see that I've created a basic constructor for our music player. Try to keep in mind that the constructor has the same name as the class. You should type what you see below in a new folder. When you save it, make sure it has the same name as the class, just like for the first one you did above.


          package {

             public class MPlay {



          Notice that below, I do not provide any values when creating the properties of the class.

               public var mName:String;
               public var mVolume:int;
               public var mTCurrent:int;
               public var mMix:Boolean;
               public var mTList:Array;


          Below here is where the constructor method begins. The properties within the parentheses are the only three that will have to be defined when the instance is created in the .fla file. The others (the ones between the curly brackets) will be given a default value only:

               public function MPlay(
                   mName:String="",
                   mVolume:int=10,
                   mMix:Boolean=false


          Next, the parentheses close, and the curly brackets open. As mentioned, only the items within the parentheses will have to be defined when the instance in the .fla file is created. Below, between the curly brackets you will see the first three items repeated from above. Here, the this keyword refers to the current class, and we are indicating in those lines that the properties of the constructor are the same as the properties of the class.

                   ) {
                 this.mName = mName;
                 this.mVolume = mVolume;
                 this.mMix = mMix;


          Those below between the curly brackets, that are NOT indicated between the parentheses, will only have their default values. These will not have to be defined when you create your instance in your .fla file as they are already defined here.

                 mTCurrent = 0;
                 mTList = new Array();
               }


               public function play():void {
                 trace("Playing: " + mTList[mTCurrent]);
               }

               public function next():void {
                 if (mMix) {
                   mTCurrent = Math.floor(Math.random() * mTList.length);
                 } else {
                   if (mTCurrent == mTList.length - 1) {
                    mTCurrent = 0;
                   } else {
                     mTCurrent++;
                   }
                 }
                 play();
               }

             }

          }



        28. Now, we're going to create a new instance of this class; so, open up a new .fla file and name it MPlayEx_02.fla. In your actions, type the following code (when saving, make sure you save it into the new folder with the new class you've just typed):

          var myMPlay:MPlay = new MPlay("Alex's Music Player", 12);

          Notice above that we're actually typing the properties' values in between the parentheses. Those are values for two of the three properties that we put in between the parentheses in the constructor method.

          trace(myMPlay.mName);
          trace(myMPlay.mVolume);
          trace(myMPlay.mMix);


          You'll notice that when I initialized the instance in the first line, that I only indicated two parameters, the name of the player (Alex's Music Player), and the volume level (12). The third parameter that I put in my constructor method in the class definition in the .as file was for the mMix property, which determines whether the songs are played randomly or in order; but it's not here. I didn't put anything here for it. That's perfectly okay. What it means is simply that it will get it's default value (recall that we gave it the default value of false in the class definition). I could have specified it here, but if I don't, then it falls back on the default value.

        29. Within our class we have a variety of properties and methods, but currently they are all publicly accessible, meaning that they can be read and modified from any other part of the code. In many scripts, this may not always be a good thing for all items. For example, many pieces of software and hardware have passwords or serial numbers that identify the particular item or user. Things such as these uniquely identify those particular items or persons. They could also be kept in properties with names such as mSerial or mPW; however, serial numbers of a piece of software or hardware cannot be changed. This means we require some manner of obscuring or hiding things such as the serial number from normal viewing. This is where what's known as access attributes, such as public which we've already seen, come in. Another possibility made available by ActionScript and Flash is private. Contrary to public access, which provides access to all parts of the code both in the class definition in the .as file, and also by instances of that class in the particular .fla files, private access provides access only to the methods within the class itself (in the .as file).

          package {

             public class MPlay {

               public var mName:String;
               public var mVolume:int;
               public var mTCurrent:int;
               public var mMix:Boolean;
               public var mTList:Array;

               private var _mSerial:String;

               public function MPlay(
                                     mSerial:String,
                                     mName:String="",
                                     mVolume:int=10,
                                     mMix:Boolean=false
                                   ) {
                 _mSerial = mSerial;
                 this.mName = mName;
                 this.mVolume = mVolume;
                 this.mMix = mMix;
                 mTCurrent = 0;
                 mTList = new Array();
               }

               public function play():void {
                 trace("Playing: " + mTList[mTCurrent]);
               }

               public function next():void {
                 if (mMix) {
                   mTCurrent = Math.floor(Math.random() * mTList.length);
                 } else {
                   if (mTCurrent == mTList.length - 1) {
                    mTCurrent = 0;
                   } else {
                     mTCurrent++;
                   }
                 }
                 play();
               }

             }

          }


          Coders of ActionScript commonly mark private properties with an underscore character (_), and so I have done so here as well. This way it is much easier to see, to have a strong visual marker within our code telling us which of our properties are private and which are public (those that do NOT contain an underscore as the first character of the name). You might also notice that I did NOT use the underscore within the constructor for the equivalent parameter there.

        30. Now, you'll have to change the code in the .fla file to pass the extra parameter to the constructor method when creating an instance of the MPlay class.
          var myMPlay:MPlay = new MPlay("B031167", "Alex's Music Player", 15);
          trace(myMPlay.mName);
          trace(myMPlay.mVolume);
          trace(myMPlay._mSerial)
          <-- You'll get an error for this line of code.

        31. Next thing we need to add are what's known as get/set methods. These allow you to create properties that act similarly to functions. They are a pair of methods with the same name. The get function is called whenever you need to read or see the property of the same name; and the set function is called when a value needs to be assigned to that property.

          A get method looks like any other method of the class you've created, except that it also contains the get keyword between the function keyword and the function name. This method returns a value.


          public function get SomePropertyName():someDataType {
             // it needs to return a value of the correct type
          }


          A set method is similar but uses the set attribute in place of the get attribute, and it's given the new value so as to pass it onto the property of the same name. The return type of the set method is always void.


          public function set SomePropertyName(value:someDataType):void {
             // the new value for the property will be
             // in the new variable above that we named value.

          }


        32. We're going to change the mTCurrent property from public to private which means we'll also be adding the underscore (_) to the beginning of the name. This takes care of another problem we would've been faced with in a moment, and that is the fact that we cannot have properties methods with the same name.


          package {

             public class MPlay {

               public var mName:String;
               public var mVolume:int;
               public var mTCurrent:int;
               public var mMix:Boolean;
               public var mTList:Array;

               private var _mSerial:String;
               private var _mTCurrent:int;

               public function MPlay(
                                     mSerial:String,
                                     mName:String="",
                                     mVolume:int=10,
                                     mMix:Boolean=false
                                   ) {
                 _mSerial = mSerial;
                 this.mName = mName;
                 this.mVolume = mVolume;
                 this.mMix = mMix;
                 _mTCurrent = 0;


          Next, we create the get/set methods. The get just needs to return the value held within the _mTCurrent property.


                 mTList = new Array();
               }

               public function play():void {
                 trace("Playing: " + mTList[mTCurrent]);
               }

               public function next():void {
                 if (mMix) {
                   mTCurrent = Math.floor(Math.random() * mTList.length);
                 } else {
                   if (mTCurrent == mTList.length - 1) {
                    mTCurrent = 0;
                   } else {
                     mTCurrent++;
                   }
                 }
                 play();
               }

               public function get mTCurrent():int {
                 return _mTCurrent;
               }


          We require something a bit more involved with the set method. From the beginning of this part of the exercise, our eventual aim was to prevent the mTCurrent property from being greater than the actual number of tracks in our list of tracks in the mTList array. Otherwise, if we called on track 12 when we only have 10 tracks, then what would happen?

          First, we need to make sure that the current track is not set to be less than 0. The Math.max() method takes care of that for us. This method looks at the two values between the parentheses and determines which is larger of the two and returns that value. Given this: Math.max(5, 25), the value returned would be 25.

          Second, we also need to make certain that the current track is not set above the actual number of tracks that exist in the track list. The Math.min() method does this. It checks the two values between the parentheses and determines which is the lesser value. For example: Math.min(5, 25), the value returned would this time be 5.

          Now, let's say we have a track list that has 5 songs in it, but that we for whatever reason choose track 8. That number is beyond how many tracks we have, so what we want the script to do is set the actual number to the last track we have. Therefore, we need the script to actually choose track 5 instead of track 8, which doesn't exist anyway.

          For a tracklist that has 5 songs, the index number of the last song is in reality 4, and that's because arrays start counting at the number 0. If we were to translate this to ActionScript, we'd write it as the length of the array minus 1. Whenever we want the last index of an array, it's always going to be one less than the length, which means we'd type it like this: tracks.length - 1. So our line of code would look something like this: Math.min(8, tracks.length - 1).

          Since the length of the array is 5, then 5 - 1 = 4. The Math.min function then chooses the lower number, 8 or 4. Obviously, it will choose 4 and return that value. That means that if we choose track 8, the music player will actually select our last track which is our 5th song, or track[4].

          That takes care of the upper limit, keeping the selection from going above however many tracks are in our list. Now, how about the lower limit? Okay, so let's pretend we're stupid and select track -32 to play. Obviously, there are no negatively numbered tracks, so what we'd really want is for our player to choose the lowest track number in the list, which would always be 0 (recall that the lowest index number in an array starts counting at 0). By using the Math.max() method we can determine our lower limit: Math.max(0, -32) Clearly, the value that will be returned is always going to be 0 if the other number is a negative number. So, if we choose track -32, what our script will choose for us actually the first track we have, or track[0].


               public function set mTCurrent(value:int):void {
                 value = Math.max(0, value);
                 value = Math.min(value, mTList.length - 1);
                 _mTCurrent = value;
               }
             }

          }


        33. And finally, let's modify the actions in the .fla file to be the following:

          var myMPlay:MPlay = new MPlay("B031167", "Alex's Music Player", 15);
          // the push() method adds elements to an array, and
          // since our array at this point has no items,
          // these are going to be our 1st, 2nd, & 3rd items.

          myMPlay.mTList.push("Sufjan Stevens - John Wayne Gacey, Jr."); myMPlay.mTList.push("Azure Ray - No Signs of Pain"); myMPlay.mTList.push("St. Vincent - The Strangers"); trace(myMPlay.mTCurrent);// traces 0
          myMPlay.mTCurrent = 55;
          trace(myMPlay.mTCurrent);
          // now traces 2 which is
          // the last index number for the mTList array
          // since there are only 3 tracks in the list.




        34. The very last thing that you should do for our next class is try to understand what you have done here. There are many new things introduced here in this blog this week. If you have any difficulties with the new concepts, it is up to you to come to class with questions for me. If you do not, then I will assume that you understand it all and are prepared to move on. All that being said, I want you to come to class with 5 things you have learned here in this blog this week, and explanations for what they are. Try to be as clear and as precise as possible, but your explanations MUST be in your own words.





No comments:

Post a Comment