PDA

View Full Version : Frequently Asked Questions


TheCanadian
08-05-2006, 11:50 PM
I've noticed a lot of questions asked with increasing frequency so I thought it would be fitting to have a FAQ thread in this forum.

Feel free to PM me with questions/suggestions/need for clarification/etc. Unlinked topics are in progress.

How do you use {any function name}? (http://www.kirupa.com/forum/showpost.php?p=1922767&postcount=2)

General Syntax/Miscellaneous Questions

Why do my if statements always or never work? (http://www.kirupa.com/forum/showpost.php?p=1923634&postcount=15)

Why does hitTest detect collisions even if my movie clips aren't touching? (http://www.kirupa.com/forum/showpost.php?p=1922772&postcount=4)

What are advantages of strict data types for variables (http://www.kirupa.com/forum/showpost.php?p=2000353&postcount=27)? (http://www.kirupa.com/forum/showpost.php?p=2000353&postcount=27)

Can I change the frame rate of my movie? (http://www.kirupa.com/forum/showpost.php?p=2007460&postcount=29)

How come I must click on my Flash movie in IE before I can interact with it? (http://www.kirupa.com/forum/showpost.php?p=2009008&postcount=31)

How can I reference objects using a variable? (http://www.kirupa.com/forum/showpost.php?p=2059193&postcount=36)

Function Related Questions

What's the difference between function myFunction(){} and myFunction = function(){}? (http://www.kirupa.com/forum/showpost.php?p=2000319&postcount=25)

Why do functions created using a loop reference the last iteration of that loop? (http://www.kirupa.com/forum/showpost.php?p=1922781&postcount=7)

How do I pass arguments to an event handler? (http://www.kirupa.com/forum/showpost.php?p=2059170&postcount=35)

TextField Related Questions

When I try to add numbers to a text field, why do they appear beside the text? (http://www.kirupa.com/forum/showpost.php?p=1922770&postcount=3)

How can I use htmlText to call an ActionScript function? (http://www.kirupa.com/forum/showpost.php?p=2008999&postcount=30)

Why does my text disappear when I rotate/fade/mask/etc it?

External Movie/Data Related Questions

My movie works on its own but doesn't when I load it into another movie. What gives? (http://www.kirupa.com/forum/showpost.php?p=1922775&postcount=5)

How come I can't use data from LoadVars or XML after I call load? (http://www.kirupa.com/forum/showpost.php?p=1922778&postcount=6)

Why does my preloader not appear for a while then start at an insanely high number? (http://www.kirupa.com/forum/showpost.php?p=1924518&postcount=16)

How can I access the properties of a loaded image/movie? (http://www.kirupa.com/forum/showpost.php?p=1941410&postcount=21)

Why doesn't onLoad work the same as onClipEvent(load) or for loading movies? (http://www.kirupa.com/forum/showpost.php?p=2036973&postcount=32)

How do I use special characters in XML or text files?

OOP Related Questions

Why can't I add properties to a class? (http://www.kirupa.com/forum/showpost.php?p=1925596&postcount=19)

Why won't some obscure functions, such as setTimeout, work in my classes? (http://www.kirupa.com/forum/showpost.php?p=2062078&postcount=37)

How come my class won't work even though there is nothing wrong with the code? (http://www.kirupa.com/forum/showpost.php?p=2097846&postcount=39)

How can I used reserved, private or irregular (ie those starting with numbers/punctuation) keywords as my own properties?

How come I can't create instances of a MovieClip subclass with the new operator?


:hoser:

TheCanadian
08-05-2006, 11:50 PM
Look in the help file included with Flash (Help>Flash Help or F1) or the Adobe LiveDocs (http://livedocs.macromedia.com/) ;)

TheCanadian
08-05-2006, 11:54 PM
The Problem
When trying to add a number to a text field, the number just appears beside the original text, eg:
myTextField.text = "15";
myTextField.text = myTextField.text + 3; //the text field shows 153

The Answer
This happens for two reasons. One, because the text in a text field is of type string. And two, because the + operator performs both addition and concatenation (joining strings). When using this operator, Flash will determine which operation, out of the two, to carry out based on the data types of the two expressions:

string + string = string
number + string = string
string + number = string
number + number = number

As you can see, whenever Flash finds a string as one of the expressions, it performs the concatenation operation (pretty catchy name). And as I mentioned earlier, the text in the text field is a string so you'll get the number converted to a string and concatenated with the other string (resulting in the problem above). The solution is to simply convert the text string to a number. This is usually done using the top-level Number function however it can also be done using parseInt or parseFloat (more info in the help file):
myTextField.text = "15";
myTextField.text = Number(myTextField.text) + 3; //the text field shows 18

TheCanadian
08-06-2006, 12:00 AM
The Problem
When checking for collisions between two movie clips, Flash will often detect that they are touching even though they are not. For example, these movie clips are detected as colliding
http://img145.imageshack.us/img145/8310/redhitbluebo5.png

The Answer
The MovieClip.hitTest method detects when the bounding boxes of a movie clip have collided, rather than the actual shapes of them. As you can see below, the bounding boxes of the above two movie clips are overlapping which is why the hitTest method will detect a collision:
http://img145.imageshack.us/img145/3648/redhitblueboundingoz9.png

There are a few simple ways to get around this, the two most common being:

1) Create smaller movie clips around the perimeter of your colliding movie clips and detect collisions between those, as explained in this tutorial by Jeremy Moseley: http://www.kirupa.com/developer/actionscript/advanced_collision.htm

2) If you are using Flash 8, you can use the BitmapData class to perform pixel-level collision detecting between two movie clips:
import flash.display.BitmapData;
import flash.geom.Point;
MovieClip.prototype.pixelHitTest = function(mc:MovieClip, threshold:Number):Boolean {
threshold = threshold ? treshold : 1;

var thisBitmap:BitmapData = new BitmapData(this._width, this._height, true, 0);
thisBitmap.draw(this);
var mcBitmap:BitmapData = new BitmapData(mc._width, mc._height, true, 0);
mcBitmap.draw(mc);

if(thisBitmap.hitTest(new Point(this._x, this._y), threshold, mcBitmap, new Point(mc._x, mc._y), threshold)) {
return true;
}
return false;
}
(see attached FLA)

TheCanadian
08-06-2006, 12:08 AM
This is most commonly caused by the use of the _root property in your loaded movie. _root is a reference to the level that the movie clip resides in. Let's say that this is the structure of your movie to be loaded:
http://img424.imageshack.us/img424/7421/loadedtimelineid9.png

As you can see, _root refers to the level that each movie clip is in and all is fine and dandy. But when we load the movie into another, things begin to go wrong:
http://img424.imageshack.us/img424/2171/loadertimelineru5.png

What happens here is _level0 of the loaded movie becomes the container movie clip and all of it's children become children of the container. Any _root references now link to the level that the container is in and the code will not work. Here's what we can do about this:

1) Don't use _root. Instead reference movie clips relatively through _parent and instance names:
http://img424.imageshack.us/img424/927/loadedtimelinerelativemc1.png

http://img424.imageshack.us/img424/6300/loadertimelinerelativenn5.png

2) Use the MovieClip._lockroot property which makes _root always refer to the same movie clip, no matter what you load it into. There is more info on this property in the help file.

3) Load the movie into a level instead of a movie clip using loadMovieNum:
http://img424.imageshack.us/img424/1444/loadertimelinelevelck8.png

TheCanadian
08-06-2006, 12:14 AM
The Problem
this.lv = new LoadVars();
this.lv.load("some.txt");
trace(this.lv.variables); //undefined

The Answer
ActionScript code is executed almost instantaneously (each line can be read in a matter of microseconds). External data on the other hand is not loaded instanataneously. Flash must connect to the server and download all of the bytes that make up the file which can take some time. By the time the data is loaded, Flash will have already executed a lot of code. This is where the onLoad event comes into play, Flash will call this function when the data is loaded:
this.lv = new LoadVars();
this.lv.load("some.txt");
this.lv.onLoad = function():Void {
trace(this.variables); //all data in some.txt's variables property is outputted
}

Be warned though, you can't access the data after the definiton of the onLoad event:
this.lv = new LoadVars();
this.lv.load("some.txt");
this.lv.onLoad = function():Void {
stuff = this.variables;
}
trace(stuff); //undefined since this line is executed before the onLoad event has been called
You must rather manipulate all of your data in the onLoad event.

TheCanadian
08-06-2006, 12:18 AM
The Problem
When creating functions in a for loop and using the iterated variable of the loop, all of the functions will reference the last value of that variable:
for(var i:Number = 0; i < 3; i++) {
this["function" + i] = function():Void {
trace(i);
}
}
function0(); //3
function1(); //3
function2(); //3

The Answer
Any function created in a loop does not retain the value of the variable when it's created. Instead it get's the value of that variable when it is called. Since the functions are called after the loop is completed, each one will use the last value of the variable.The most common example of this mistake is found when creating events for buttons:
for(var i:Number = 0; i < 3; i++) {
var mc:MovieClip = this.attachMovie("myButton", "myButton" + i, i);
mc.onPress = function():Void {
trace(i);
}
}
Here, each button will trace 3 since that is the last value of i in the loop. We can fix this by storing the value of i in a variable that is specific to each button:
for(var i:Number = 0; i < 3; i++) {
var mc:MovieClip = this.attachMovie("myButton", "myButton" + i, i);
mc.index = i;
mc.onPress = function():Void {
trace(this.index);
}
}
Now pressing one of the buttons will output the value of i when it was created.

scotty
08-06-2006, 03:10 AM
Thank you for making this thread, good idea :thumb:

scotty(-:

senocular
08-06-2006, 01:33 PM
Added to the resources thread :)

Anogar
08-06-2006, 02:26 PM
Excellent resource. Thanks for making this. :thumb:

Jeff Wheeler
08-06-2006, 11:56 PM
Allen: I suggest you try making a thread specifically for your question. :)

This should be stickied. :thumb:

phorte
08-07-2006, 12:06 AM
This is pretty much the best thread i have ever seen!
Nice work! Give this man a medal!:thumb2:

scotty
08-07-2006, 12:57 AM
Moved Allens questions here
http://www.kirupa.com/forum/showthread.php?t=229816

scotty(-:

TheCanadian
08-07-2006, 02:36 AM
Haha - high praise :thumb:

TheCanadian
08-07-2006, 02:54 AM
The Problem
When trying to use if statements, either the code always executes or it never does. Example:
if(myCondition = true) {
//always executes
}
if(myCondition = false) {
//never executes
}

The Answer
The problem here is the use of the wrong operator. The = operator is used for assigning values to variables and not for comparing two values. So in this code:
if(myCondition = true) {}
myCondition first gets set to true and then that value is returned, giving you this:
if(true) {}
Which is why the code in the brackets is executed every time.

The direct comparison of values is left to, well, the comparison operator (==). Simply use this operator and everything should go smoothly:
if(myCondition == true) {}

TheCanadian
08-07-2006, 11:10 PM
There are two possible causes to this:

1) Your preloader itself takes up an insane size in your movie. If it's, for example, 50% of the total size of your movie then by the time it is loaded and displays on the stage your movie will be half loaded. You can have Flash generate a size report when you publish your movie so you can see how the bytes of your movie are distributed between frames. In the Publish Settings:
http://img328.imageshack.us/img328/1862/sizereportjx4.png

2) You have a lot of movie clips and AS2 classes exported for the first frame. When Flash compiles your movie, it removes all unused symbols from the library to reduce file size. That is, any symbols not placed on the timeline at some point in your movie are removed. However, the compiler has no way to tell which symbols are used in the AS of your movie. This is why, when setting up a linkage ID for your movie clips, you must check export for first frame so that the compiler will know that you want to use the symbols in AS and consequently will not remove them during it's optimization. And that is what gums up the works. All of those symbols must be loaded before the first frame which means that your preloader cannot display until they have finished.

The solution is not to export them for the first frame. But to prevent them from being removed at compile time you must have them appear somewhere on the timeline of your movie. Having all of the symbols used in AS one frame after your preloader is sufficent to be able to use them in the rest of your movie. Then when the movie is loaded, skip this frame to the beginning of your movie:
http://img70.imageshack.us/img70/2467/preloadertimelinezn9.png

AS2 classes are another part of this problem since they are also exported before the first frame. This can be changed very easily however in the AS settings dialogue:
http://img123.imageshack.us/img123/8995/assettingsuj5.png

Note that if you export the classes to a frame later than any symbols using them, those symbols will fail to work correctly.

For more info, here is a very comprhensive preloading tutorial by senocular:
http://www.senocular.com/flash/tutorials/preloading/

phorte
08-08-2006, 03:01 AM
Embeded fonts should be in here i reckon. That question comes up so much around here.

Also, nice work on the latest topics. Keep up the good work! :thumb:

Jeff Wheeler
08-08-2006, 03:09 AM
Make sure to mention the pixelation problem…

TheCanadian
08-08-2006, 08:38 PM
The Problem
When trying to add properties to a class, the compiler gives an error saying that there is no such property:
Math.myMethod = function():Void {} //error

The Answer
The problem here is with how the class is defined and is more of a thing you'll have to accept rather than fix. A class can be either dynamic or non-dynamic. Dynamic classes can have properties added to them outside of the class definition whereas non-dynamic classes cannot. The Array class, for example, is dynamic since it needs to have all of the indexes added to it dynamically. If it was not dynamic, you would need to declare an infinite amount of properties in the class definition. Non-dynamic classes have all of there properties declared in the class definition and they are limited to those and only those properties. The Math class is not dynamic which means that you cannot add properties to it outside of the class definition (which is why the compiler gives you an error if you try to do just that). The best and most recommended solution is to extend the class and add your properties in there, or make it dynamic and add them from the class.

See senocular's tutorial on OOP for more information:
http://www.kirupa.com/developer/oop2/AS2OOPClassStructure7.htm

TheCanadian
08-08-2006, 08:40 PM
Thanks for the comments, I'll write something about embedding fonts and why fonts are blurry at some point in the future :)

TheCanadian
08-25-2006, 11:06 PM
The Problem
When loading an image into a movie clip, the width is never accurate:
this.createEmptyMovieClip("myMovieClip", 1);
myMovieClip.loadMovie("myImage.png");
trace(myMovieClip._width); //0

The Answer
This is pretty much the same deal as How come I can't use data from LoadVars or XML after I call load? (http://www.kirupa.com/forum/showpost.php?p=1922778&postcount=6) The image hasn't loaded by the time your code has executed which means that your movie clip will be unchanged and thus have the same width as before you started the loading. The solution is a bit different with movie clips, however:

You must have a continuous comparison of the bytes loaded into the movie and the total bytes of the image being loaded. When they are equal, the image has completely loaded and you can get the correct width:
this.createEmptyMovieClip("myMovieClip", 1);
myMovieClip.loadMovie("myImage.png");
myMovieClip.onEnterFrame = function():Void {
if(this.getBytesLoaded() == this.getBytesTotal()) {
trace(this._width); //width of loaded image
}
}
More on how to do this correctly and an alternate approach (thanks scotty):
http://www.kirupa.com/forum/showpost.php?p=1941575&postcount=22

You can use the MovieClipLoader class, which does the process described above in its internal workings and has a lot of functionality for monitoring the progress of the download:
this.createEmptyMovieClip("myMovieClip", 1);
imageLoader = new MovieClipLoader();
imageLoaderListener = new Object();

imageLoader.loadClip("myImage.png", myMovieClip);
imageLoader.addListener(imageLoaderListener);
imageLoaderListener.onLoadInit = function(targetMC:MovieClip):Void {
trace(targetMC._width); //width of loaded image
}


The Problem
When loading an image into a movie clip, the width is never accurate:
this.createEmptyMovieClip("myMovieClip", 1);
myMovieClip.loadMovie("myImage.png");
trace(myMovieClip._width); //0

The Answer
This is pretty much the same deal as How come I can't use data from LoadVars or XML after I call load? (http://www.kirupa.com/forum/showpost.php?p=1922778&postcount=6) The image hasn't loaded by the time your code has executed which means that your movie clip will be unchanged and thus have the same width as before you started the loading. The solution is a bit different with movie clips, however:

You must have a continuous comparison of the bytes loaded into the movie and the total bytes of the image being loaded. When they are equal, the image has completely loaded and you can get the correct width:
this.createEmptyMovieClip("myMovieClip", 1);
myMovieClip.loadMovie("myImage.png");
myMovieClip.onEnterFrame = function():Void {
if(this.getBytesLoaded() == this.getBytesTotal()) {
trace(this._width); //width of loaded image
}
}
More on how to do this correctly and an alternate approach (thanks scotty):
http://www.kirupa.com/forum/showpost.php?p=1941575&postcount=22

You can use the MovieClipLoader class, which does the process described above in its internal workings and has a lot of functionality for monitoring the progress of the download:
this.createEmptyMovieClip("myMovieClip", 1);
imageLoader = new MovieClipLoader();
imageLoaderListener = new Object();

imageLoader.loadClip("myImage.png", myMovieClip);
imageLoader.addListener(imageLoaderListener);
imageLoaderListener.onLoadInit = function(targetMC:MovieClip):Void {
trace(targetMC._width); //width of loaded image
}

scotty
08-26-2006, 06:00 AM
Two notes on the loadMovie.
As soon as you load the picture in a movieclip, you can't use that movieclips onenterframe. The code will act like you've stated in the problem, it will perform the loadMovie command, but trace 0. Better is to create another mc and use that one's onenterframe to check if the picture is loaded.
In theory, there's a moment that both bytesloaded and bytestotal are equal so it's better to check for bytesTotal as well. (Although it's not very likely this will happen on broadband connections)
var mc = this.createEmptyMovieClip("myMovieClip", 1);
myMovieClip.loadMovie("myImage.png");
var temp = this.createEmptyMovieClip("temp", 2);
temp.onEnterFrame = function():Void {
if (mc.getBytesLoaded() == mc.getBytesTotal() && mc.getBytesTotal()>0) {
trace(mc._width);
//width of loaded image
delete this.onEnterFrame;
}
};

Or you can check for the pictures width
var mc = this.createEmptyMovieClip("myMovieClip", 1);
myMovieClip.loadMovie("myImage.png");
var temp = this.createEmptyMovieClip("temp", 2);
temp.onEnterFrame = function():Void {
if (mc._width) {
trace(mc._width);
//width of loaded image
delete this.onEnterFrame;
}
};


scotty(-:

TheCanadian
08-27-2006, 01:43 AM
Thanks for the additional information scotty, I added a link to your post in the answer :mountie:

scotty
08-27-2006, 04:11 AM
:thumb:

TheCanadian
11-15-2006, 12:10 AM
Although both are fundamentally the same there are some important differences. The declaration function myFunction(){} is called a named function. myFunction = function(){} is called an anonymous function and is basically a function literal referenced by a variable.

1) Named functions are parsed before any other code being executed in the frame. That is, they can be called prior to their definition in the script. Anonymous functions cannot. For example, this will work:
//named function
f(15); //15
function f(x) {
trace(x);
}
Whereas this will not:
//anonymous function
f(15); //
f = function(x) {
trace(x);
}

2) Named functions cannot be defined within statement blocks (if, for, while, etc.) whereas anonymous functions can. For example, this will work:
//anonymous function
if(true) {
f = function(x) {
trace(x);
}
}
f(15); //15
Whereas this will not:
//named function
if(true) {
function f(x) {
trace(x);
}
}
f(15); //

3) Named functions cannot be used to declare the function in a scope other than the current scope. Since anonymous functions are just function literals assigned to a variable, they can be defined in the scope of any object in existence. For example, an anonymous function such as this:
//anonymous function
myXML = new XML();
myXML.onLoad = function() {}
Is not possible with named functions.

4) Named functions are used in AS2 class method and constructor declaration:
class MyClass {
function MyClass(){}
function classMethod(){}
}
Senocular also makes a good point about named functions and class methods in AS3:
for AS3 . . . scripts in timelines, named functions are methods [of the timeline's class] and anonymous functions are simply variables of the type Function



Whenever I try to write anonymous I subconsciously add an e at the end making it anonymouse. Every time! :fist:

B L U E
11-15-2006, 12:15 AM
i have one tC. What are the benefits of using Void as return types and parameters? such as

ActionScript Code:
function onEnterFrame(Void):Void {





vs

ActionScript Code:
function onEnterFrame() {




always been a minor thing i never understood

TheCanadian
11-15-2006, 12:56 AM
In AS2:
There is no advantage to the end user, data typing in AS2 is only for compiler error checking to help you code. This is because all variables are typed dynamically at run-time by the Flash Player.

For example, if you try to assign a String object to a variable which is meant to reference a Number, you will get an error:
var n:Number;
n = new String("hello"); //**Error** Type mismatch in assignment statement: found String where Number is required.
If you didn't use strict data types for your variables, the compiler would assume everything is okay and you would be stuck wondering why the movie doesn't work the way it should:
var n;
n = new String("hello"); //is fine according to the compiler
n += 10; //expecting n to be a number
trace(n); //will get hello10 when you expect some number
The same applies to function return types since function returns are just references to objects in the memory which have types. If you assign the return of String.substring (which returns a String) to a variable with type Number, you will get an error the same way you got one above.

Void return types follow the same story since they also indicate a type (or more correctly an absence) of data. If you were to try to assign the return of Array.reverse (for instance) to a strictly typed variable, you would get an error since the function has Void as it's return type (which, by definition, a variable cannot reference).

In AS3:
Strictly typed variables in AS3 will boost the performance of your movie since it will allow the virtual machine to know the types of your variables ahead of time.
In ActionScript 3.0, type information is preserved at runtime and utilized for a number of purposes. Flash Player performs runtime type checking, improving the system's type safety. Type information is also used to represent variables in native machine representations, improving performance and reducing memory usage.

TheCanadian
11-15-2006, 12:59 AM
i have one tC. What are the benefits of using Void as return types and parameters? such as

ActionScript Code:

function onEnterFrame(Void):Void {






vs

ActionScript Code:

function onEnterFrame() {





always been a minor thing i never understood
Hopefully the above answers your question. Using Void as the parameter of a function is just a convention to indicate that there should be no arguments but is not checked by the compiler :)

TheCanadian
11-25-2006, 04:38 PM
1) You can use setInterval to control the speed at which your timeline plays and/or as an alternative to onEnterFrame events.

To adjust the speed at which the timeline plays, we can call a function which advances to the next frame:
this.stop();
this.desriedFrameRate = 30;
this.playRateInt = setInterval(this, "nextFrameSI", 1000 / this.desriedFrameRate);
function nextFrameSI():Void {
this.nextFrame();
updateAfterEvent();
}
We must call updateAfterEvent if the desiredFrameRate is higher than the actual frame rate of your movie so that the stage will be redraw when you advance the frame (rather than on the movies regular interval).

Since setInterval is used to call functions over an interval, it can be used as an alternative to onEnterFrame if you need it to run slower or faster:
this.desiredFrameRate = 5;
this.callFunctionInt = setInterval(this, "otherOnEnterFrame", 1000 / this.desiredFrameRate);
function otherOnEnterFrame():Void {
trace("onEnterFrame");
}

Note that the above two methods do not actually change the frame rate of your movie, but rather allows you to control the rate at which the timeline plays and at which some functions are called.

2) You can use streaming sound to directly change the frame of your main movie:
prior to AS3 you can also change the frame rate of the player by loading in a movie that has a streamed sound in it. The frame rate of that movie will then be used for your main movie (this has worked since at least Flash 5 if I remember right)
See attached example.

3) In AS3:
This can be done very easily. Just set the Stage.frameRate property to your desired frame rate (between 0.01 and 1000).

TheCanadian
11-28-2006, 01:25 AM
This is done using an anchor tag and the asfunction protocol. It looks something like this:

asfunction:function:Function, parameter:String

Note that the parameter is optional.

The usage is fairly straight forward and there is a lot of information in the help files/LiveDocs but I'll go over some sample usages.

The Basics
this.createTextField("myTextField", 1, 10, 10, 0, 0);
this.myTextField.autoSize = true;
this.myTextField.html = true;
this.myTextField.htmlText = "<a href='asfunction:traceArgs,hello world!'>Press Me</a>";
function traceArgs(a:String):Void {
trace(a);
}
Whenever you press the text, Flash will output "hello world!"

Passing Multiple Arguments
The asfunction protocol only allows you to pass one argument to the function, but this can be easily remedied by using a character as a delimiter and splitting the string argument inside the function.
this.createTextField("myTextField", 1, 10, 10, 0, 0);
this.myTextField.autoSize = true;
this.myTextField.html = true;
this.myTextField.htmlText = "<a href='asfunction:traceArgs,arg1, arg2, arg3, argN'>Press Me</a>";
function traceArgs(a:String):Void {
var args:Array = a.split(", ");
for(var i:Number = 0; i < args.length; i++) {
trace(args[i]);
}
}
Now when you press the text, Flash will output each intended argument as an independant element of the args array.

Calling Functions in Different Scopes
To call a function in another scope, simply add the path to and the instance name of the movie clip before the function call - as in any other AS code:
this.myObject = new Object();
this.myObject.method = function():Void {
trace("called");
}
this.createTextField("myTextField", 1, 10, 10, 0, 0);
this.myTextField.autoSize = true;
this.myTextField.html = true;
this.myTextField.htmlText = "<a href='asfunction:myObject.method'>Press Me</a>";
Whenever you press the text, "called" is outputted.



And that's about all there is to know to call AS functions from TextFields.

TheCanadian
11-28-2006, 01:47 AM
In the wake of losing a patent lawsuit with Eolas (http://en.wikipedia.org/wiki/Eolas), Microsoft announced on December 2, 2005, that "native" support for ActiveX has been dropped: "After a forthcoming update, Microsoft Internet Explorer users will not be able to directly interact with Microsoft ActiveX controls loaded by the APPLET, EMBED, or OBJECT elements."[1] (http://msdn.microsoft.com/ieupdate/) Functionally, this means that Internet Explorer users would still be able to use ActiveX but would have to explicitly "activate" objects such as Flash navigation bars and QuickTime (http://en.wikipedia.org/wiki/QuickTime) movies before they could interact with them. The objects still display, but the user can no longer do anything with them (for example, pause a playing movie) until they activate them. When users move their cursors over such an object a pop-up window directs them to "Click to activate and use this control." If they then click on the object, they may subsequently use it in the old fashion.
Quote from:
http://en.wikipedia.org/wiki/Activex#ActiveX

See this article for more information:
http://en.wikipedia.org/wiki/Eolas


Kirupa has an excellent tutorial to fix this issue, which can be found here:
http://www.kirupa.com/developer/flash8/flash_fix.htm

TheCanadian
01-07-2007, 09:39 PM
The MovieClip.onLoad method is called when a movie clip with a MovieClip sub-class association is instantiated - not for the creation of any movie clip or with the loading of a movie.

There is no time line based alternative for onClipEvent(load), that is you cannot have an event handler called when a movie clip is created like you would if your action script was placed directly on the movie clip. Actions on a frame are executed when the time line reaches that frame. Therefore simply putting the action script you want to execute when the movie clip is created on the frame that the movie clip is created on should suffice.

As said above, onLoad is not for use with loading movies either.

If you are loading a movie with MovieClip.loadMovie, you will have to determine when the movie is loaded by creating a periodic comparison of MovieClip.getBytesLoaded() versus MovieClip.getBytesTotal(), when they are equal the movie has been loaded.
If you are using MovieClipLoader.loadClip to load your movies, then you should use the various events associated with that class to determine the status of the loading process.

kookaburra
01-08-2007, 06:41 AM
THe BitmapData is just amazing. Thanks Canadian!

TheCanadian
01-08-2007, 11:01 AM
No problem :)

TheCanadian
02-05-2007, 07:11 PM
The Problem
When trying pass arguments to an event handler, the function gets called immeadiately and the event handler doesn't work. For example:
myButton.onPress = myPressFunction(arg1, arg2);

The Answer
When you assign a function to an event handler such as onPress, you are assigning a reference to a function. Example:
myButton.onPress = myPressFunction;
This will mean that the Flash Player will call the function when the button is pressed, this is where arguments (if any) are passed to the function. There is no way to pass arguments to the function, it's kind of backwards thinking. What you'll have to do is make the arguments you wish to pass to the function as variables in the scope of some object, ideally the object for which the event handler is a property of:
myButton.onPress = myPressFunction;
myButton.arg1 = "hello";
myButton.arg2 = "world";
function myPressFunction() {
trace(this.arg1); //hello
trace(this.arg2); //world
}

Thanks to pablo2006 for suggesting and helping to write this answer/question :hugegrin:

TheCanadian
02-05-2007, 07:55 PM
The Problem
How can I reference objects using a variable? This is commonly a problem with dynamically created buttons:
for(i = 0; i < 3; i++) {
button+i.someProp = "Hello World!"; //error
}

The Answer
This is probably the question that gets asked the most on these forums. Referencing an object with a variable is done using something called associative array referencing or array notation. The fundamental concept behind this is that:
myObject.prop = "value";
//and
myObject["prop"] = "value";
Are the same thing. Associative array referencing follows the pattern of scope["prop"] where scope is the object which contains the property and prop is the name of the property you wish to reference. Save appearance, array notation works in exactly the same way as dot notation.

Going back to the original, problematic, example, the correct code would look like this:
for(i = 0; i < 3; i++) {
this["button"+i].someProp = "Hello World!";
}
The button string is concatenated (joined) with the i variable, forming a new reference with each iteration of the loop. First button0, then button1, et cetera.

That's the quick, but some of you may think that that's the same notation that is used with instances of the Array class. While that is true, the converse is actually more correct: Array instances use that notation.

Arrays are exactly the same as generic Objects, the only difference is that they have a collection of methods to deal with their properties. And because they require a need for organization, they typically only use numerical properties. Given the array myArray = ["a", "b", "c"], you could theoretically reference the indices using myArray.0, myArray.1 and myArray.2. The reason that we must use array notation is because the compiler doesn't allow the reference of numerical properties with dot notation.

TheCanadian
02-09-2007, 07:37 PM
When creating a class, the compiler will assume that all references to objects are references to objects that are members of the class unless otherwise specified. Since setTimeout is a top-level function (one in the _global scope), you must reference it through the use of _global:
_global.setTimeout(/*arguments*/);

But why do other top-level functions work in classes? Well this has to do with the top-level function definition. Most global functions are intrinsically declared as top-level in an AS file thus allowing Flash to recognize which functions should not need reference in class files. However, for whatever reason, Macromedia (now Adobe) decided not to declare some functions, including setTimeout, as top-level which is why the compiler won't recognize them.

This can be easily remedied by manually adding setTimeout (and any other functions you wish to use) to the aforementioned AS file. Navigate to and open Install Directory>Flash 8>language>First Run>Classes>toplevel.as and add the following ActionScript somewhere in the file:
intrinsic function setTimeout():Number;
You will need to restart Flash. Now you can use this function in your class files without the global reference.

superbungalow
03-26-2007, 04:38 PM
The Problem
When checking for collisions between two movie clips, Flash will often detect that they are touching even though they are not. For example, these movie clips are detected as colliding
http://img145.imageshack.us/img145/8310/redhitbluebo5.png

The Answer
The MovieClip.hitTest method detects when the bounding boxes of a movie clip have collided, rather than the actual shapes of them. As you can see below, the bounding boxes of the above two movie clips are overlapping which is why the hitTest method will detect a collision:
http://img145.imageshack.us/img145/3648/redhitblueboundingoz9.png

There are a few simple ways to get around this, the two most common being:

1) Create smaller movie clips around the perimeter of your colliding movie clips and detect collisions between those, as explained in this tutorial by Jeremy Moseley: http://www.kirupa.com/developer/actionscript/advanced_collision.htm

2) If you are using Flash 8, you can use the BitmapData class to perform pixel-level collision detecting between two movie clips:
ActionScript Code:
import flash.display.BitmapData;
import flash.geom.Point;
MovieClip.prototype.pixelHitTest = function(mc:MovieClip, threshold:Number):Boolean {
threshold = threshold ? treshold : 1;

var thisBitmap:BitmapData = new BitmapData(this._width, this._height, true, 0);
thisBitmap.draw(this);
var mcBitmap:BitmapData = new BitmapData(mc._width, mc._height, true, 0);
mcBitmap.draw(mc);

if(thisBitmap.hitTest(new Point(this._x, this._y), threshold, mcBitmap, new Point(mc._x, mc._y), threshold)) {
return true;
}
return false;
}




(see attached FLA)

could you by any chance explain that code a bit further for us newbies (well, me)? specifically:

MovieClip.prototype.pixelHitTest = function(mc:MovieClip, threshold:Number):Boolean {
threshold = threshold ? treshold : 1;

and:

if(thisBitmap.hitTest(new Point(this._x, this._y), threshold, mcBitmap, new Point(mc._x, mc._y), threshold)) {
return true;
}
return false;
}

TheCanadian
04-03-2007, 12:58 AM
Well more often than not, there is something wrong with the code. But if you're absolutely positive that your coding is sound, then this may be an issue with Flash's class caching functionality.

Basically when you compile a class, Flash will cache it in your install directory as an ActionScript Object or ASO file. When you compile a movie, Flash will also compile all of the classes used. If the class is already cached as an ASO, Flash will see that it is already compiled and won't compile it again unless it is an older version of the class (different timestamp). Sometimes, however, Flash may ignore newer versions of the class in favour of the ASO file.

More by senocular here:
http://www.kirupa.com/developer/oop2/AS2OOPClassFileManage5.htm
And the Adobe documentation:
http://livedocs.adobe.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001338.html

To force Flash to re-compile the newest version of your class you must delete the ASO file(s).

In Flash 8: Control>Delete ASO Files

In Flash MX04: You have to manually delete the files from your computer. Alternatively you can download an extension to automate this process, such as:
http://www.adobe.com/cfusion/exchange/index.cfm?extid=1016963&view=sn111#loc=en_us&extid=1016963&view=sn111&viewName=Adobe%20Exchange&avm=1

iceblueflame
04-11-2007, 03:29 AM
Firstly, for this function to work, the movie clip should have been brought into the flash file using attachMovie() or createEmptyMovieClip().

If the function still doesnt work, then you're probably using getNextHighestDepth() to assign a depth to the clip when its created. The problem is that at some point, this function gives negative depth values to the movieclip. removeMovieClip() cannot remove clips with negative depth values. So you can either use swapDepths() to change the depth or simply replace removeMovieClip() with unloadMovie().

NickZA
06-11-2007, 01:24 PM
I'd like to suggest that this post be turned into an article because it took me a *heck* of a long time to track down this solution, hiding here in the forums coyly.

There are a lot of dead ends out there when searching for Flash pixel-perfect collision detection.

Anyway, many many thanks to TheCanadian for making this clear and simple.

:mountie:

-NickZA

Rozzadon
06-26-2007, 06:23 PM
But this wont work in as 3.
i used to be able to do the following (in as2):
this["box"+i].alpha = 50;

any suggestions on how to make this happen in AS 3?
example:
package{
import flash.display.Sprite;

dynamic public class Test extends Sprite{
for(var i:Number = 1; i <= 3; i++) {
this["box"+i].alpha = .5;
}
}
}

The Problem
How can I reference objects using a variable? This is commonly a problem with dynamically created buttons:
for(i = 0; i < 3; i++) {
button+i.someProp = "Hello World!"; //error
}

The Answer
This is probably the question that gets asked the most on these forums. Referencing an object with a variable is done using something called associative array referencing or array notation. The fundamental concept behind this is that:
myObject.prop = "value";
//and
myObject["prop"] = "value";
Are the same thing. Associative array referencing follows the pattern of scope["prop"] where scope is the object which contains the property and prop is the name of the property you wish to reference. Save appearance, array notation works in exactly the same way as dot notation.

Going back to the original, problematic, example, the correct code would look like this:
for(i = 0; i < 3; i++) {
this["button"+i].someProp = "Hello World!";
}
The button string is concatenated (joined) with the i variable, forming a new reference with each iteration of the loop. First button0, then button1, et cetera.

That's the quick, but some of you may think that that's the same notation that is used with instances of the Array class. While that is true, the converse is actually more correct: Array instances use that notation.

Arrays are exactly the same as generic Objects, the only difference is that they have a collection of methods to deal with their properties. And because they require a need for organization, they typically only use numerical properties. Given the array myArray = ["a", "b", "c"], you could theoretically reference the indices using myArray.0, myArray.1 and myArray.2. The reason that we must use array notation is because the compiler doesn't allow the reference of numerical properties with dot notation.

GrndMasterFlash
08-28-2007, 01:31 PM
fe does who want to use this beautiful script in AS3, this is how i got it working

//Convert to AS3
import flash.geom.Point;
import flash.display.BitmapData;
import flash.display.*;
import flash.events.*;

function drager(Event):void {
//trace(pixelHitTest(red, blue, undefined));
if (pixelHitTest(red, blue, undefined)) {
this.red.alpha = .5 ;
this.blue.alpha = .5;
} else {
this.red.alpha = 1 ;
this.blue.alpha = 1;
}
}

function dstart(event:MouseEvent) {
witch = event.currentTarget.name;
targ = getChildByName(witch);
targ.startDrag();
}
function dstop(event:MouseEvent) {
witch = event.currentTarget.name;
targ = getChildByName(witch);
targ.stopDrag();
}
red.addEventListener(MouseEvent.MOUSE_DOWN, dstart);
red.addEventListener(MouseEvent.MOUSE_UP, dstop);
blue.addEventListener(MouseEvent.MOUSE_DOWN, dstart);
blue.addEventListener(MouseEvent.MOUSE_UP, dstop);
stage.addEventListener(Event.ENTER_FRAME, drager);

Class MovieClip function pixelHitTest(mc1:MovieClip, mc2:MovieClip, threshold:Number):Boolean {
var threshold = threshold ? threshold : 1;

var thisBitmap:BitmapData = new BitmapData(mc1.width, mc1.height, true, 0);
thisBitmap.draw(mc1);

var mcBitmap:BitmapData = new BitmapData(mc2.width, mc2.height, true, 0);
mcBitmap.draw(mc2);

if (thisBitmap.hitTest(new Point(mc1.x, mc1.y), threshold, mcBitmap, new Point(mc2.x, mc2.y), threshold)) {
return true;
}
return false;
}much thanx to TheCanadian for the AS2 version, it is genius! :hr:

**btw, if you use this technique make sure the registration point is in the upper left corner, so the bit map lays directly over, other wise this hunk of beauty will not work right

synax
09-14-2007, 03:23 PM
Help -> ActionScript 3.0 Language and Components Reference -> ActionScript 2.0 Migration

SpaceHunter
09-20-2007, 10:19 PM
fe does who want to use this beautiful script in AS3, this is how i got it working

//Convert to AS3
import flash.geom.Point;
import flash.display.BitmapData;
import flash.display.*;
import flash.events.*;

function drager(Event):void {
//trace(pixelHitTest(red, blue, undefined));
if (pixelHitTest(red, blue, undefined)) {
this.red.alpha = .5 ;
this.blue.alpha = .5;
} else {
this.red.alpha = 1 ;
this.blue.alpha = 1;
}
}

function dstart(event:MouseEvent) {
witch = event.currentTarget.name;
targ = getChildByName(witch);
targ.startDrag();
}
function dstop(event:MouseEvent) {
witch = event.currentTarget.name;
targ = getChildByName(witch);
targ.stopDrag();
}
red.addEventListener(MouseEvent.MOUSE_DOWN, dstart);
red.addEventListener(MouseEvent.MOUSE_UP, dstop);
blue.addEventListener(MouseEvent.MOUSE_DOWN, dstart);
blue.addEventListener(MouseEvent.MOUSE_UP, dstop);
stage.addEventListener(Event.ENTER_FRAME, drager);

Class MovieClip function pixelHitTest(mc1:MovieClip, mc2:MovieClip, threshold:Number):Boolean {
var threshold = threshold ? threshold : 1;

var thisBitmap:BitmapData = new BitmapData(mc1.width, mc1.height, true, 0);
thisBitmap.draw(mc1);

var mcBitmap:BitmapData = new BitmapData(mc2.width, mc2.height, true, 0);
mcBitmap.draw(mc2);

if (thisBitmap.hitTest(new Point(mc1.x, mc1.y), threshold, mcBitmap, new Point(mc2.x, mc2.y), threshold)) {
return true;
}
return false;
}much thanx to TheCanadian for the AS2 version, it is genius! :hr:

**btw, if you use this technique make sure the registration point is in the upper left corner, so the bit map lays directly over, other wise this hunk of beauty will not work right
Although this is one good implementation for simple quick checks with few objects on the screen, it will not be good enough when writing a game like asteroids where you have 15 objects or more on the screen. pixelHitTest is very slow when comparing a multitude of objects. Most likely this is due to the Bitmap draw function. Perhaps copypixel would improve the performance, but I'm not sure.

GrndMasterFlash
09-21-2007, 04:18 PM
yeah, if you have muliple objects or a couple very large objects the pixle hit test might not be the best tech to use, but if your doing say a maze based game, its the ****!!

:p: thanx again Canadian

icio
03-12-2008, 10:48 AM
Should this really be in the Actionscript 3 forum? I know a lot of the theory still applies, but the code isn't so applicable.

Edit: good posts btw, TC.

GrndMasterFlash
05-02-2008, 03:35 PM
Although this is one good implementation for simple quick checks with few objects on the screen, it will not be good enough when writing a game like asteroids where you have 15 objects or more on the screen. pixelHitTest is very slow when comparing a multitude of objects. Most likely this is due to the Bitmap draw function. Perhaps copypixel would improve the performance, but I'm not sure.


icio -- at the bottom of this page i have an example that is converted to AS3
http://www.kirupa.com/forum/showthread.php?t=229727&page=3

IDEA!!!!

if you wrap the pixel based hit test inside of a regular hit test object then it will save a lot of processing because the pixel hit test will only fire off f the two items are in each others bounds.
solid.:thumb2: