Freelancer behind 5 1/2 math and physics enthusiast Patrick has a knack for making seemingly simple things overly complicated. Perfect for a tutorial writer. When you become an accomplished programmer, you actually get worried when your code works for the first time; surely this is wrong, it works! Yes, such is the tragedy of computer work; it never quite works as intended. Actionscript is no different. Sooner or later you will stumble into a bug that will seem impossible to iron out.
Looking at the boards and at feedback from previous tutorials, I've spotted what I believe to be the most common Actionscript errors. These vary from basic to advanced; even expert coders may learn a thing or two. Before looking at these errors, I present a brief review of Flash's debugging tools.
The most primitive of the Flash debugging tools, it's been around since Flash 4. It will send a string to the output window when you test your movie inside the Flash IDE. It can be used to see if a function is called, if a movieclip is correctly targeted, if a variable has the right value and so forth. Even though it is primitive, I still use it all the time, and you should too. Use like this:
[as]trace("I'm a trace action!");[/as]Or with a variable:
[as]myTrace = "I'm the content of a variable";When testing your movie inside the Flash IDE, you will find two items under the Debug menu. List Objects will list levels, frames, buttons, movieclips, text, shapes and such, along with their instance name. List Variables will list all of the persistent variables, as well as their scope, type and value.
List Objects is particularly useful for debugging duplicatemovieclip and attachmovie, as you can see if the movieclips are being created. List Variables is great as well, although you will find it hard to spot your variables if you use components, as they use a ton of variables themselves.
If you need to watch continuously for a value, you may place a textfield (dynamic text) on stage and set its text property to show debugging text. With the Object.watch function, this can be automated relatively easily. For example, if you have a textfield named debug on stage, you can try this:
[as]//Debugging codeIn this case we are trying to debug a millisecond counting function. It uses the msecs variable; we set _root to watch this variable and call watchMsecs every time it is changed. A string is created which compares our value to the the time elapsed as measured by getTimer; the debug textfield is used to display the result. Upon testing the movie, you can see that there is a difference between getTimer and the interval timer. The great thing about this method is that you can test it in a browser to see if the difference is the same in the IDE or in browser, while the trace approach works only in the IDE.
Flash has an integrated debugger that is very powerful. To activate the debugger, you need to go into Control > Debug Movie. You will see the usual Test Movie setup but with an additional window aptly titled 'Debugger'. It should look like this:

As indicated, when you first debug your movie, the Flash player is paused. You can select your movie's scripts by using the combo box on the right. By clicking on the left margin of a line of code, you will set a breakpoint, indicated by a red octagon. When you press play, the flash player will pause every time it encounters a breakpoint; this allows you to examine the value of a variable or the position of the playhead before an action is executed. By right clicking a property or variable in the Name : Value grid you may add it to the watch stack. The debugger also offers advanced features such as remote debugging.
The debugger is a very handy tool for large projects. However, for quick and dirty coding, you may find the previous methods to be more appropriate.
Yes, the Flash instruction manual IS a debugging tool. I ALWAYS keep the Actionscript dictionary open when I code, and you should too. Personally, I don't like the new integrated help system (in MX 2004), as I find there's already more than often of these palettes and I have limited screen space. Luckily, Solomon Wong of Flash Skynet has kindly created a Flash extension which provides an external HTML help system; you can download it on Macromedia Exchange. Make sure you look at the examples Macromedia has provided, they can serve as a great guideline when using a function for the first time.
Targeting errors are extremely frequent among beginners and experts alike. These errors can be very hard to spot. A common issue for beginners is the distinction between library name, export identifier and instance name; this leads to confusion and often errors. When you create a symbol, you give it a library name:

You will then see this name in the library. This name is NOT exported in the swf. You will never refer to this name in scripting; it is therefore completely arbitrary.
If you drag an instance of this clip onto the stage, and select it, you will have access to the instance name. You will enter it in the properties panel:

