kirupaForum

kirupaForum (http://www.kirupa.com/forum/index.php)
-   Flash ActionScript (http://www.kirupa.com/forum/forumdisplay.php?f=9)
-   -   ActionScript 3.0 Tip of the Day (http://www.kirupa.com/forum/showthread.php?t=223798)

senocular 06-29-2006 06:52 PM

* represents an untyped value. It has more "compatibility" in the sense that it doesn't conflict with other data types. For example, if you return an variable typed as Object from a function and attempt to assign it to a varible typed as Array, you'll get an error. Returning a variable typed as * will not give you that error. Now, since Array is derived from object, you could get around that confliction using the as operator, but if you're possibly dealing with any kind of return type, * might be more convenient. The Proxy class, for example, uses * for values assigned to and retrieved from it.

* is also useful if you want your variables to be able to have a value of undefined. Objects cannot be undefined and are instead null. Using * you can have a variable with a value of undefined.

senocular 06-29-2006 06:55 PM

Quote:

Originally Posted by FatalDisruption
I don't think Strings or Numbers etc are objects.


They are Objects as the Number and String classes inherit from the Object class. All classes inherit from Object, and though there are primitive number and string values, in Flash they are still instances of their respective Number and String classes and therefore are seen also as Object instances.

senocular 06-29-2006 10:18 PM

Label Statements
 
ActionScript 3 introcuduces labels, new identifiers that can be associated with loop blocks. Why would you want to identify a loop block? Because you can use that identifier as a target for break and continue commands. Consider two loops where one is nested in the other. If at some point you want to exit both loops while in the nested loop, you can't. The break command only exits the current block. A common workaround is to use a flag variable to be able to check that, when in the first loop, if that should be exited as well. ex:
ActionScript Code:

var i:Number;
var j:Number;
var exit:Boolean = false;
for (i=0; i<10; i++) {
    for (j=0; j<10; j++) {
        if (i > 3 && j > 3) {
            exit = true;
            break;
        }
    }
    if (exit) {
        break;
    }
}


When i is greater than 3 and j is greater than 3, break is used to exit the current loop, but this only exits the j loop. To exit the i loop too, the exit variable was used with an if condition in the i loop to exit that one as well.

Labels let you identify and break from a specific loop (and consequently any nested loops within). The format for a label is label: statement
Ex:
ActionScript Code:

var i:Number;
var j:Number;
mainLoop: for (i=0; i<10; i++) {
    for (j=0; j<10; j++) {
        if (i > 3 && j > 3) {
            break mainLoop;
        }
    }
}


By giving the first loop a label of mainLoop, it can be broken out of easily within the nested loop using break mainLoop; This creates cleaner code and removes the necessity for the extra variable.

Chaoswarp 06-30-2006 12:37 PM

Yo senocular,

thanks for the tips, really helpful in getting into this stuff.

Couple questions,

First with the scopeing...

ActionScript Code:

traceThis.call(new Sprite()); // "Class Instance"
 



if this call keeps the class scope, why bother passing in another object? I kinda though the point of .call and .apply where to change scopes in functions? So i guess i am just wondering, why would u ever need to pass something into .call? wouldnt they all just be

ActionScript Code:

func.call(null, a,b,c);



Secondly the casting stuff
ActionScript Code:

var m:int = 8
var t:String = m as String
var o:String = String(m)

trace(t) //null?
trace(o) //8
 




how come i am getting null, maybe i am just not understanding this, but shouldnt those do the same thing?

Thanks again!

senocular 06-30-2006 02:09 PM

Quote:

Originally Posted by Chaoswarp
if this call keeps the class scope, why bother passing in another object? I kinda though the point of .call and .apply where to change scopes in functions? So i guess i am just wondering, why would u ever need to pass something into .call?


In the case of class methods, call is pretty useless. Apply is still helpful because it can let you use an array as arguments, but neither will let you change the scope of a function if it is defined as a method of a class. Class methods are bound to the scope of the class and cannot change so passing any scope object is redundant. Call and apply, however, will work on anonymous functions defined, for example, in a class method or the constructor.

Quote:

Originally Posted by Chaoswarp
Secondly the casting stuff... how come i am getting null, maybe i am just not understanding this, but shouldnt those do the same thing?


Casting with the as operator does not convert a datatype, it only changes Flash's understanding of what that variable's type is and only if compatible. By compatible I mean the original variable's class or any type within that class's hierarchy. So if an object is a Sprite and it was returned from a function as a Display Object (such as getChildAt would do), then you would most likely want to use as to reassociate it's type to be a Sprite. as would also work to change the value's type to any other object within the Sprite's heirarchy:
Sprite -DisplayObjectContainer -InteractiveObject -DisplayObject -EventDispatcher -Object
though you'd generally want to stick with the constructor class since it is more appropriate to your object.

Conversion functions are used to convert a value to another value of a different type. When converting a number to a string, you would use a conversion function (String()) because Numbers do not inherit from String. Because of that, as would fail.
Number -Object

Conversion functions are typically the class name called as a function, though simple casting will be used if there is no actual casting function associated with the class (with, for example, your custom classes; String, however, is a unique conversion function).

Chaoswarp 06-30-2006 02:24 PM

thanks that makes more sense. :)

NEW Question, and maybe I am just all together spacing out on this one.. but uhm where are the Tween Classes?

I attempted to do import mx.effects.Tween... but that doesnt work, nor do i think it should. I hunted through all the class files, and those still all look flash 8.

Can ya gimme a hint as to how to get going tweening things with AS3? I know i could make my own timers and do it myself, but I am looking to find out what happened to the Tween Class.

Also where does flash store the class files i am importing. for example where is flash.display.MovieClip. Does that class file exist on my computer? or is it in the flash player? can i use mx classes? if so where are those located for AS 3?

Any help would be appriciated, i am pretty much looking for a simple example like.. there is a circle movieclip made with a class, function called bounceIt. and in the bounceIt function it creates a new tween and bounces the ball up and down.

Sorry if these are all retarded, just trying to get a head start :)

senocular 06-30-2006 09:30 PM

All classes that you import from the flash packages (packages that begin with flash.) are internal to the Flash player. These are the fundamentals by which everything you program is based on. Other classes are external; these include the classes in the mx packages. You can find all of the source files for the mx classes in Flash's installation directory (or Flex's frameworks directory). The tweening classes are a part of these classes and they still exist for ActionScript 9.
mx.effects.Tween;

