Your Script Style

[ LiB ]  

Your scripting style should continue to improve forever. That is, you never know it all and you're never too old to learn more. Before you start archiving the greatest scripts of all time, however, you just want to improve your style. That is, you can start by improving a single script in part of your movie, then move on to improving the whole movie...and then maybe improve an entire project and so on. Start with the details. This section examines ways to improve the way you write scripts.

It would be great if I had a set of absolute rules to follow, but it's more ambiguous than that. Even when there are accepted "best practices" defined, you may not be ready to fully use them. Regardless of your experience level, it makes sense to always look for ways to improve, even if that means being self-critical of the way you've solved a problem.

Think Modularly

A few general approaches, when taken, should alert you that a better way exists. If you ever copy and paste the same block of code, for example, you know something is wrong with your approach. You should instead take that code and put it inside a function. Then in the two places you were going to paste it, trigger the function. Not only does this mean you can modify the code in one central place, it also means that if later you need to trigger the same code, you can do so by invoking the function (instead of copying and pasting again).

Often you may be copying and pasting when you intend to make minor changes to the copy. That is, you're not really duplicating the code exactly, but with minor adjustments. For example:


 button1_btn.enabled=false; button2_btn.enabled=false; button3_btn.enabled=false; 


In this case, you can't just trigger the same function three times because you're doing three different things. But you can generalize the code. Instead of thinking, "I've got to disable button1, button2, and button3," think, "I've got to disable buttons 1 through 3." Pretty much the same thing, but by thinking in these terms the adjusted code is easier to derive:


 owner=this; for(var i=1;i<4;i++){ owner["button"+i+"_btn"].enabled=false; } 


Although this is more code, you'll see the benefits when you have, say, 100 buttons to disable. Actually, if you think even more generally , it might make sense to put this inside a function that you can use to both enable or disable all the buttons:


 owner=this; function changeButtons(active){ var total=3; for(var i=0;i<total;i++){ owner["button"+Number(i+1)+"_btn"].enabled=active; } } 


Now you can just say changeButtons(true) or changeButtons(false) . Notice another enhancement I made: I'm using a variable total that's more exposed because, frankly, it's the only hard-wired part of this script. Notice, too, that because I'm using a more popular technique of starting with in the for loop, I need to add 1 when building the button's instance name .

This example isn't supposed to be revolutionary, but rather descriptive of the process where you continually improve the scripts you have. Way before code is worthy of recycling, it has to be as generic as possible. Although it is sometimes more complex, the best code is very specific in its purpose and very general in its application. For example, one function may be in charge of disabling buttons (that's a specific goal), but you should write the function so that it can disable as many or few buttons as needed (that is, you can apply it generally). I can assure you that many scripts in this book are not ideal. Although they should all work, most of the time I was just trying to show a particular subject. In many cases I opted for clearer code rather than optimized, elegant code. When you try improving your scripts (for possible use in your code library, for example), it makes sense to capitalize on making it as generic as possible.

Advanced Techniques