You will refer to the movieclip by its instance name in scripting. It is therefore very important that it consistent with your scripting. Textfields and buttons have instance names as well, and they are just as important.
By right-clicking on a movieclip in the library and selecting Linkage, you will access the clip's linkage properties. By checking "export for Actionscript", you will notice yet another name input, the identifier. You will only use the identifier with attachmovie. Sounds can also use identifiers, and they work in much the same way: they are only used in with the Sound.attachSound and Sound.stop functions.
When a script involving movieclips does not work correctly, a first step is to check that the instance name and the name in the script are one and the same. This brings me to my next important point: Flash MX 2004 is case-sensitive. This means it makes a difference if you use capitals letters or not. So calling gotoAndStop and gotoandstop will NOT give the same result: only the first will work. This is true of built-in functions and of user-created objects.
Flash has a rich but complex hierarchical structure; this means objects (including movieclips) can be nested. This is a great feature of Flash but it can cause headaches: make sure you correctly refer to the path of the objects you are manipulating. If you are not familiar with proper movieclip and object referencing, please refer to Jesse Stratford's Paths to Objects and Variables tutorial.
Name clashing is a special, virulent case of targeting error. It happens when two objects are of the same name in a given path. You may have noticed that I sometimes speak interchangeably of movieclips and objects. That's because movieclips ARE Objects. They behave in a peculiar way, yes, in that by modifying their properties their appearance on stage changes, but they are objects.
If you give a movieclip an instance name, and then create variable or object of any type of the same name in the same path, you will 'overwrite' the reference to the movieclip and lose access to it. If you're getting cryptic errors such as a movieclip's _x property being undefined, this may well be the cause.
This applies to not only movieclips but to all actionscript objects. Here's an example of what NOT to do:
[as]function test()If Actionscript 2 exporting is selected, the script simply doesn't compile, as Flash is smart enough to spot the error; in AS1 mode it shows the following output:
[code]Here's a testThe reason is that inside the test function the function itself is overwritten. Therefore on the second call, Flash can't resolve the function and returns and undefined value.
Another common form of name clashing is having two movieclips by the same name. For example, you place a radio button component on stage and give it an instance name of 'radioBtn'. Then you copy and paste it several times on the stage. When you test your movie, your radio buttons behave erratically: when you roll out of a radio button it disappears, or it doesn't work at all. This is because Flash can't refer to the movieclips correctly because they have the same names.
When creating complex movies, you will have several functions that act as event handlers for various objects, as well as generic user-defined functions. Some functionality may not work at all when you test your movie. Before checking for any other error, please, check if the relevant function is actually called. Just place a trace('in'); action at the beginning of the function to see if it is called. If you don't see 'in' in the output panel when you test your movie the function is never called. Most likely this is simply a targeting error; double-check your object and function names to see if they are coherent.
If after checking your function names, everything looks all right but your movie still does not work, it could be because you are using a function string where a function reference is required, or vice versa. For example:
[as]function showTimer()This looks like it should work, but it does nothing. This is because onX handlers expect function references, not function strings. If you remove the quotes on the last line, the movie will work properly. Most of the time, Flash will want a function reference. There are some notable exceptions, however; for example when using setinterval with an object as the first parameter, the callback parameter is a function string.
This type of imbroglio also happens, though less often, with variables. For example, Object.watch requires a variable string as the first argument and a function reference as the second. Very confusing indeed. Look at the examples in the Actionscript Dictionary for specifics.
Naively using Movieclip.onKeyUp and Movieclip.onKeyDown will not work. This is because by default movieclips are not listeners of Key events. For example:
[as]function showTimer()You can test your movie and press all the keys you want, you will never get the timer in the output window. Isn't Movieclip.onKeyDown exactly the same as onClipEvent(keyDown) ? Nope. To get the same functionality as with onClipEvent, you will need to add a listener, such as this:
[as]function showTimer()I believe this has to do with focus handling in components. See this article by Guy Watson of Flashguru fame for more info on listeners.
In the same vein as the previous error, Movieclip.onLoad and onClipEvent(load) are NOT the same. The documentation tells all:
"This handler [Movieclip.onLoad] can be used only with movie clips for which you have a symbol in the library that is associated with a class."
So Movieclip.onLoad is nothing like onClipEvent(load). Unless you know what you're doing, don't use it. Look at the the MovieClipLoader class for an onLoad handler that actually works, or check out the Loader component.
I've had terrible difficulty with this when learning Actionscript way back when Flash 4 was the thing. LoadMovieNum loads movies into what is called a level. In each level there are depths. Levels have precedence over depths, that is, any depth in level 1 is higher than any other depth in layer 1. Levels can be accessed cross-movie using _level0 or _level1, for example. Each level has its own _root. A level is not like a movie clip; you can't for example write _level1._visible = false and expect your movie to disappear.
MovieClip.LoadMovie loads a movie into a movieclip. The loaded movie then 'becomes' a movieclip in its own right. You may for example use:
[as]_root.createEmptyMovieClip('empty', 0);The contents of example.swf will be placed in the empty movieclip. When it appears, it will be placed on (100, 200). As the loaded movie 'becomes' the movieclip, it does not have its own _root.
Generally speaking, I suggest that you do NOT use loadMovieNum unless you have a very specific reason to do so. Mainly, the only (valid) reason I find is that you need to load in a movie that is designed to be used alone (needs its own _root) which you do not have the source for. LoadMovieNum is just not flexible. Your movie will be at (0,0) sitting there and that's it. Now this admittedly radical opinion will displease some; you are free not to follow my advice on this.
In any event if you are to load a movie (especially someone else's) into a movieclip it probably won't work immediately. The reason is that the loaded movie refers to _root, which is not the same when the movie is played alone or loaded in a movieclip. This is where most beginners abandon. You shouldn't.
You need to convert absolute references to relative references in which _root does not appear. So all of these _root's will be replaced with _parent and this. Not a simple matter in most cases, but you will learn a great deal. First load the source into Flash and make it work alone without all of the _root's. Then try it again as a loaded movie clip and it should work fine.
Please, before anything else, when files don't work online, first check if all the support files are correctly uploaded. I once had a problem on a test server where all of the XML files became empty once on the server; probably some filter on the server.
Place your HTML file and your SWF in the SAME folder, OR use absolute URLS. Of course, update the HTML file to match the situation. When Flash encounters a load command that uses a relative URL it passes it along to the browser. The browser must decide whether that URL is relative to the Flash file or to the HTML file. If they are in the same folder, there is no ambiguity. However, if that is not the case, do you know what it will choose? I don't either! Save yourself the trouble, keep the main swf in the same folder as the HTML.When files are loaded through one of Flash's numerous load functions (loadMovie, MovieClipLoader.loadClip, XML.load, Sound.loadSound, etc.), there is always a lag between the load call and the data being received. You must take that into account. Never play with a movie you're not 100% sure is loaded. Using MovieClipLoader and LoadVars is safer than loadMovie and loadVariables because of all the neat loading events they fire.
Double-check if your preloaders are working. If you don't have them, use them! Check out the progress bar component, it can hook to most loading functions and objects, so you'll have visual feedback.
This goes with the previous error, but I've seen this so often it deserves its own point. You create a preloader of some kind and it takes a good deal of time to show up, even though it's on the first frame and only a few kbs. What's going on?
The reason is that Flash may place objects before the first frame. Your preloader will only be shown once these are loaded. The three usual suspects are: movieclips, components and sounds. When you check Export for Actionscript in the Linkage properties of a movieclip, by default the "Export in first frame" option is selected. Uncheck it and see if your preloader does the same thing. You needn't put your file online to see if it works; simply press Ctrl+Enter twice to do a streaming simulation.

After taking the time to uncheck the 'Export in First Frame' option in the movieclip that was causing the problem, you may find your attachmovie calls cease to function properly. This is because the clip is not exported in the swf anymore. Place an instance of the movieclip on frame 2 of your movie off of the stage. It need only to be shown on a single frame, so you can put a blank keyframe on the movieclip's layer in frame 3.
The second culprit: components. Like movieclips, components have linkage properties. If you uncheck export in first frame on a standard v2 component, you'll notice you will still have the same loading issues. That's because the component's class is still loaded before the first frame. What you have to do is go into File > Publish settings; in the Flash tab, click the Settings button to the right of the "Actionscript Version" option; in "Export frame for classes", write 2instead of 1. That should do the trick.
The third element that will cause preloading issues is sounds. Sounds that are exported for actionscript, like movieclips and components, are exported by default before anything on the first frame. As usual, uncheck "Export in first frame" in the Linkage properties dialog. You must include the sound somewhere in your movie or it won't be exported. If you place it naively on the second frame, the sound will play: this is bad. What I suggest rather is this procedure: create an empty movie clip. In the first frame, place a stop() action. In the second frame, create an empty keyframe. In the properties panel, select the sound you need to preload from the Sound combo box. Place an instance of this movieclip in the the second frame of your movie. This way, Flash sees an instance of the sound, so it will preload it in the second frame, but the movieclip will never reach the sound, thanks to the stop action in the first frame.
This is straight from the documentation:
gotoAndPlay()
usage: gotoAndPlay([scene,] frame)MovieClip.gotoAndPlay()
usage: my_mc.gotoAndPlay(frame)
So you see, Movieclip.gotoAndPlay does NOT have a scene parameter. Hence, if you are inside a movieclip and trying to reach the first frame in Scene 1, using _root.gotoAndPlay("Scene 1", 1) just won't work. It's essential to understand that scenes are not exported in the swf. All scenes are put one after the other to create a single scene when publishing to swf, much like layers. If you use gotoAndPlay with the scene parameter, when you publish your file, the IDE compiler will catch these calls and converts them to standard gotoAndPlay calls without the scene parameter.
For example, if you have two scenes called Scene 1 and 2, both having 10 frames, and you use gotoAndPlay("Scene 2", 5), the compiler simply translates it to gotoAndPlay(15). If you want to use that call inside of a movieclip, simply use _root.gotoAndPlay(15). This goes for gotoAndStop as well. You may also use frame labels, as they also work well.
When a textfield is created in the IDE or using actionScript, by default it uses device fonts. Using device fonts, you may suffer any of the following problems:
The reason is that when device fonts are used the operating system is in charge of text rendering, so it's not nearly as reliable as Flash's internal rendering. The classic reason for using device fonts is because text is crisp and readable at small sizes. Flash MX 2004 now offering aliased text, this is no longer an issue.
The solution to these problems is font embedding. When a textfield is used with an embedded font, it behaves nicely, just like regular static text. To turn on font embedding, create a textfield on stage in dynamic or input text mode. Select it and press the "Character..." button. Select "Specify ranges" and choose which outlines you need to embed. Usually Basic Latin will do, although you will have to include accented characters if you are using a non-English language.
In actionscript, you can set the Textfield.embedFonts property to true for a specific textfield. This will only work if the font is already embedded somewhere else in the movie, so may need to create a dummy textfield with the character embedding options set in order for this to work properly. Note that bold and italic count as separate fonts, so you may need to create several of these dummy textfields, one for each variant of a font.
There is another way to embed the fonts for actionscript use, and this is the font symbol method. The documentation is very vague on this, so here goes. You can include a font as a library item, called a font symbol. Go into the Library and click the Options button in the top right of the panel. You should see a "New Font..." item. Select it; this dialog should pop up:

This allows you to embed a specific font. Once you have your font symbol created, right-click it to access its Linkage properties. Select Export for Actionscript and give it an identifier. This identifier serves as a font name just like any other in Actionscript. Take this for example:
[as]_root.createTextField('txt',0, 100,100,200,200);This creates a new textfield on stage with "Hello world!" as the text. Here I created a new font symbol with an aliased Arial 11. Having given it the linkage identifier 'fntArial', I can use it in the textfield.
If you use non-English latin characters (accented characters like é for example) in an XML or text file and load it into Flash, you will find that Flash does not handle these letters appropriately. The accented letter and the next few characters don't show up. The solution is to save the text or XML file as Unicode. Most text editors have this function. For Windows XP users, this can be done with the new version of Notepad: select File > Save As and set the encoding to Unicode in the bottom combo box:

As for Oriental languages using different character sets, this thread may be of some help.
Using startDrag cancels all other startDrag actions before it. This may be an issue if for example, you need to drag both a custom cursor and ordinary movieclip, as only one will work. Here's a simple way to simulate a drag without actually using startDrag:
[as]myMC.onMouseMove = function()This will make the movieclip myMC follow the mouse. For a more comprehensive approach to this, please take a look at the new beginDrag and endDrag functions by Senocular.
With all of this info in mind, you should be able to debug a Flash movie without too much trouble. Remember that patience is key. Try everything you can think of several times even before throwing in the towel. It's the only way to learn.
If you need professional help with ActionScript, please visit 5etdemi.com for my portfolio and contact info. Happy flashing!