senocular 06-30-2006 10:10 PM

Detecting When the Mouse Leaves the Movie
 
One thing about previous versions of ActionScript was that you could never tell when the user no longer had his or her mouse over the Flash movie. This made it hard for people to know whether or not the user is still interacting with their movie or if they've given up and moved on to something more interesting. This was especially a problem for custom cursors where, if the user moved the cursor off the Flash movie, the custom cursor would still remain in the Flash movie not moving while the real cursor could be seen moving around every where else.

ActionScript 3 now allows you to detect when the mouse has left the flash movie using the stage's mouseLeave event. This event happens whenever the mouse exits the Flash movie. There is no mouseEnter event, but you can use mouseMove for that since mouseMove only occurs in Flash (for the stage, or really any, object) when the mouse is within the bounds of the movie.

Here's a simple example that uses a square as a custom cursor:
ActionScript Code:

package {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.ui.Mouse;
   
    public class Test extends Sprite {
       
        private var cursor:Sprite = new Sprite();
       
        public function Test() {
            cursor.graphics.beginFill(0xFF);
            cursor.graphics.drawRect(0, 0, 25, 25);
            addChild(cursor);
           
            stage.addEventListener(Event.MOUSE_LEAVE, cursorHide);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, cursorFollow);
            Mouse.hide();
        }
       
        public function cursorHide(evt:Event):void {
            cursor.visible = false;
        }
       
        public function cursorFollow(evt:MouseEvent):void {
            if (!cursor.visible) cursor.visible = true;
            cursor.x = stage.mouseX;
            cursor.y = stage.mouseY;
            evt.updateAfterEvent();
        }
    }
}


As your mouse leaves the movie, the cursor sprite is hidden. When the mouse is brought back in the movie, the mouseMove event fires and the cursor is made visible again.

Chaoswarp 07-01-2006 09:22 AM

Hmmmm well if the tween classes still exist, and should work the same. what am I doin wrong?

I got a movieclip mc on the timeline, ofcourse.

ActionScript Code:

import mx.effects.Tween
var t = new Tween(mc, "_rotation", Elastic.easeOut, 0,360, 3, true)



this gives me a compiler error
Quote:

ReferenceError: Error #1065: Variable Tween is not defined.
at Timeline0_63425fcc21fc6e4194dfe8880df15cd/::frame1()

So what is the proper way to get access to the Tween class?

senocular 07-01-2006 09:28 AM

for 1, _rotation is now rotation, but more importantly it looks like the AS3 preview didn't come with updated AS3 mx classes. You'll have to live without them (or use Flex or the Flex SDK)

icio 07-01-2006 09:48 AM

You also haven't included the package with `Elastic` in it.
I think that package is mx.transitions.easing.*

Not that it matters if the package wasn't included for AS3.

TheCanadian 07-01-2006 01:34 PM

Actually it's in mx.effects.easing

Chaoswarp 07-01-2006 02:23 PM

hehe yah knew about the other classes, figured it was pointless if i couldnt find this one. :)