The good news about ActionScript is that because there's so much you can learn, you'll never feel like you know it all and become bored (at least I'm nowhere near that point). Here are some pointers for the direction you might take to enhance your scripting ability as well as develop more useful code snippets.

Functions as Constructors

Most functions behave like subroutines where you can trigger the contained code by using the form functionName() . By just changing the way you design and implement the function, however, it can serve to produce custom object instances while the movie plays. This enables your code to adapt by spawning many instances of the same code template. For example, you could give your users the ability to add entries into an address book where each entry was based on the same object that contained a standard set of properties and methods . The funkiest thing when learning to use constructor functions is that you're just making variables containing codeit's not like you necessarily "see" anything onstage. (Obviously, if you tie it to attachMovie where you're creating clips on-the-fly , you'll see something; however, that's not a requirement by any means.) Here's a before-and-after example where constructor functions were used. The example requires the following components : a Button ( add_btn ), a List ( all_lb ), and a ComboBox ( option_cb ) populated with some labels. Plus, an input text field ( name_txt ) and a multiline dynamic text field ( results_txt ). See Figure 13.5.

Figure 13.5. The following code sample uses the components shown.

graphics/13fig05.jpg



 allEntries=[]; function addEntry(){ var thisObj=new Object(); thisObj.name=name_txt.text; thisObj.option=option_cb.selectedItem.label; thisObj.creationDate=new Date(); all_lb.addItem(thisObj.name+" : "+thisObj.option, allEntries.length); allEntries.push(thisObj); } add_btn.onPress=function(){ addEntry(); } all_lb.addEventListener("change",doClickList); function doClickList() { var thisObj=allEntries[all_lb.selectedItem.data]; results_txt.text=thisObj.creationDate+newline; results_txt.text+="name: " + thisObj.name+newline; results_txt.text+="option: " + thisObj.option; } 


Although there's nothing wrong with this codeit works after allthings are spread out. I'm using an array ( allEntries ) to store all the saved data, and the List's data array (the second parameter) contains the entry's index in the array. Also, the doClickList() function needs to directly grab properties of the appropriate object from within the allEntries array.

The following alternative uses a constructor function to create objects that contain homemade methods to give outside functions indirect access to their contained properties:


 function Entry(name, option){ this.name=name; this.option=option; this.creationDate=new Date(); this.getName=function(){ return this.name; } this.getOption=function(){ return this.option; } this.getAll=function(){ var retString=""; retString+=this.creationDate+newline; retString+="name: " + this.name+newline; retString+="option: " + this.option; return retString; } } function addEntry(){ thisOne=new Entry(name_txt.text,option_cb.selectedItem.label); all_lb.addItem(thisOne.getName()+" : "+thisOne.getOption(),thisOne); } add_btn.onPress=function(){ addEntry(); } all_lb.addEventListener("change",doClickList); function doClickList() { results_txt.text=all_lb.selectedItem.data.getAll(); } 


This accomplishes the same thing as the first solution. However, this example centralizes all the data handling in one place: the Entry() constructor function. That is, when a new entry is needed, the Entry() function is invoked with the keyword new . This returns an object fashioned however Entry is definedin this case, including methods to get the name, get the option, or get a formatted string with all properties. Having all this data handling in one place means that outside scripts never directly touch an object's propertiesthey always go through the methods. This way, if you change the name or behavior of any property, you don't have to go searching all the places that may be accessing the old properties. Everything is in one place.

There are a couple other approaches in this example, but to learn more I highly recommend a book called Object-Oriented Programming in Flash , by Brandon Hall et al.ndex>

Extending the Prototype

The concept of extending the prototype is covered in much more detail other places. However, I think it's worth showing you a technique that's really practical even if it doesn't fully explain the subject. Real quick: Every object type has a prototype property where all of its methods are stored. If you add more methods to an object's prototype , you'll be adding to all instances of that object type in your movie. The following example adds to the prototype of the MovieClip by defining a method that will adjust any clip's scale:


 MovieClip.prototype.setScale=function(toWhat){ this._xscale=toWhat; this._yscale=toWhat; }; 


The setScale() function is now automatically embedded in every MovieClip instance in our movie. Because the two lines inside the function affect this , we can use setScale() to affect any clip. For example, myClip.setScale(50); will scale the instance named myClip to 50 percent (both _xscale and _yscale ).

This is really powerful, but you don't want to override built-in methods. For example, you don't want to replace setScale (above) with play or something built-in. Here are just a couple more examples to give you an idea how useful it is.

Here is a method that makes it possible to set a clip's right-side location directly:


 MovieClip.prototype.setRight=function(toWhat){ // assuming top left registration this._x=toWhat-this._width }; //e.g. myClip.setRight(400); 


This method enables you to build a functional time string based on a sound that's playing:


 Sound.prototype.getTimeString=function(){ var p=this.position; var m=Math.floor(p/60000); var s=Math.floor((p-m*60000)/1000); var d=Math.floor((p-m*60000-s*1000)/100) if(m<10){m="0"+m;} if(s<10){s="0"+s;} return m+":"+s+"."+d; } //e.g. myField_txt.text= s.getTimeSring(); 


It turns out that Flash MX 2004's support for ActionScript 2.0 gives you a more elegant way to extend objects. It's actually called "extends." The equivalent to MovieClip.prototype is class myClass extends MovieClip{} . You'll learn the basics of AS2 later in this chapter.

After you get the hang of it, extending the prototype is very, very convenient . My only recommendation is to always start with a clear objective instead of extending the prototype just for the sake of doing it.

It's important to remain practical. If using constructor functions or the prototype concepts are confusing, for instance, there's no point in using them immediately. It makes sense to attempt to apply themperhaps just not in the heat of a project. Ultimately, this way you'll recognize what code to save by recognizing what's familiar. After a few projects (or revisions of the same project), try to identify patterns in your approach. Not only will this help you see places for improvement, it will also enable you to identify the sorts of code worthy of archiving. Now it's time for you to explore different ways to store your favorite scripts.

[ LiB ]  


Macromedia Flash MX 2004 for Rich Internet Applications
Macromedia Flash MX 2004 for Rich Internet Applications
ISBN: 0735713669
EAN: 2147483647
Year: 2002
Pages: 120

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