thanks though, saves me some headache. Also is it just me, or does the code Check in flash IDE not work on AS 3 classes?

senocular - Can I get the updated Class files from the SDK or some from flex somewhere? like just copy them over my other ones? Or do i need to develop in flex until they release a new flash 9, if i wanna use those features?

thanks

senocular 07-01-2006 02:40 PM

You should be able to use the classes from the Flex SDK. Just download them somewhere on your computer and specify the location of the folder with the mx directory in your Flash preferences class path.

senocular 07-02-2006 06:54 AM

SimpleButton Instances
 
ActionScript 3 now supports a new class called SimpleButton (flash.display.SimpleButton). This class lets you create button symbols in ActionScript - something previously not possible older versions of ActionScript.
ActionScript Code:

var myButton:SimpleButton = new SimpleButton();


The SimpleButton class contains 4 properties that relate to the various states of a button; upState, overState, downState, and hitAreaState. Create display objects for these states and assign them to those properties to create a fully functional button symbol using ActionScript 3.
ActionScript Code:

myButton.upState = mySprite1;
myButton.overState = mySprite2;
myButton.downState = mySprite3;
myButton.hitAreaState = mySprite4;


senocular 07-02-2006 09:40 AM

Quote:

Originally Posted by senocular
You should be able to use the classes from the Flex SDK. Just download them somewhere on your computer and specify the location of the folder with the mx directory in your Flash preferences class path.


It looks like there's a lot of underlying complications in the mx framework provided with Flex that prevent this from being possible. So it looks like to use the Tween class in AS3, you'll have to rewrite it yourself ;)

Enemу 07-03-2006 10:43 AM

Quote:

Originally Posted by senocular
Here's a simple example that uses a square as a custom cursor:
Code:


...
public function cursorFollow(evt:MouseEvent):void {
            if (!cursor.visible) cursor.visible = true;
            cursor.x = stage.mouseX;
            cursor.y = stage.mouseY;
            evt.updateAfterEvent();
        }



Pls, comment on evt.updateAfterEvent(); , I know what updateAfterEvent() function does, but placing evt object before it confuses me.

It instructs player to refresh stage after event completes, right?

Why don't just write

Code:

updateAfterEvent();
?

I'll be thankfull if someone will point me on docs describing updateAfterEvent();

Krilnon 07-03-2006 11:06 AM

updateAfterEvent() is a method of the MouseEvent class, not a global function, so you need to call it from an instance of the MouseEvent class, in this case, 'evt'.

It is also a method of the KeyboardEvent and TimerEvent classes.

Here is the link to the documentation: http://livedocs.macromedia.com/labs/...teAfterEvent()

senocular 07-04-2006 08:00 AM

Commas in Shorthand Array Definitions
 
When defining arrays in ActionScript 3 using the shorthand array access operator (brackets), you can now have a trailing comma following the last element without causing an error (like in PHP). This makes working with multi-line array definitions a little less error-prone when rearranging elements. Ex:
ActionScript Code:

var myList:Array = [
    "The",
    "quick",
    "brown",
    "fox",
];


In ActionScript 1 and 2, the comma after "fox" would create an error. This is not the case in ActionScript 3.

Note: this does not work with Array() or new Array(), only [].

senocular 07-04-2006 08:14 AM

Package Block
 
Packages in ActionScript 3 are defined a little differently than they are in ActionScript 2. In ActionScript 3, the package path is no longer part of the class definition. Instead, it is part of a new block which contains your class, the package block defined with the package keyword. That gives you the following basic structure for AS3 files:
ActionScript Code:

package my.package.path {
    class MyClass {
    }
}


In AS2, it would look like the following:
ActionScript Code:

// ActionScript 2:
class my.package.path.MyClass {
}


In fact, in AS3, all class files require a package block, even if they are not in a package.
ActionScript Code:

package {
    class NotInAPackageClass {
    }
}


Each package block can define a class or a function that is associated with the file. The class or function within the block should be defined with the same name as the file (minus the .as extension).
ActionScript Code:

package com.kirupa.utils {
    function StripString(str:String):void {
        // ...
    }
}


The above would be saved as StripString.as in a com/kirupa/utils folder.

senocular 07-04-2006 08:59 AM

I'm going to skip ahead a little because the next two topics are related to the one I just posted

senocular 07-04-2006 09:01 AM

Same-file Helper Classes
 
Class definitions typically belong in their own .as file for either ActionScript 2 or 3. ActionScript 3, however, allows you to include additional helper classes within a single .as file in addition to your primary class.

Additional classes defined in an .as file are defined after a package block and are visible only to the primary class (or function) in the package block or other helper classes in the same file.
ActionScript Code:

package {
    class MyClass {
        function MyClass() {
            var helper:MyHelper = new MyHelper();
        }
    }
}
class MyHelper {
    function MyHelper() {
        var helper:HelpersHelper = new HelpersHelper();
    }
}
class HelpersHelper {
    function HelpersHelper () {
    }
}


Remember that only one class can be defined in a package block. Additional helper classes defined in the same file are not part of the package and can be used only with the packaged class in the same file.

senocular 07-04-2006 09:29 AM

Access Attributes
 
ActionScript 3 introduces 2 new access attributes for classes and members and refines the private attribute of ActionScript 2. In ActionScript 3 you have the following attributes for controlling access:
  • public
  • protected
  • private
  • internal (default)

public: The public attribute is the same as it was in ActionScript 2. Anything defined as public can be accessed anywhere by anything.

Constructors are always public.

Application classes need to be public.

protected: The protected attribute is a new attribute for ActionScript. It sets variables hidden from all access except from subclasses accessing the variables (inherited) from their own instance. Attempting to access a protected variable from another class instance in any circumstance will result in an error.

Classes and constructors cannot be defined as protected.

private: AS2 had the private attribute but it worked more like protected as subclasses had full access to private members. Now, with AS3, private is completely private and is only accessible from within the class in which it is defined. To all other classes, even subclasses, a private member doesn't even exist. This means that subclasses can even define new members of the same name and not have a conflict since the private member of the superclass is completely hidden. Private members are accessible directly off of class instances only when done so within the class definition.

Classes and constructors cannot be defined as private.

internal: Internal access is similar to public access but is restricted to package definitions. Classes in the same package have access to all internal members of any other class in that package. Classes in other packages do not have access.

Internal is the default for every class and class member except constructors which are always public.

Access control in helper classes are a little different. Since helper classes don't technically belong in packages, internal access for them is restricted to the classes in the current file. Helper classes themselves are inherently internal in this respect (and do not need to be explicitly provided any form of access attribute). Other access attributes within helper classes behave as expected. Note: your primary class cannot extend a helper class. Only helper classes can extend other helper classes and they need to be in the same file.



Something to keep in mind that access control for AS3 is also enforced not only during compile time, but also runtime. Hacks used in AS2 to get by accessing hidden methods will no longer work in AS3.

Example 1
ActionScript Code:

package {
   
    import flash.display.Sprite;
   
    // Application class needs to be public (internal by default)
    public class AccessControl extends Sprite {
       
        // constructors are always public
        function AccessControl() {
           
            // only classes in this file
            // can access helper classes
            var helper:Helper = new Helper();
           
            trace(helper.pubNum); // OK
            // trace(helper.protNum); // Error - cannot access protected
            // trace(helper.privNum); // Error - cannot access private
            trace(helper.interNum); // OK
        }
    }
}

// Helper class is implicitly internal
class Helper {
   
    // public access granted anywhere
    // variables are usually protected or
    // private with get/set used for public access
    public var pubNum:Number = 1;
   
    // protected access granted only for
    // subclasses in that class
    protected var protNum:Number = 2;
   
    // private access granted only in this class
    private var privNum:Number = 3;
   
    // internal access granted only in the same
    // package, but for helper classes, it means
    // only in the same file
    internal var interNum:Number = 4;
       
    // constructors are always public
    function Helper() {
    }
}

// SubHelper class is implicitly internal
// can extend other helper classes
class SubHelper extends Helper {
   
    // constructors are always public
    function SubHelper() {
        trace(pubNum); // OK
        trace(protNum); // OK - inherited
        // trace(privNum); // Error - cannot access private
        trace(interNum); // OK
    }
}




Example 2
ActionScript Code:

package {
   
    import flash.display.Sprite;
    import containers.*;
   
    // Application class needs to be public (internal by default)
    public class AccessControl extends Sprite {
       
        // constructors are always public
        function AccessControl() {
           
            // can access classes in other packages
            // only if public
            var bowl:Bowl = new Bowl(); // OK
            // var basket:Basket = new Basket(); // Error - cannot access internal
           
            trace(bowl.pubNum); // OK
            // trace(bowl.protNum); // Error - cannot access protected
            // trace(bowl.privNum); // Error - cannot access private
            // trace(bowl.interNum); // Error - cannot access internal
        }
    }
}

ActionScript Code:

package containers {

    // public class accessible anywhere
    public class Bowl {
       
        // public access granted anywhere
        public var pubNum:Number = 1;
       
        // protected access granted only for
        // subclasses in that class
        protected var protNum:Number = 2;
       
        // private access granted only in this class
        private var privNum:Number = 3;
       
        // internal access granted only in the same package
        internal var interNum:Number = 4;
           
        // constructors are always public
        function Bowl() {
           
            // can access inteneral classes if in same package
            var basket:Basket = new Basket();
           
            trace(basket.pubNum); // OK
            // trace(basket.protNum); // Error - cannot access protected
            // trace(basket.privNum); // Error - cannot access private
            trace(basket.interNum); // OK - same package
           
            // clone using public method
            var basketCopy:Basket = basket.clone();
        }
    }
}

ActionScript Code:

package containers {
   
    // interal only accessible
    // from other classes in package
    internal class Basket {
       
        // public access granted anywhere
        public var pubNum:Number = 1;
       
        // protected access granted only for
        // subclasses in that class
        protected var protNum:Number = 2;
       
        // private access granted only in this class
        private var privNum:Number = 3;
       
        // internal access granted only in the same package
        internal var interNum:Number = 4;
       
        // constructors are always public
        function Basket() {
        }
       
        // accessible anywhere as long as
        // referencing a Basket instance
        public function clone():Basket {
            var basket:Basket = new Basket();
            basket.pubNum = pubNum; // OK
            basket.protNum = protNum; // OK - same class
            basket.privNum = privNum; // OK - same class
            basket.interNum = interNum; // OK
            return basket;
        }
    }
}


devonair 07-06-2006 12:35 AM

Quote:

Originally Posted by senocular
You should be able to use the classes from the Flex SDK. Just download them somewhere on your computer and specify the location of the folder with the mx directory in your Flash preferences class path.


Just gave that a go... I had to comment out the includes and delete all references to the mx_internal namespace (Senocular probably knows a more elegant method of "fixing" these things, I'm more a slash and burn kinda guy) and came up with this:

http://www.onebyonedesign.com/flash/f9/tween/ (click on the circle)

the script:

ActionScript Code:

package com.onebyonedesign.tests {
 
 import mx.effects.*;
 import flash.display.*;
 import flash.events.*;
 import mx.effects.easing.*;
 
 public class TweenTest extends Sprite {
 
  private var _circle:Sprite;
 
  function TweenTest() {
   stage.frameRate = 31;
   init();
  }
 
  private function init():void {
   _circle = makeCircle();
   _circle.addEventListener(MouseEvent.MOUSE_DOWN, tweenMe);
  }
 
  private function makeCircle():Sprite {
   var s:Sprite = new Sprite();
   s.graphics.beginFill(0x660000);
   s.graphics.drawCircle(20, 20, 20);
   addChild(s);
   return s;
  }
 
  private function updateTween(vals:Array):void {
   _circle.x = vals[0];
   _circle.y = vals[1];
  }
 
  private function endTween(vals:Array):void {
   trace ("ending coordinates: " + vals);
  }
 
  private function tweenMe(e:Event):void {
   var myTween:Tween = new Tween(_circle, [_circle.x, _circle.y], [275, 200], 1000, 31);
   myTween.easingFunction = Elastic.easeOut;
   myTween.setTweenHandlers(updateTween, endTween);
  }
 }
}




the cool thing is that we can now add arrays of properties instead of doing one at a time.. Disco...

EDIT:
Thank you for these tips, Senocular.. Great thread and some great info...

Increu 07-06-2006 04:26 AM

I dontknow whats hapenning, i am trying this code
import flash.utils.Dictionary;

ActionScript Code:

var a:Object = new Object();
var b:Object = new Object();

var dict: Dictionary = new Dictionary();
dict[a] = 1; // dict[a] = 1;
dict[b] = 2; // dict[b] = 2;


for (var prop:String in dict) {
     trace(prop); // traces: [object Object], [object Object]
     trace(dict[prop]); // traces: 1, 2
}



and its not tracing 1,2, just undefined undefined
why why why???????

gpacioli 07-06-2006 05:35 AM

I continue to hear and read about Flex --- someone in a Davie, Florida user group said, "Flex is Adobe's Number one priority." Is this the place to ask,
"What is Flex --- and what good does it do? Does it compete with Flash? Do I start to learn Flex when I'm just learning Flash. Or what the ... ?

senocular 07-06-2006 06:29 AM

Quote:

Originally Posted by Increu
I dontknow whats hapenning, i am trying this code
import flash.utils.Dictionary;

var a:Object = new Object();
var b:Object = new Object();

var dict: Dictionary = new Dictionary();
dict[a] = 1; // dict[a] = 1;
dict[b] = 2; // dict[b] = 2;


for (var prop:String in dict) {
trace(prop); // traces: [object Object], [object Object]
trace(dict[prop]); // traces: 1, 2
}

and its not tracing 1,2, just undefined undefined
why why why???????


woops, that would be my fault - typo (actually force of habit) - but good that you pointed that out!

Why you are getting undefined in that trace is because I used String as the data type for the prop variable. Because of this, when iterating through the dict object, the values of prop in that loop are converted to their String equivalent instead of being the object themselves - exactly what you would use the dict object to avoid.

To fix this, you just have to make sure the prop variable isnt cast as a String. Because you actually don't know what prop could be, it should be cast as *. So the loop should look like:
ActionScript Code:

for (var prop:* in dict) {
     trace(prop); // traces: [object Object], [object Object]
     trace(dict[prop]); // traces: 1, 2
}


So now, prop remains whatever type it actually exists within the dict object (Object in this case) and the second trace resolves correctly as dict[a] and dict[b] instead of dict["[object Object]"]
;)

senocular 07-06-2006 06:32 AM

Quote:

Originally Posted by devonair
Just gave that a go... I had to comment out the includes and delete all references to the mx_internal namespace (Senocular probably knows a more elegant method of "fixing" these things, I'm more a slash and burn kinda guy) and came up with this:

http://www.onebyonedesign.com/flash/f9/tween/ (click on the circle)

very cool, devonair, thanks!

senocular 07-06-2006 06:46 AM

Quote:

Originally Posted by gpacioli
I continue to hear and read about Flex --- someone in a Davie, Florida user group said, "Flex is Adobe's Number one priority." Is this the place to ask,
"What is Flex --- and what good does it do? Does it compete with Flash? Do I start to learn Flex when I'm just learning Flash. Or what the ... ?


Well, I wouldn't be so bold as to say Flex is Adobe's Number one priority. But, the short answer is, Flex is a programmer-centric develop environment and server for the creation and deployment of Flash-based rich internet applications (RIAs). It has a strong focus on UI components and web services for the exchange and presentation of data.

Does it compete with Flash? No, not really. Though Flex Builder is an IDE for creating Flash applications, it doesn't have any of the drawing tools Flash has for content creation, nor does it have any timeline necessary for animations. Flex Builder is more of a workshop to bring existing content together to quickly and easily create moderately sized or large, screen or form based RIAs. You can kind of think of Flex as a programmers Flash where Flash is more for designers and animators (though, admittedly, Flash suffers a bit in terms of animation).

Flex presentation server is a different beast altogether and is more about server-side deployment (even further from Flash then Builder).

Also see:
http://www.gskinner.com/blog/archive..._from_a_f.html
Skinner's perspective on Flex (with a nice little analogy for Flex and Flash)

senocular 07-06-2006 10:42 AM

Abstract Classes
 
Unfortunately ActionScript 3 does not support abstract classes (classes that cannot be instantiated only extended). So you cannot create your own abstract classes in Flash. However, be aware that some of the internal classes in ActionScript are internally abstract. These classes include:As abstract classes, you cannot create instances of them directly using the new keyword.
ActionScript Code:

var myObj:InteractiveObject = new InteractiveObject(); // ERROR
 


However, in addition to that, in ActionScript, it also means that you cannot directly subclass these classes and create instances of those subclasses
ActionScript Code:

package {
    import flash.display.DisplayObject;
    public class MyDisplay extends DisplayObject{
        public function MyDisplay (){
            // ERROR
        }
    }
}


This has to do with the internal nature and how they are defined for the Player. If you attempt to subclass one of these classes and instantiate that subclass, you will get the same Argument Error that you would get if you tried to instantiate one of those classes directly.

Instead, what you would need to do is extend an internal class that already subclasses these classes. For example, if you wanted to extend DisplayObject, you could instead extend Shape, a light, internal class that is a subclass of DisplayObject.

Increu 07-06-2006 08:22 PM

Quote:

Originally Posted by senocular

Why you are getting undefined in that trace is because I used String as the data type for the prop variable. Because of this, when iterating through the dict object, the values of prop in that loop are converted to their String equivalent instead of being the object themselves - exactly what you would use the dict object to avoid.

To fix this, you just have to make sure the prop variable isnt cast as a String. Because you actually don't know what prop could be, it should be cast as *. So the loop should look like:





Ok..now i see it!!Thanks Sen!!
Just one more thing...i dont know if i understand it rigth, it is correct to say that the dictionary is for add properties to things that already exists
or
the dictionary is in fact, creating a new object inside the dictionary instance and the name of this object is a string and this string is the same name of any object i want...
Now i am confused...

senocular 07-06-2006 10:14 PM

all Dictionary objects are, are Object objects that dont convert their keys to strings.

senocular 07-07-2006 09:01 AM

The override Keyword
 
Overriding a method of a class means redefining a method for a class which would otherwise be inherited. The new method is then used in place of the inherited one (though the inherited method can still be invoked using super).

For ActionScript 3, when you override a method or property of a superclass, you need to use the override attribute with your new method. This specifies that the member you are creating is overriding that which would otherwise be inherited. If you do not use override with a method that already exists in a superclass, an error is thrown at compile time.

Ex:
ActionScript Code:

package {
    import flash.display.*;
    class MySprite extends Sprite {

        private var children:Array = new Array();

        public function MySprite() {
        }

        public override function addChild(child:DisplayObject):DisplayObject {
            children.push(child);
            super.addChild(child);
            return child;
        }
    }
}


Since addChild exists in the Sprite superclass, the override attribute is needed to successfully define the new addChild method which also adds the child passed to a children array.

Note that the method signature needs to match that of the overriden method

Override works with both normal class methods as well as getter/setter methods (properties), but it will not work with any of the following:
  • Variables
  • Constants
  • Static methods
  • Methods that are not inherited
  • Methods that implement an interface method
  • Inherited methods that are marked as final in the superclass

Also be aware that override is not needed for methods inherited directly from the Object class. These include:
  • hasOwnProperty
  • isPrototypeOf
  • propertyIsEnumerable
  • setPropertyIsEnumerable
  • toString
  • valueOf
These methods are added dynamically and are not part of the actual class definition. The override keyword is to be used only with methods which are part of a class's original definition.

However, if extending a class which uses a method above as part of its defnition, the override keyword is required. For example, if you are extending Object, you do not need to use the override keyword for the toString method. But, if you extend the Sprite class, you will need to override toString since the Sprite class has its own unique toString which is part of its class definition.

senocular 07-08-2006 07:01 PM

Using prototype
 
The prototype object in ActionScript is an object that exists among classes whose values are shared among all instances of the class to which it belongs. In ActionScript 1 and 2, it was used to control class inheritance. When a subclass instance references a variable, it first checks for that variable in the instance, followed by the class's prototype, followed by the superclass's prototype and so on through the prototype (inheritance) chain until there are no more classes.

In ActionScript 3, inheritance is primarily managed through Class inheritance and does not depend on the prototype object. However, the prototype object still exists and still provides much of the same functionality it did in AS1/AS2.

Each class and (non-method) function created in AS3 has a prototype object associated with it. For classes, prototype is read-only, meaning you cannot redefine it with a new value. However, it doesn't mean you cannot define new values within it (otherwise it would be pointless ;) ). Function prototypes are not read only. This allows you to create dynamic classes using the old style of class definitions through functions and set up inheritance through redefining the prototype.

Example:
ActionScript Code:

package {
   
    import flash.display.Sprite;
   
    public dynamic class MyClass extends Sprite {
       
        public function MyClass(){
           
            // prototype = new Object(); // ERROR, cannot change prototype of class
            prototype.newValue = 1; // OK, adding (or removing) prototyped values
           
            trace(this.newValue); // 1
            trace(prototype.toString); // function Function() {}
            trace(prototype.addChild); // undefined
            trace(addChild); // function Function() {}

            // dynamic ("old style") class definition
            var TempClass:Function = function():void {
                trace("Create TempClass");
            }
           
            TempClass.prototype = prototype; // OK, can set up inheritance
           
            var tempObject:* = new TempClass(); // "Create TempClass"
           
            trace(tempObject.newValue); // 1
        }
    }
}



Note that you should always prefix dynamic variable references with the this keyword. Also note that the Object class methods are dynamic and are defined in the prototype (which is why they are not overridden with the override keyword). You may also notice that the tempObject is typed as * instead of TempClass. This is because TempClass is only recognized as being a Function in AS3, not an actual class though it can still be used as one. Though a Class type exists, dynamic classes created like TempClass will always be recognized as Functions so creating instances with them always generates instances typed as a generic object.

senocular 07-11-2006 03:04 PM

Regular Expression (RegExp) Support
 
ActionScript 3 now supports regular expressions! The implementation is much like the one used in JavaScript. You can create new regexp patterns with the RegExp class constructor (top level) and a string or using the literal text format (defined like a string only replacing quotes with a forward slash (/). Ex:
ActionScript Code:

var reCon:RegExp = new RegExp("\\w+", "i");
var reLit:RegExp = /\w+/i;


RegExp methods include:
  • RegExp.exec()
  • RegExp.test()
String methods that work with regular expressions include:
  • String.match()
  • String.replace()
  • String.search()

senocular 07-11-2006 03:36 PM

Approach to Depth Sorting
 
Because of how the display list works with ActionScript 3, some methods of depth sorting will no longer work. One in particular is sorting objects on the screen based on their y location. In ActionScript 1 and 2, you could simply tell the clip to swapDepths at its _y location and be done with it. With AS3, this is no longer possible since no gaps can exist within the depths display list ("array").

An approach to obtaining the same functionality in AS3 is possible through an sorted array. Store the objects you want to arrange in an array. Then sort that array based on the y properties of the display objects within. All you have to do after that is place them in the display list in the order sorted. Ex:
ActionScript Code:

var sortedItems:Array = new Array(mc1, mc2, mc3);
function arrange():void {
    sortedItems.sortOn("y", Array.NUMERIC);
    var i:int = sortedItems.length;
    while(i--){
        if (getChildAt(i) != sortedItems[i]) {
            setChildIndex(sortedItems[i], i);
        }
    }
}


Here the sortedItems array stores the display objects being sorted (mc1 - mc3). In the arrange function, that array is sorted based on their y properties and then added to the display list at their locations within the array (if not already there).

Though this is not quite as easy as swaping to the depth of the _y property, it still proves a fairly efficient means of sorting objects on the screen based on their y location.

senocular 07-11-2006 09:39 PM

Deep Object Copies with ByteArray
 
Using the new ByteArray (flash.utils.ByteArray) class in ActionScript 3, you can now easily create deep object copies. By deep, I mean being able to create copies not of just a single object and all its references, but also all the objects it references. This means if you use this method to copy an array which references an object, that object will also be copied as part of the copy procedure. Such a copy (clone) method would look like the following:
ActionScript Code:

function clone(source:Object):* {
    var copier:ByteArray = new ByteArray();
    copier.writeObject(source);
    copier.position = 0;
    return(copier.readObject());
}


Note: you may need to import flash.utils.ByteArray;

To use this function simply say:
ActionScript Code:

newObjectCopy = clone(originalObject);


Though this will make a deep copy of your objects, be aware that it does not retain class association. So, if you try to copy a MyClass instance, the copy will no longer be recognized as being of MyClass. This method is best used with generic objects.

senocular 07-12-2006 07:38 AM

Similarly Named Instance and Static Properties
 
In ActionScript 1, you could have static properties of a class with the same name as instance properties. ActionScript 2 then came along and added a restriction preventing you from being able to do that. Now, with ActionScript 3, it is now again possible to have static properties with the same name as instance properties.
ActionScript Code:

package {
   
    import flash.display.Sprite;
   
    public class MyApp extends Sprite {
   
        private var variable:String;
        private static var variable:String;
           
        public function MyApp() {         
            this.variable = "foo";
            MyApp.variable = "bar";
           
            trace(this.variable); // "foo"
            trace(MyApp.variable); // "bar"
            trace(variable); // "foo"
        }
    }
}


senocular 07-13-2006 09:05 PM

EventDispatcher
 
ActionScript 3 uses the EventDispatcher (flash.events.EventDispatcher) class for all event handling. This class was available in ActionScript 2, but it existed as an external class in the mx framework. Now, it is built into the player (and in being so, improves performance).

Whenever you want to create an event handler to be called during a certain event, whether it be every frame (enterFrame event), or at the press of a button (mouseDown event), in AS 3, you will need to use EventDispatcher. This means there are no more onEnterFrame of onPress functions you can define that will automatically handle these events, nor are there any simple addListener methods for generalized event listening. EventDispatcher and addEventListener (and related methods) does it all.

Methods
  • addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
  • dispatchEvent(event:Event):Boolean
  • hasEventListener(type:String):Boolean
  • removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
  • willTrigger(type:String):Boolean

Note that addEventListener only takes functions as listeners, not objects. Also remember that class methods are bound to their instances so when used as listeners, 'this' in the event call still references the orginal class instance no matter what object dispatched the event.

Basic Example:
ActionScript Code:

package {
   
    import flash.display.Sprite;
    import flash.events.Event;
   
    public class MyDispatcher extends Sprite {
       
        public function MyDispatcher() {
            addEventListener("customEvent", handleEvent);
            dispatchEvent(new Event("customEvent"));
        }
       
        private function handleEvent(event:Event):void {
            trace(event.type); // "customEvent"
        }
    }
}



By extending the EventDispatcher class or any class that inherits from it like Sprite (all DisplayObjects are inherently EventDispatchers), your class gains access to the EventDispatcher methods. Then, other instances (or the class instance itself) can add methods to instances of that class using addEventListener and in turn they can call those events through dispatchEvent.

If there is some reason your class cannot inherit from the EventDispatcher class (for example, if its already inheriting from another class which does not inherit from EventDispatcher), then you can use the EventDispatcher constructor to intialize your class instance with the methods of EventDispatcher via aggregation (composition). Just make sure you implement the IEventDispatcher interface (flash.events.IEventDispatcher). Ex:
ActionScript Code:

package {
   
    import flash.display.Sprite;
    import flash.events.Event;
   
    public class MyDispatcher extends Sprite {
       
        public function MyDispatcher() {
            var dispatcher:CustomDispatcher = new CustomDispatche