View Full Version : ActionScript 3 Tip of the Day
senocular
June 19th, 2006, 09:02 PM
ActionScript 3 is the next step forward in Flash scripting and to help with the transition (for those of you deciding to make it), I thought I'd make a new Tip of the Day thread for ActionScript 3.0 to help people prepare (after 100 tips, they will no longer be provided daily).
Note: Many of these tips were created prior to the release of Flash and pertain to AS-only projects. Others were for use with the Alpha version of Flash (released prior to the full release of Flash). Most of these are noted as being for "Flash 9". Though much has changed in Flash CS3, most of those tips should still apply to it as well.
To code AS3, you'll need one of the following:
Flash Professional CS3 (http://www.adobe.com/products/flash)
Free Flex SDK (with AS3 compiler) (http://www.adobe.com/products/flex/sdk/)
Flex Builder 2 (http://www.adobe.com/products/flex/)
http://try.flex.org/ (online Flex MXML - with AS3 - compiler)
ActionScript 3 Tips and Tricks:
Latest Additions
(All categories are ordered from oldest (top) to newest (bottom))
Use IEventDispatcher to type EventDispatcher objects
What removeMovieClip() becomes in ActionScript 3
How stage, root, and MainTimeline Fit Together
Thinking "Outside Looking In" and not "Inside Looking Out"
General
Change the frame rate of your movie
Abstract Classes
Deep Object Copies with ByteArray
Determine Instance Class or Superclass
Multiple Arguments in trace()
Loading Text and XML with URLLoader
Get Sound Spectrum Information
Garbage Collection: Reference Counting & Mark and Sweep
Weak References
MXMLC: SWF Metadata Tag
TextField.appendText()
Access to stage and root
No More Color Class; Use ColorTransform
Array.indexOf (Array.lastIndexOf())
System.totalMemory
Closing Net Connections
AVM2 (AS3) to AVM1 (AS2/AS1) Communication via LocalConnection
Class member enumeration
Key.isDown in AS3
Scale and Alpha Ranges
Available ActionScript packages
Numeric Calculations: Number vs. int Speed
Getting Around globally accessible _root and _global
ActionScript 2 to ActionScript 3 Converter
Accessing FlashVars and HTML Parameters
ActionScript Speed Through Typing
LivePreview and the LivePreviewParent class
Flex Component Kit for Flash CS3
Loading URL encoded Variables
Interactive Masks
No _lockroot
Loading a Cross-domain Policy File
Loading External Classes with ApplicationDomain
Save Memory When Reusing Bitmaps With the Same BitmapData
ActionScript SWFs and Version Compatibility
Use IEventDispatcher to type EventDispatcher objects
How stage, root, and MainTimeline Fit Together
Thinking "Outside Looking In" and not "Inside Looking Out"
Language Elements/Behavior and Syntax
Class scope is now bound to class methods
New Variable Types
New Import Directive
Type Casting and the as Operator
Unique Class Variables
The delete Keyword and Class Members
Label Statements
Commas in Shorthand Array Definitions
Package Block
Same-file Helper Classes
Access Attributes
The override Keyword
Using prototype
Similarly Named Instance and Static Properties
super() Placement (Now Anywhere)
is Operator (vs instanceof)
Number() Conversion No Longer Interprets Octals
Changes in typeof
for..in and for each..in
Default Values for Function Parameters
Undetermined Number of Arguments With ...(rest)
arguments
Support for Namespaces
Namespaces: Name Qualifier Operator (::)
dynamic is Not Inherited
Prevent Overriding and Subclassing with final
in Operator
Constants
include Directive
Duplicate Variable Definitions
Namespaces: use namespace Directive
asfunction: Now event:
No more random(); Use Math.random()
Property Access and Downcasting (parent, root, etc.)
New Classes
The Dictionary Class
SimpleButton Instances
Regular Expression (RegExp) Support
EventDispatcher
URLRequest for URL Strings
XML vs. XMLDocument
Timer Class
ByteArray Class
Animator class in AS3 (Flash CS3)
Loading External SWFs with Loader (Preloading)
Loading External Classes with ApplicationDomain
Regular Expressions
Regular Expression (RegExp) Support
RegExp: Email Validation
Proxy Class
Proxy Class
Proxy: getProperty and setProperty
Proxy: callProperty
Proxy: Property Enumeration (nextName(), nextValue(), and nextNameIndex())
XML
Writing Inline XML
XML vs. XMLDocument
XML: @ Operator for Attributes
XML: XML and XMLList
XML: Children (.) and Decendants (..)
XML: Removing Nodes
Events
New MouseMove Behavior
Detecting When the Mouse Leaves the Movie
EventDispatcher
Events and Event Types
Calling Event Handlers without Events
Render Event
Event Propagation Support
rollOver and rollOut vs. mouseOver and mouseOut
Creating a mouseWithin Event
mouseEnabled and Event Blocking
mouseChildren with Event Propagation
Cleaning Up Event Listeners
Event Phases and Event Capturing
Determining Event Phase
Preventing Event Propagation
Global Events
Detecting a mouseUp Outside
Event Capturing and mouseEnabled
Overriding clone in Events
Use IEventDispatcher to type EventDispatcher objects
Errors and Error Handling
Runtime Errors; Error Class
Errors: try..catch..finally and Exception Handling
Errors: Asynchronous Exception Handling
Errors: Referencing properties from a null reference
Display Objects (MovieClips)
Graphics Object and the Drawing API
Display Objects
SimpleButton Instances
Approach to Depth Sorting
Determining Current Frame Label
getBounds() vs getRect()
duplicateMovieClip Replacement
Creating graphics Copies
DisplayObjectContainer contains()
Detecting Addition to or Removal from Stage
Adding an isPlaying Property to MovieClips
getObjectsUnderPoint
Loading External SWFs with Loader (Preloading)
Flash CS3: Frame Navigation and Child Access
Save Memory When Reusing Bitmaps With the Same BitmapData
What removeMovieClip() becomes in ActionScript 3
Flash Authoring
Flash 9: Timelines as Classes
Flash 9: BitmapData and Bitmaps from the Library
Flash 9: Display Object Variables and Instance Names
Flash 9: Document Class
Flash 9: Strict Mode
Flash 9: Timeline navigation and code execution
Flash 9: addFrameScript
Flash CS3: Setting MovieClip Base Classes
Flash CS3: Changing Function Behavior Across Frames
Flash CS3: New Library BitmapData Instances
Flash CS3: Frame Navigation and Child Access
Flash CS3: Automatic Timeline Declarations
Flash CS3: Component Classes
Additional Resources:
Beginners Guide to Getting Started with AS3 (Without Learning Flex) - uses SDK for MXMLC (http://www.senocular.com/flash/tutorials/as3withmxmlc/)
Getting Started with ActionScript 3.0 in Adobe Flash CS3 (http://www.senocular.com/flash/tutorials/as3withflashcs3/)
ActionScript 3 Language Reference (http://www.adobe.com/go/AS3LR/)
ActionScript 2 to ActionScript 3 Migration Guide (http://www.adobe.com/go/AS2toAS3/)
Adobe ActionScript Technology Center (http://www.adobe.com/devnet/actionscript/)
ActionScript 3 Overview (http://www.adobe.com/devnet/actionscript/articles/actionscript3_overview.html)
ActionScript 3 Learning Tips (http://www.adobe.com/devnet/actionscript/articles/actionscript_tips.html)
ActionScript Cheetsheets and References (http://actionscriptcheatsheet.com/blog/quick-referencecheatsheet-for-actionscript-20/)
Programming ActionScript 3 (PDF) (http://www.adobe.com/go/programmingAS3_pdf)
Flash Player 9 Security (PDF) (http://www.adobe.com/devnet/flashplayer/articles/flash_player_9_security.pdf)
ActionScript 3 and AVM 2.0 Performance Tuning (PDF) (http://www.onflex.org/ACDS/AS3TuningInsideAVM2JIT.pdf)
Samples:
Flex 2 AS3 Samples (http://www.adobe.com/go/as3examples)
Flash CS3 Samples (http://www.adobe.com/support/documentation/en/flash/samples/)
senocular
June 19th, 2006, 09:03 PM
Using ActionScript 3, you can dynamically change the frame rate of your movie using the Stage class.
The Stage class (flash.display.Stage (http://livedocs.macromedia.com/flex/2/langref/flash/display/Stage.html)) is the class assigned to the stage object which is accessible from your main movie sprite/movie clip (or others within the same security sandbox) using the stage property. The stage object has a frameRate property which can contain any value between 0.01 and 1000 and determines the frame rate at which the Flash player plays back your movie. Changing this value lets you change the frame rate at runtime.
// change frame rate to 12 fps:
stage.frameRate = 12;
mathew.er
June 19th, 2006, 10:08 PM
Nice to have an AS 3 thread. Maybe whole Flex/AS3 forum would be usefull as it seem to spred a lot.
To the stage thing... is "stage" and not "Stage" a typo or do you need to import and instance the Stage to change the framerate? Shouldnt flash.display.Stage.frameRate = 12 do the job then?
REEF·
June 19th, 2006, 10:18 PM
Changing FPS with AS? Isnt this a dream come true?
TheCanadian
June 19th, 2006, 10:26 PM
Nice to have an AS 3 thread. Maybe whole Flex/AS3 forum would be usefull as it seem to spred a lot.
To the stage thing... is "stage" and not "Stage" a typo or do you need to import and instance the Stage to change the framerate? Shouldnt flash.display.Stage.frameRate = 12 do the job then?
No, in AS3 it has changed - the Stage class is accessed through the stage property of a DisplayObject instance. However, they all reference the same thing I think.
ieatcotten
June 20th, 2006, 02:33 AM
However, they all reference the same thing I think.
Thats how I understand it.
Inheritance:Stage->DisplayObjectContainer-> InteractiveObject->DisplayObject ->EventDispatcher->Object
The Stage class represents the main drawing area. The Stage represents the entire area where Flash content is shown.
The Stage object is not globally accessible. You need to access it through the stage property of a DisplayObject instance.
http://livedocs.macromedia.com/labs/1/flex20beta3/langref/flash/display/Stage.html
mathew.er
June 20th, 2006, 03:27 AM
So that example at livedocs makes it pretty clear... "stage" is a global object allowing you to view and change its properties or to register events with it.
package {
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
public class StageExample extends Sprite {
public function StageExample() {
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.addEventListener(Event.ACTIVATE, activateHandler);
stage.addEventListener(Event.RESIZE, resizeHandler);
}
private function activateHandler(event:Event):void {
trace("activateHandler: " + event);
}
private function resizeHandler(event:Event):void {
trace("resizeHandler: " + event);
trace("stageWidth: " + stage.stageWidth + " stageHeight: " + stage.stageHeight);
}
}
}
@fabiopb: Why? Isnt this just a sign, that flash goes on pretty well? If your worried anout the Adobe Flash application itself, then you dont need to be... Flex is just for something else than Flash. It wont also disappear from the Internet as everybody has the plugin, people are used to use it and it still has great potential.
sandeep_cdac200
June 20th, 2006, 03:34 AM
one more step towards making AS to Java!! Great!!
senocular
June 20th, 2006, 10:55 AM
one more step towards making AS to Java!! Great!!
There are more steps to come that reinforce this idea ;)
senocular
June 20th, 2006, 11:12 AM
ActionScript 3 is entirely class-based. When you create classes, you create variables and functions (methods) which relate to and work with that class and instances of that class. Unlike ActionScript 2, methods in ActionScript 3 now retain their class scope when called, even if assigned to another object and called from that object, or if used with Function.call and Function.apply. Example:
package {
import flash.display.Sprite;
public class ClassScope extends Sprite {
public function ClassScope() {
traceThis(); // "Class Instance"
var obj:Object = new Object();
obj.traceThis = traceThis;
obj.traceThis(); // "Class Instance"
traceThis.call(new Sprite()); // "Class Instance"
}
public override function toString():String {
return "Class Instance";
}
public function traceThis():void {
trace(this);
}
}
}
sepu
June 20th, 2006, 01:09 PM
this topic at least should be a sticky !
thx Senocular.
senocular
June 20th, 2006, 01:28 PM
this topic at least should be a sticky !
thx Senocular.
Since it's every day it won't have problems staying near the top ;)
icio
June 20th, 2006, 01:42 PM
Nice one, sen :thumb:
REEF·
June 20th, 2006, 02:51 PM
A few questions...Whats AS 3.0 for? Is there a new flash coming out?
And PK...why do you believe flash will decline?
senocular
June 20th, 2006, 02:59 PM
A few questions...Whats AS 3.0 for? Is there a new flash coming out?
ActionScript 3 is the next release of ActionScript that will be supported in Flash Player 9. Flex 2 applications are built using ActionScript 3 and the next version of Flash (code named BLAZE) will support it when it's released some time after Flex. Unlike ActionScript 2, ActionScript 3 uses an entirely new virtual machine providing it with new robust features and increased performance.
More details on available and upcoming products can be found on http://www.adobe.com/ and http://labs.adobe.com/ (where both the Flex 2 beta and Flash Player 9 beta are currently available for download)
andrewfitz
June 21st, 2006, 02:34 AM
Hey sen, how much work do you think it'll take to convert an AS2 class to a fully optimized AS3? I'm assuming it would take just a few changes to make it work, but an entire rewrite to take advantage of all AS3+F9 features. Have you tried converting any of your classes to 3 yet?
Working with a project that has a few thousand lines of code, it seems like a daunting task. Because there's things like attachMovie that aren't even there anymore, so it's not like easy AS1 to AS2, correct?
senocular
June 21st, 2006, 01:36 PM
Hey sen, how much work do you think it'll take to convert an AS2 class to a fully optimized AS3? I'm assuming it would take just a few changes to make it work, but an entire rewrite to take advantage of all AS3+F9 features. Have you tried converting any of your classes to 3 yet?
Working with a project that has a few thousand lines of code, it seems like a daunting task. Because there's things like attachMovie that aren't even there anymore, so it's not like easy AS1 to AS2, correct?
It depends. Some conversions aren't that bad. However, with the new scoping behaviors of AS3, there can be some drastic changes. Also, another thing to consider is default values for some variable types. Declared but undefined Number variable instances, for example, are no longer undefined but NaN and to check to see if they have been defined you should use isNaN(myNum) and not myNum == undefined.
There are also a lot of little things that have to be modified, such as adding the package {} block, using the override keyword, and changing all instances of Void to void (and not using void if methods have no arguments).
I've only converted my Path class at this point, and I think that was only (if) a couple hundred lines. It wasn't too bad at all, but I know there are some other classes I think I would fear to convert.
senocular
June 21st, 2006, 01:50 PM
Like ActionScript 1 and 2, ActionScript 3 also has a drawing API that allows you to draw vector lines and shapes dynamically in movie clips and sprites. With ActionScript 3, however, the drawing API is now used off of an object within display objects (movie clips, sprites, etc.) defined as graphics (flash.display.Graphics (http://livedocs.macromedia.com/flex/2/langref/flash/display/Graphics.html)). This graphics property represents the dynamic drawing layer where drawing API drawings exist. Like before, it is placed below all children of the target object. Also, in ActionScript 3, you have new methods that help you more easily create rectangles, circles, and even rounded rectangles. These include:
drawCircle(x:Number, y:Number, radius:Number):void
drawEllipse(x:Number, y:Number, width:Number, height:Number):void
drawRect(x:Number, y:Number, width:Number, height:Number):void
drawRoundRect(x:Number, y:Number, width:Number, height:Number, ellipseWidth:Number, ellipseHeight:Number):void
Example:
// draw a blue rounded rectangle:
var square:Sprite = new Sprite();
square.graphics.beginFill(0xFF);
square.graphics.drawRoundRect(0, 0, 100, 50, 10, 10);
square.graphics.endFill();
addChild(square);
senocular
June 22nd, 2006, 10:19 AM
ActionScript 3 supports a wide range of variable types including some which were not present in previous versions of ActionScript. Basic types for AS3 include:
Primitive:
Boolean
int
null
Number
String
uint
undefined
Complex:
Object
Array
Date
Error
Function
RegExp
XML
XMLList
Additional types also exist that relate to their classes; ex: Matrix (flash.geom.Matrix), Shape (flash.display.Shape), URLRequest (flash.net.URLRequest), etc.
Things to note:
The special Void type has changed in AS3 to be lowercase (void not Void)
There's a new * type that is used to represent any data type. This should be used instead of ommitting typing information for your variables.
var anything:*;
The XML type is not the same as the XML type in ActionScript 1 and 2. The old XML type (object) is now defined as XMLObject. XML now references the new E4X-based XML object.
int and uint are new primitive number data types for integer (numbers without decimal values) and unsigned integer (numbers without decimal values that also cannot be negative). These can be useful for values which are not supposed to have decimal values such as loop iterators. The int data type will provide a small perfomance boost when used over Number in most cases, but uint should only be used when necessary such as with color values.
senocular
June 23rd, 2006, 10:24 AM
ActionScript 3 now has a new collection of "display objects" which includes those objects that can be seen on the screen or added to the "display list." This goes beyond the simple movie clip, button, and text field objects that ActionScript had access to before. AS3 display objects include
AVM1Movie
Bitmap
Loader
MorphShape*
MovieClip
Shape
SimpleButton
Sprite
StaticText*
TextField
Video
*Are for referencing pre-existing objects existing on the timeline; you cannot create them via AS.
AVM1Movie represents a movie created with ActionScript 1 or 2. Those movies use ActionScript Virtual Maching 1 where AS3 movies use AVM2. AVM2 movies can play AVM1 movies, but cannot interact with them (their ActionScript) using AS3.
Bitmaps are bitmap objects. You can specify their imagery with BitmapData objects or they can be bitmaps from files.
Loader objects are display objects that load external content into them. This content can be images or other SWF movies.
MorphShapes are shape tweens created in the timeline. Though you cannot create them in ActionScript, you can access those that exist on the timeline already using ActionScript and they are of the type MorphShape.
MovieClips are the movie clips you know and love.
Shapes are stripped down movie clips that essentially only contain a graphics object for drawing in with the vector drawing API. Using Shapes instead of MovieClips or Sprites can help conserve memory
Sprite objects are essentially movie clips without timelines. This is your most common display object in AS3 and usually the one extended when creating your own display object subclasses.
StaticText, like MorphShapes, cannot be created with ActionScript instead referening static text objects that are pre-existing on the Flash timeline.
TextField objects include dynamic and input text.
Video objects represent Flash video.
senocular
June 24th, 2006, 12:07 PM
The import directive in ActionScript 3 is a little different than import in ActionScript 2. In AS2, import was used solely as a name shortener for classes defined in packages; it was not required to use a class. Instead of using import, you could just have used the class's full name. ex:
// ActionScript 2
var myPoint:flash.geom.Point = new flash.geom.Point(0,0);
In ActionScript 3, the import directive is required to access classes in their packages, even if you reference the class using its full name. You can still use the full name (or just the imported class name), but the import is required
// ActionScript 3
import flash.geom.Point;
var myPoint:flash.geom.Point = new flash.geom.Point(0,0);
As with AS2, you can also use the wildcard character (*) in AS3 to import all classes within a package.
import flash.geom.*;
Krilnon
June 24th, 2006, 12:36 PM
How did I not see this thread until today? :-/
Why are the rules /suggestions for using uint so strict? Is it not as fast as an int variable? In other words, I see no reason not to use uint for every value that I know will be a positive integer, why isn't this the case?
When using addChild and getChild-type methods, you are allowed to add objects that are subclasses of DisplayObject, but the 'get' functions all return DisplayObjects. I'm assuming that this is done so the method will have only one return type, but it is kind of inconvenient to have to construct subclass-typed objects out of that returned value, like "Bitmap(imageHolder.getChildAt(0))". Is there a better way of handling returns that return value types that are less specific than you would like?
How do you make functions callable by events and non-events with more than just an event as an argument? In your CoilGallery source, I saw that you had something like "event:Event = null", which I'm assuming makes the argument optional. I've been running into trouble using functions for multiple purposes that need specific argument types. If I, for example, had a function that for some reason needed to have the x property of a DisplayObject. If I wanted to be able to call this function with an event and by itself, would it be best to define the function so it can be run by itself and then have a separate function that serves as an event handler to get the desired property using info from the event.target and then passes that into the function with the x argument?
senocular
June 24th, 2006, 12:54 PM
1. Yes, uints are pretty slow. I don't know why, but they are. Typically they're just used for numbers that require values that high (like colors with alpha information). Using int for integers is generally a little faster than Number (but not much if at all in all situations). All in all, using only Number wouldn't kill you. They might get around to optimizing int (and maybe uint?) more in the future, though. So its good practice to use them where applicable. For more info see:
http://kuwamoto.org/2006/06/15/avoid-ints-in-actionscript/
2. The getChild methods all return DisplayObject types because methods are only allowed to have one type associated with their return value. By using DisplayObject, its using a type that all objects must be or inherit from to even be added in the first place. So if you add something to the display list, you know it's at least going to be a DisplayObject and having the return value typed as that means it works for whatever is returned.
Note: You can also use the 'as' operator to change the type of variables (and I think this is preferred over ClassCast() conversions).
var myBmp:Bitmap = imageHolder.getChildAt(0) as Bitmap;
3. In using event:Event = null as the parameter for a method, I was able to use it both as an event (where the event object is passed) and as a normal method call anywhere else in my code using methodName(); since having a default value for parameters makes them optional. Required parameters have no default value. You can have both as well, but optional have to come after all required.
If you want to have a method that acts as an even handler and a normal method, if its "normal" use doesn't use an event parameter as the first parameter, then you'll most likely just have to use a separate method for the event handler that calls your normal event.
There is also a new ...(rest) parameter that lets you specify an undetermined number of untyped arguments. Arguments that map themselves to the ...(rest) parameter are assigned to an array with the name of (rest) which you can name anything you want. I'm pretty sure I used this for the trace method in the Output class (com.senocular.utils.Output). That should use it by itself as one parameter, but you can also have required parameters come before it. You can find more information in the docs under
Language Elements > Statements, Keywords & Directives > [Definition keyword summary] ...(rest)
Krilnon
June 24th, 2006, 01:11 PM
Thanks senocular! :beam:
Note: You can also use the 'as' operator to change the type of variables (and I think this is preferred over ClassCast() conversions).
That's just what I was looking for. I had seen the 'as' operator before (in your CoilGallery, I think), but it makes much more sense when applied to a situation that I'm familiar with.
senocular
June 26th, 2006, 12:12 PM
ActionScript lets you change the assigned type of an object to other compatible types when needed. This is called casting. Both ActionScript 2 and 3 support casting using type(object) syntax. For example, if your custom class object was assigned to a variable typed as an object, you can reassign typing for that object by casting it to have a type of your custom class thereby letting Flash know what methods and properties exactly are available to that object
var obj:Object = getMyCustomObject();
vay customObj:MyClass = MyClass(obj);
ActionScript 3 introduces a new operator for casting, the as operator. The as operator replaces casting using type(object) in ActionScript 2 with a syntax of object as type.
var obj:Object = getMyCustomObject();
vay customObj:MyClass = obj as MyClass;
The as operator works much like casting in ActionScript 2. If the conversion can't be made, the result of the cast is null. Otherwise, the object being cast is returned and assigned a type of the type used.
ActionScript 3 still supports type(object) casting, but the behavior is a little different now. Instead of returning null for failed casting, a TypeError is thrown. Failure occurs when you try to cast an object into an incompatible type such as trying to cast one object into a type it is not associated with or inherits from.
Note: ActionScript also has global conversion functions in that work in the style of Class(object) which have precedence over type(object) casting. These include String(), Number(), and Array(), etc. These don't cast so much as actually convert one object into another (where applicable). Because these have precedence over type(object) casting, its preferred that the as operator be used when casting objects to different data types.
senocular
June 26th, 2006, 12:23 PM
In ActionScript 2, variables defined within a class's body were defined in the class's prototype object. This was an efficient means to handle variable definitions but it also meant that complex data types (such as Arrays) had a tendency to be "shared" among instances if not explicitly defined for instances within the class constructor. This is no longer a problem with ActionScript 3. Class variables defined in the class body are now unique to each class instance so this problem no longer occurs.
class myClass{
private var list:Array = [1,2,3]; // bad for AS2, ok for AS3
public function myClass(){
// list should be defined here for AS2
}
}
senocular
June 27th, 2006, 03:09 PM
The mouseMove event has changed a little in ActionScript 3. Before, mouseMove events were global meaning that no matter where the mouse was in the Flash movie, if it moved, any listener to Mouse or any MovieClip (which automatically receive mouse events without being made listeners of Mouse) would recognise that it moved and recieve the event.
With ActionScript 3, the Mouse object is no longer used for dispatching mouse events. For mouseMove events, you would listen to InteractiveObject instances such as Sprites, MovieClips, and the Stage. So instead of adding listeners to Mouse, you would use some InteractiveObject. For each InteractiveObject instance, though, the mouseMove event is only called when the mouse moves from one location on that object to another location on that object. For a mouseMove event anywhere in the movie, you would want to add your listener(s) to the Stage instance.
Given this behavior, when using mouseMove to drag objects, you would always want to use Stage as your dispatcher in the case that when you move the mouse, the location it moves is off the object your dragging. If that were to happen, the mouseMove event wouldnt not fire and your drag would stop.
stage.addEventListener(MouseEvent.MOUSE_MOVE, dragMyObject);
Krilnon
June 27th, 2006, 05:59 PM
With ActionScript 3, the Mouse object no longer exists
Doesn't it exist, just not in the way it did before? For example,
trace(typeof(Mouse)); That traces "object", so Mouse still exists as an object, right? It just has two static methods and everything that it inherits.
As far as dragging goes, has startDrag (and stopDrag) been improved at all? I always avoided it in Flash <9, but I tried to use it again for the AS Battle and ended up falling back on hand coding it with if constraints. The built-in function seems to be more trouble than it's worth, so is there any case where it would be better to use startDrag? (Perhaps when I have a predefined rectangle that might be changed dynamically?)
senocular
June 27th, 2006, 06:13 PM
Yeah, I meant to say its no longer an object that you add listeners too - lemme edit that ;) Mouse does exist, but for a different reason - mainly just to control whether or not the mouse cursor is seen (I think that actually may be it too)
AS for startDrag, I dont think it has changed much.
JoshuaJonah
June 27th, 2006, 06:19 PM
ActionScript 1.0 Tip of the day: Upgrade
:D
Krilnon
June 28th, 2006, 11:19 AM
I have a suggestion for today's hint: Describe how to use AS 3.0 classes with the Flash 9 preview. I'm trying to get my gallery to work with it, though I haven't had any luck so far. (I've only had it for 10 minutes, though)
var myGallery:KrilGallery = new KrilGallery();
Generates:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at KrilGallery$iinit()
at Timeline0_6f3f7df53146e840b3f92ad2f63d7757/::frame1()
It does run the first line of the constructor function, though, as it traces "KrilGallery". The next line tries to access the stage, so perhaps that is part of the issue.
senocular
June 28th, 2006, 11:34 AM
Krilnon, all you do is type your class in the document class field in the property inspector then publish.
Your application class is setup to represent the actual movie being published (the document class). Just making a new instance of it on the timeline only creates an instance in a default document class and your movie won't function as expected. :)
Krilnon
June 28th, 2006, 11:57 AM
Oh, that makes things much more simple. Thanks :)
senocular
June 28th, 2006, 12:11 PM
The delete keyword in Flash is used to remove variable definitions. It doesn't delete objects from memory (this happens behind the scenes using something called the "Garbage Collector"), it just takes a variable you've created and gets rid of it so that it is no longer accessible and is no longer present through iteration (for..in loops, etc.).
Internally, the Garbage Collector, or GC for short, knows when to physicially delete objects in memory when they no longer have any variables that reference them. So, for example, if you have two variables A and B and they both reference ObjectX, deleting variable A will not cause ObjectX to be removed from memory by the GC because variable B still references it. However, if you delete both variables A and B, there will be no more references to ObjectX and the GC will recognize that it needs to be removed from memory
var a:Object = new Object();
var b:Object = a; // reference same new Object();
delete a;
trace(b); // [object Object] - still exists in memory
delete b;
// GC will mark object for deletion from memory
This works practically the same way for Flash 8 and Flash 9 (ActionScript 1, 2, and 3), though some changes were made in 8 to improve the GC. (Note: GC deletion from memory is not immediate.)
Though the GC has not really changed much with ActionScript 3 and the new virtual machine that runs it, what has changed is the behavior of the delete keyword. Now, the delete keyword only works for dynamic properties of a class instance and not declared class memebers (variables or methods). With ActionScript 1 and 2, delete could be used for anything. ActionScript 3 only lets you delete dynamic variables and locks those which are not.
// ActionScript 2
class DeleteVarClass {
public var myVar:Number;
function DeleteVarClass() {
myVar = 1;
trace(myVar); // 1
delete myVar;
trace(myVar); // undefined
}
}
// ActionScript 3
package {
public class DeleteVarClass {
public var myVar:Number;
public function DeleteVarClass() {
myVar = 1;
trace(myVar); // 1
delete myVar;
trace(myVar); // 1
}
}
}
Because myVar in the above example was declared as part of the class definition, it cannot be deleted using delete in ActionScript 3.
Since you cannot delete class members in ActionScript 3, if you want to cause a variable to no longer reference an object or value in memory you should set your variable's value to null instead of deleting it.
myVar = null;
If all variable references to an object are null, the GC will mark it for deletion and it will eventually be cleared from memory.
lunatic
June 28th, 2006, 12:19 PM
*sigh* I wish I had your brain. :(
senocular
June 29th, 2006, 03:54 PM
The Dictionary class (flash.utils.Dictionary (http://livedocs.macromedia.com/flex/2/langref/flash/utils/Dictionary.html)) in ActionScript 3 is a new addition to ActionScript. Dictionary objects exactly like generic Object objects aside from one thing: Dictionary objects can use any value as a property name or key as opposed to a string.
Generic objects in ActionScript use string keys (names) for property definitions. If a non-string value is used as a key, the key interpretation is the string representation of that value. Example:
var obj:Object = new Object();
obj["name"] = 1; // string key "name"
obj[1] = 2; // key 1 (converted to "1")
obj[new Object()] = 3; // key new Object() converted to "[object Object]"
for (var prop:String in obj) {
trace(prop); // traces: [object Object], 1, name
trace(obj[prop]); // traces: 3, 2, 1
}
If you attempt to use different objects as keys in generic objects, what you'll get iare string conversions that match each other. That means that though you have used separate objects as keys, to the object container, its the same key and they will reference the same value.
var a:Object = new Object();
var b:Object = new Object();
var obj:Object = new Object();
obj[a] = 1; // obj["[object Object]"] = 1;
obj[b] = 2; // obj["[object Object]"] = 2;
for (var prop:String in obj) {
trace(prop); // traces: [object Object]
trace(obj[prop]); // traces: 2
}
The Dictionary class is not restricted to this limitation. You can have any value as a key and that value will fully represent that key as opposed to the object using its string representation. So in the above example, if a Dictionary instance is used, you would have two separate keys, one for each object.
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:* in dict) {
trace(prop); // traces: [object Object], [object Object]
trace(dict[prop]); // traces: 1, 2
}
Though you still get [object Object] in the trace, this is a result of the string conversion in the trace command; it is a unique object key in the Dictionary instance.
Note that prop here is typed as *. This is important as the keys in the dict object can be of any type. If you used String for prop's type, it would cast the a and b objects as Strings when finding them in the loop making prop "[object Object]" instead of actual references to a and b which they would need to be to correctly obtain the values 1 and 2 through dict. For generic objects, regardless of the type used for prop, you will always get a String.
andrewfitz
June 29th, 2006, 08:13 PM
What is the point, can't you just use a regular object? I guess I'm confused as to what it would be used for.
senocular
June 29th, 2006, 08:50 PM
What is the point, can't you just use a regular object? I guess I'm confused as to what it would be used for.
You can look at the examples and see where they are different. Objects use string keys where Dictionaries use the objects themselves. This lets you essentially use objects as variable names which can be very useful in the right circumstances.
For example, consider having a bunch of "male" objects and a bunch of "female" objects, and eventually you have your objects get hitched and all get married. However, male and female objects dont have any internal property that lets you specify who their partner is, so instead you set up a reference table to let you access any female from a male or male from a female so reference[male] = female. Given any male, access it from the reference object and it returns the respective female and vise versa. Here's the thing, using normal objects, this won't work because any male or female you use as a key will be resolved as "[object Object]" and after assigning them all to your reference object, it only ends up with one value, "[object Object]" which has the value of the last male of female you assigned to it. Dictionaries, on the other hand, don't make that string conversion and would work for this.
I even used a dictionary in my coil gallery to allow me to reference sprites added to the coil display. Sprites added using addItem were used with another object with coil-specific properties which was used in how the sprite was displayed in the coil display itself. Using a dictionary object, I could quickly access that wrapper by using a reference to the sprite without the need to modify anything within the sprite itself.
mathew.er
June 29th, 2006, 10:19 PM
Regarding a post you wrote earlier, I am a little curious about one thing... Why would anyone need * as a type? Isnt
var anything:*;the same as
var anything:Object;as everything comes from the Object class... Or are primitive data types not really objects?
andrewfitz
June 29th, 2006, 10:43 PM
I don't think Strings or Numbers etc are objects.
senocular
June 29th, 2006, 10: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
June 29th, 2006, 10:55 PM
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
June 30th, 2006, 02:18 AM
ActionScript 3 introcuduces labels (http://livedocs.macromedia.com/flex/2/langref/statements.html#label), 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:
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:
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
June 30th, 2006, 04:37 PM
Yo senocular,
thanks for the tips, really helpful in getting into this stuff.
Couple questions,
First with the scopeing...
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
func.call(null, a,b,c);
Secondly the casting stuff
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
June 30th, 2006, 06:09 PM
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.
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
June 30th, 2006, 06: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
July 1st, 2006, 01:30 AM
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
July 1st, 2006, 02:10 AM
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:
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
July 1st, 2006, 01:22 PM
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.
import mx.effects.Tween
var t = new Tween(mc, "_rotation", Elastic.easeOut, 0,360, 3, true)
this gives me a compiler error
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
July 1st, 2006, 01:28 PM
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
July 1st, 2006, 01:48 PM
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
July 1st, 2006, 05:34 PM
Actually it's in mx.effects.easing
Chaoswarp
July 1st, 2006, 06: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
July 1st, 2006, 06: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
July 2nd, 2006, 10:54 AM
ActionScript 3 now supports a new class called SimpleButton (flash.display.SimpleButton (http://livedocs.macromedia.com/flex/2/langref/flash/display/SimpleButton.html)). This class lets you create button symbols in ActionScript - something previously not possible older versions of ActionScript.
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.
myButton.upState = mySprite1;
myButton.overState = mySprite2;
myButton.downState = mySprite3;
myButton.hitAreaState = mySprite4;
senocular
July 2nd, 2006, 01: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.
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у
July 3rd, 2006, 02:43 PM
Here's a simple example that uses a square as a custom cursor:
...
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
updateAfterEvent(); ?
I'll be thankfull if someone will point me on docs describing updateAfterEvent();
Krilnon
July 3rd, 2006, 03:06 PM
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/1/flex20beta3/langref/flash/events/MouseEvent.html#updateAfterEvent()
senocular
July 4th, 2006, 12:00 PM
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:
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
July 4th, 2006, 12:14 PM
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:
package my.package.path {
class MyClass {
}
}
In AS2, it would look like the following:
// 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.
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).
package com.kirupa.utils {
function StripString(str:String):void {
// ...
}
}
The above would be saved as StripString.as in a com/kirupa/utils folder.
senocular
July 4th, 2006, 12:59 PM
I'm going to skip ahead a little because the next two topics are related to the one I just posted
senocular
July 4th, 2006, 01:01 PM
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.
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
July 4th, 2006, 01:29 PM
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
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
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
}
}
}
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();
}
}
}
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
July 6th, 2006, 04:35 AM
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:
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
July 6th, 2006, 08:26 AM
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???????
gpacioli
July 6th, 2006, 09: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
July 6th, 2006, 10:29 AM
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:
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
July 6th, 2006, 10:32 AM
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
July 6th, 2006, 10:46 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 ... ?
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/archives/2006/07/flex_2_from_a_f.html
Skinner's perspective on Flex (with a nice little analogy for Flex and Flash)
senocular
July 6th, 2006, 02:42 PM
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:
DisplayObject (http://livedocs.macromedia.com/flex/2/langref/flash/display/DisplayObject.html)
InteractiveObject (http://livedocs.macromedia.com/flex/2/langref/flash/display/InteractiveObject.html)
DisplayObjectContainer (http://livedocs.macromedia.com/flex/2/langref/flash/display/DisplayObjectContainer.html)
Graphics (http://livedocs.macromedia.com/flex/2/langref/flash/display/Graphics.html)
As abstract classes, you cannot create instances of them directly using the new keyword.
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
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
July 7th, 2006, 12:22 AM
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
July 7th, 2006, 02:14 AM
all Dictionary objects are, are Object objects that dont convert their keys to strings.
senocular
July 7th, 2006, 01:01 PM
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:
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
July 8th, 2006, 11:01 PM
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:
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
July 11th, 2006, 07:04 PM
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 (http://livedocs.macromedia.com/flex/2/langref/RegExp.html)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:
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
July 11th, 2006, 07:36 PM
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:
var sortedItems:Array = new Array(mc1, mc2, mc3);
function arrange():void {
sortedItems.sortOn("y", Array.NUMERIC);
var i:int = sortedItems.length;
while(i--){
if (getChildIndex(sortedItems[i]) != 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
July 12th, 2006, 01:39 AM
Using the new ByteArray (flash.utils.ByteArray (http://livedocs.macromedia.com/flex/2/langref/flash/utils/ByteArray.html)) 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:
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:
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
July 12th, 2006, 11:38 AM
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.
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
July 14th, 2006, 01:05 AM
ActionScript 3 uses the EventDispatcher (flash.events.EventDispatcher (http://livedocs.macromedia.com/flex/2/langref/flash/events/EventDispatcher.html)) 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:
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:
package {
import flash.display.Sprite;
import flash.events.Event;
public class MyDispatcher extends Sprite {
public function MyDispatcher() {
var dispatcher:CustomDispatcher = new CustomDispatcher();
dispatcher.addEventListener("customEvent", handleEvent);
dispatcher.dispatchEvent(new Event("customEvent"));
}
private function handleEvent(event:Event):void {
trace(event.type); // "customEvent"
}
}
}
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
class CustomDispatcher implements IEventDispatcher {
private var eventDispatcher:EventDispatcher;
public function CustomDispatcher() {
eventDispatcher = new EventDispatcher(this);
}
public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {
eventDispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
public function dispatchEvent(event:Event):Boolean {
return eventDispatcher.dispatchEvent(event);
}
public function hasEventListener(type:String):Boolean {
return eventDispatcher.hasEventListener(type);
}
public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void {
eventDispatcher.removeEventListener(type, listener, useCapture);
}
public function willTrigger(type:String):Boolean {
return eventDispatcher.willTrigger(type);
}
}
The CustomDispatcher helper class above doesn't inherit from EventDispatcher but uses aggregation to obtain EventDispatcher functionality through an instance of EventDispatcher initialized in the constructor.
senocular
July 14th, 2006, 03:00 AM
Event objects used with EventDispatcher in ActionScript 3 are a little less generic than those used with ActionScript 2. In AS 3, each event object has its own class. The most common event classes are Event (flash.events.Event (http://livedocs.macromedia.com/flex/2/langref/flash/events/Event.html)) for general events and MouseEvent (flash.events.MouseEvent (http://livedocs.macromedia.com/flex/2/langref/flash/events/MouseEvent.html)) for events associated with the mouse. Other event classes can be found in the flash.events package, all of which inherit from Event.
When using EventDispatcher.dispatchEvent(), you pass in an Event instance that is specific to the event being dispatched. The type of event dispatched is defined within the Event instance used. For example, dispatching an "enterFrame" event would mean using dispatchEvent with an Event instance instantiated with the type "enterFrame".
dispatchEvent(new Event("enterFrame"));
When an event handler is executed as a result of this event, that event object is passed into the function as a single argument. Properties from that event can then be extracted to learn more about the event that occured. For example, the type property from the Event class tells which event was dispatched.
addEventListener("enterFrame", eventHandler);
dispatchEvent(new Event("enterFrame"));
...
private function eventHandler(event:Event):void {
trace(event.type); // "enterFrame"
}
Though event types are strings, all common Flash events are available in Flash through static constants of the Event classes. The "enterFrame" event type, for example, is accessible using Event.ENTER_FRAME. Mouse events are within the MouseEvent class. Click events, for example, are MouseEvent.CLICK. These constants are prefered over their string representations.
addEventListener(Event.ENTER_FRAME, eventHandler);
dispatchEvent(new Event(Event.ENTER_FRAME));
When making your custom Events, you can use the Event object with a custom type or alternatively, extend the Event class creating a new kind of Event instance to be used with your events.
senocular
July 14th, 2006, 05:28 PM
In ActionScript 3, you can define XML variables using inline XML in your script. You don't even need to enclose it in Strings like you did in previous versions of ActionScript. The ActionScript 3 compiler will automatically parse the XML in the code and recognize when it stops and when normal AS code starts.
var myXml:XML =
<body>
<!-- comment -->
text1
<a>
<b>text2</b>
</a>
</body>;
gerardo
July 14th, 2006, 08:45 PM
Hey senocular, jus wondering if you can post something about the new URLLoader and URLRequest use with PHP. Thanks in advance.
senocular
July 14th, 2006, 08:51 PM
Hey senocular, jus wondering if you can post something about the new URLLoader and URLRequest use with PHP. Thanks in advance.
If you have a specific question, post a new thread about it in the forum
senocular
July 17th, 2006, 10:53 AM
ActionScript 3 lets you easily obtain any instances class name using a new function called getQualifiedClassName (flash.utils.getQualifiedClassName (http://livedocs.macromedia.com/flex/2/langref/flash/utils/package.html#getQualifiedClassName())).
var sprite:Sprite = new Sprite();
trace(getQualifiedClassName(sprite)); // "flash.display::Sprite"
You can also use the getQualifiedSuperclassName (flash.utils.getQualifiedSuperclassName (http://livedocs.macromedia.com/flex/2/langref/flash/utils/package.html#getQualifiedSuperclassName())) function to find its superclass
trace(getQualifiedSuperclassName(sprite)); // "flash.display::DisplayObjectContainer"
If you want to go backwards, and convert a string into an actual class reference, you can use getDefinitionByName (flash.utils.getDefinitionByName (http://livedocs.macromedia.com/flex/2/langref/flash/utils/package.html#getDefinitionByName())).
trace(getDefinitionByName("flash.display::Sprite")); // [class Sprite]
Also see describeType() (flash.utils.describeType (http://livedocs.macromedia.com/flex/2/langref/flash/utils/package.html#describeType())) in the following post...
devonair
July 17th, 2006, 01:03 PM
that's beautiful.. so much better than typeof.. Though I might also add (if I may), if you want some extremely (almost stupid amount of) detailed info about your class type, you can also use describeType()..
so
var sprite:Sprite = new Sprite();
var spriteDescription:XML = describeType(sprite);
trace (spriteDescription);
traces:
<type name="flash.display::Sprite" base="flash.display::DisplayObjectContainer" isDynamic="false" isFinal="false" isStatic="false">
<extendsClass type="flash.display::DisplayObjectContainer"/>
<extendsClass type="flash.display::InteractiveObject"/>
<extendsClass type="flash.display::DisplayObject"/>
<extendsClass type="flash.events::EventDispatcher"/>
<extendsClass type="Object"/>
<implementsInterface type="flash.events::IEventDispatcher"/>
<implementsInterface type="flash.display::IBitmapDrawable"/>
<accessor name="buttonMode" access="readwrite" type="Boolean" declaredBy="flash.display::Sprite"/>
<accessor name="soundTransform" access="readwrite" type="flash.media::SoundTransform" declaredBy="flash.display::Sprite"/>
<accessor name="useHandCursor" access="readwrite" type="Boolean" declaredBy="flash.display::Sprite"/>
<method name="stopDrag" declaredBy="flash.display::Sprite" returnType="void"/>
<accessor name="dropTarget" access="readonly" type="flash.display::DisplayObject" declaredBy="flash.display::Sprite"/>
<accessor name="graphics" access="readonly" type="flash.display::Graphics" declaredBy="flash.display::Sprite"/>
<accessor name="hitArea" access="readwrite" type="flash.display::Sprite" declaredBy="flash.display::Sprite"/>
<method name="startDrag" declaredBy="flash.display::Sprite" returnType="void">
<parameter index="1" type="Boolean" optional="true"/>
<parameter index="2" type="flash.geom::Rectangle" optional="true"/>
</method>
<method name="swapChildren" declaredBy="flash.display::DisplayObjectContainer" returnType="void">
<parameter index="1" type="flash.display::DisplayObject" optional="false"/>
<parameter index="2" type="flash.display::DisplayObject" optional="false"/>
</method>
<accessor name="tabChildren" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObjectContainer"/>
<method name="getObjectsUnderPoint" declaredBy="flash.display::DisplayObjectContainer" returnType="Array">
<parameter index="1" type="flash.geom::Point" optional="false"/>
</method>
<method name="getChildAt" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
<parameter index="1" type="int" optional="false"/>
</method>
<method name="removeChildAt" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
<parameter index="1" type="int" optional="false"/>
</method>
<method name="getChildIndex" declaredBy="flash.display::DisplayObjectContainer" returnType="int">
<parameter index="1" type="flash.display::DisplayObject" optional="false"/>
</method>
<method name="areInaccessibleObjectsUnderPoint" declaredBy="flash.display::DisplayObjectContainer" returnType="Boolean">
<parameter index="1" type="flash.geom::Point" optional="false"/>
</method>
<method name="contains" declaredBy="flash.display::DisplayObjectContainer" returnType="Boolean">
<parameter index="1" type="flash.display::DisplayObject" optional="false"/>
</method>
<accessor name="mouseChildren" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObjectContainer"/>
<method name="removeChild" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
<parameter index="1" type="flash.display::DisplayObject" optional="false"/>
</method>
<method name="setChildIndex" declaredBy="flash.display::DisplayObjectContainer" returnType="void">
<parameter index="1" type="flash.display::DisplayObject" optional="false"/>
<parameter index="2" type="int" optional="false"/>
</method>
<method name="addChildAt" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
<parameter index="1" type="flash.display::DisplayObject" optional="false"/>
<parameter index="2" type="int" optional="false"/>
</method>
<accessor name="numChildren" access="readonly" type="int" declaredBy="flash.display::DisplayObjectContainer"/>
<method name="addChild" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
<parameter index="1" type="flash.display::DisplayObject" optional="false"/>
</method>
<method name="getChildByName" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
<parameter index="1" type="String" optional="false"/>
</method>
<accessor name="textSnapshot" access="readonly" type="flash.text::TextSnapshot" declaredBy="flash.display::DisplayObjectContainer"/>
<method name="swapChildrenAt" declaredBy="flash.display::DisplayObjectContainer" returnType="void">
<parameter index="1" type="int" optional="false"/>
<parameter index="2" type="int" optional="false"/>
</method>
<accessor name="doubleClickEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
<accessor name="contextMenu" access="readwrite" type="flash.ui::ContextMenu" declaredBy="flash.display::InteractiveObject"/>
<accessor name="accessibilityImplementation" access="readwrite" type="flash.accessibility::AccessibilityImplementation" declaredBy="flash.display::InteractiveObject">
<metadata name="Inspectable">
<arg key="environment" value="none"/>
</metadata>
</accessor>
<accessor name="mouseEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
<accessor name="focusRect" access="readwrite" type="Object" declaredBy="flash.display::InteractiveObject"/>
<accessor name="tabIndex" access="readwrite" type="int" declaredBy="flash.display::InteractiveObject"/>
<accessor name="tabEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
<accessor name="alpha" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="scale9Grid" access="readwrite" type="flash.geom::Rectangle" declaredBy="flash.display::DisplayObject"/>
<accessor name="name" access="readwrite" type="String" declaredBy="flash.display::DisplayObject"/>
<accessor name="filters" access="readwrite" type="Array" declaredBy="flash.display::DisplayObject"/>
<accessor name="y" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="rotation" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="scrollRect" access="readwrite" type="flash.geom::Rectangle" declaredBy="flash.display::DisplayObject"/>
<accessor name="x" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="cacheAsBitmap" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObject"/>
<accessor name="accessibilityProperties" access="readwrite" type="flash.accessibility::AccessibilityProperties" declaredBy="flash.display::DisplayObject"/>
<method name="globalToLocal" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Point">
<parameter index="1" type="flash.geom::Point" optional="false"/>
</method>
<method name="getBounds" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Rectangle">
<parameter index="1" type="flash.display::DisplayObject" optional="false"/>
</method>
<accessor name="opaqueBackground" access="readwrite" type="Object" declaredBy="flash.display::DisplayObject"/>
<method name="hitTestPoint" declaredBy="flash.display::DisplayObject" returnType="Boolean">
<parameter index="1" type="Number" optional="false"/>
<parameter index="2" type="Number" optional="false"/>
<parameter index="3" type="Boolean" optional="true"/>
</method>
<accessor name="visible" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObject"/>
<accessor name="mouseX" access="readonly" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="mask" access="readwrite" type="flash.display::DisplayObject" declaredBy="flash.display::DisplayObject"/>
<method name="getRect" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Rectangle">
<parameter index="1" type="flash.display::DisplayObject" optional="false"/>
</method>
<accessor name="scaleX" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="scaleY" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="root" access="readonly" type="flash.display::DisplayObject" declaredBy="flash.display::DisplayObject"/>
<accessor name="loaderInfo" access="readonly" type="flash.display::LoaderInfo" declaredBy="flash.display::DisplayObject"/>
<method name="hitTestObject" declaredBy="flash.display::DisplayObject" returnType="Boolean">
<parameter index="1" type="flash.display::DisplayObject" optional="false"/>
</method>
<accessor name="transform" access="readwrite" type="flash.geom::Transform" declaredBy="flash.display::DisplayObject"/>
<accessor name="width" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="stage" access="readonly" type="flash.display::Stage" declaredBy="flash.display::DisplayObject"/>
<accessor name="parent" access="readonly" type="flash.display::DisplayObjectContainer" declaredBy="flash.display::DisplayObject"/>
<accessor name="height" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<method name="localToGlobal" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Point">
<parameter index="1" type="flash.geom::Point" optional="false"/>
</method>
<accessor name="mouseY" access="readonly" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="blendMode" access="readwrite" type="String" declaredBy="flash.display::DisplayObject"/>
<method name="removeEventListener" declaredBy="flash.events::EventDispatcher" returnType="void">
<parameter index="1" type="String" optional="false"/>
<parameter index="2" type="Function" optional="false"/>
<parameter index="3" type="Boolean" optional="true"/>
</method>
<method name="addEventListener" declaredBy="flash.events::EventDispatcher" returnType="void">
<parameter index="1" type="String" optional="false"/>
<parameter index="2" type="Function" optional="false"/>
<parameter index="3" type="Boolean" optional="true"/>
<parameter index="4" type="int" optional="true"/>
<parameter index="5" type="Boolean" optional="true"/>
</method>
<method name="toString" declaredBy="flash.events::EventDispatcher" returnType="String"/>
<method name="dispatchEvent" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
<parameter index="1" type="flash.events::Event" optional="false"/>
</method>
<method name="hasEventListener" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
<parameter index="1" type="String" optional="false"/>
</method>
<method name="willTrigger" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
<parameter index="1" type="String" optional="false"/>
</method>
</type>
I just love AS3... really, I do...
senocular
July 17th, 2006, 01:10 PM
I was going to save that as a tip for another day :bad: but thanks :trout:
McGuffin
July 17th, 2006, 01:35 PM
Sen, question about getDefinitionByName(). Does the class need to be hardcoded into the file before using the returned value for getDefinitionByName()? Example:
I have a pageType field in a MySQL database that tells the Flash site which page template to use for its pages. Homepage, Aboutpage, etc. I use:
var className:String = "pages."+_root.pageDatabase.getPageType(i);
var theStringClass:Function = mx.utils.ClassFinder.findClass(className);
_root["pageInstance"+i] = new theStringClass();
To create each page. The problem is, I need to hardcode an instance of each of these page classes into my site so that file will load and keep the class.
var homepagedisplay = new pages.Homepage();
delete homepagedisplay;
I'd like to skip that step, seeing as how I could have it completely dynamic if I didn't have to hardcode in anything.
senocular
July 17th, 2006, 02:04 PM
You should need to at least import the needed classes into your file if not native player classes. If you dont, Flash will not have them in the SWF to use. With AS3, instantiation shouldnt be required (and really, with AS2, it wasnt either as long as you used the class reference somewhere).
devonair
July 17th, 2006, 02:08 PM
I was going to save that as a tip for another day :bad: but thanks :trout:
whoops.. sorry - seemed to fit the topic...
senocular
July 17th, 2006, 02:09 PM
I almost added it as part of that one, but I was starting to get a little thin on topics, and since they were every day I'm going to try to stretch them out. Not a big deal ;)
senocular
July 18th, 2006, 12:15 AM
In ActionScript 2, the call to super() in the constructor of a class inheriting from another class had to be the first statement within the constructor. If you didn't add it explicitly yourself, it was added for you.
In ActionScript 3, super will still be added for you if you did not include it yourself, but now you are allowed to place it anywhere within your constructor, even after other statements; it no longer has to be the first statement in your constructor.
package {
public class SubClass extends SuperClass {
protected var value:int;
public function SubClass(value:int = 0) {
this.value = value;
super(20);
}
}
}
senocular
July 18th, 2006, 12:20 AM
In ActionScript 2, the call to super() in the constructor of a class inheriting from another class had to be the first statement within the constructor. If you didn't add it explicitly yourself, it was added for you.
In ActionScript 3, super will still be added for you if you did not include it yourself, but now you are allowed to place it anywhere within your constructor, even after other statements; it no longer has to be the first statement in your constructor.
package {
public class SubClass extends SuperClass {
protected var value:int;
public function SubClass(value:int = 0) {
this.value = value;
super(20);
}
}
}
senocular
July 18th, 2006, 12:45 PM
Just a little FYI - I changed the links in the index to reference the posts in the context of the thread. This makes it a little easier to go through and read related posts as well :)
Krilnon
July 18th, 2006, 01:31 PM
If you extend a class, the constructor for the extended class won't run upon instantiation, but it can still be accessed with super, correct?
senocular
July 18th, 2006, 01:44 PM
the super class constructor will still run, you can just decide when now (AS2 it was always before any other code).
Krilnon
July 18th, 2006, 03:27 PM
You might want to edit the override (http://www.kirupa.com/forum/showthread.php?p=1893462#post1893462) post to mention that when you override methods that use the AS3 namespace, you need to include the namespace in your override definition.
The post mentions the need to match the method signature, but it probably took me half of an hour to figure out that I needed to include the namespace to avoid an error I was getting when overriding Array.push().
senocular
July 19th, 2006, 07:04 PM
MovieClip (flash.display.MovieClip (http://livedocs.macromedia.com/flex/2/langref/flash/display/MovieClip.html)) instances in ActionScript 3 have a couple of new properties called currentLabels and currentLabel. currentLabels is an array of FrameLabel (flash.display.FrameLabel (http://livedocs.macromedia.com/flex/2/langref/flash/display/FrameLabel.html)) instances describing the frame labels within the movie clip's timeline. Each FrameLabel in the currentLabels array contains two properties: name, and frame. Name provides the name of the label and frame is the frame number on which it exists. currentLabel returns the name of the label associated with the current frame.
var label:String = my_mc.currentLabel;
senocular
July 21st, 2006, 04:36 PM
As with previous versions of ActionScript, there exists a trace function for outputing messages into the Output panel in Flash. In ActionScript 1 and 2, trace accepted one argument that was outputed to the Output panel in Flash. In ActionScript 3, trace now accepts any number of arguments and outputs them each.
trace(value1, value2, value3);
Note: You could get essentially the same effect in AS1 and AS2 using
trace([value1, value2, value3]);
using an array ;)
senocular
July 21st, 2006, 04:42 PM
When you define event handlers in ActionScript 3, the functions need to accept 1 parameter of the type Event. When these methods are called by the events, those event objects are then passed into the handler.
If you have an event handler that you want to use as a normal function call, you can call that function with a new Event object passed into it like so:
myHandler(new Event(someEventType));
However, that can be a hassle and a little confusing (plus you are creating an event that probably has nothing to do with the function). If you just want to be able to call the event handler without having to worry about that event but still have it work for calls coming from events, you can define the handler with your event parameter having a default value of null. This way you can call the function without an event but still have it work when the event is passed from an actual event call.
public function myHandler(event:Event = null):void {...}
...
// call normally without event
myHandler();
Note: this will not work if your event handler relies on information from the event object.
senocular
July 22nd, 2006, 06:49 PM
Methods relying on URL strings in ActionScript 3 now use URLRequest (flash.net.URLRequest (http://livedocs.macromedia.com/flex/2/langref/flash/net/URLRequest.html)) instances instead of direct string values for URLs. URLRequest instances contain the following properties:
contentType:String
data:Object
method:String
requestHeaders:Array
url:String
which relates to the URL itself (specified in the url property).
For example, when using navigateToURL() (flash.net.navigateToURL (http://livedocs.macromedia.com/flex/2/langref/flash/net/package.html#navigateToURL())) (getURL() replacement), instead of passing a string of the URL to navigate to, you use a URLRequest instance.
var request:URLRequest = new URLRequest("http://www.adobe.com/");
navigateToURL(request);
masylum
July 25th, 2006, 04:14 AM
eval() is removed...
senocular
July 25th, 2006, 11:43 AM
XML has changed for ActionScript 3. The new way of dealing with XML revolves around E4X - ECMAScript's XML specification. This provides a different, more efficient interface for dealing with XML nodes and attributes. These are all associated with the new XML (top level XML (http://livedocs.macromedia.com/flex/2/langref/XML.html)) class.
var myXML:XML = new XML(objectToConvert);
var myXML:XML = <node />;
The old class, as it was used in ActionScript 1 and 2, is still around. However, it has been renamed to XMLDocument (flash.xml.XMLDocument (http://livedocs.macromedia.com/flex/2/langref/flash/xml/XMLDocument.html)). If you want to work with XML the way you did with AS1 and AS2, you would use XMLDocument instead of XML.
var myXML:XMLDocument = new XMLDocument("<node />");
senocular
July 25th, 2006, 11:56 AM
In previous versions of ActionScript, there were a couple of classes who had the capability of loading external text, namely LoadVars and XML. The loading responsibilities of these classes has moved to one single class in ActionScript 3, URLLoader (flash.net.URLLoader (http://livedocs.macromedia.com/flex/2/langref/flash/net/URLLoader.html)). This class is a lot like LoadVars. The big difference is that it is used for XML since the responsibility of loading XML from an external source has been removed from the XML class. Instead, you would load the text with URLLoader and then give that text to an XML object for parsing.
Like LoadVars, URLLoader has a load() method that is used to load text from an external source. This accepts 1 argument, a URLRequest instance (NOT a URL string). You can then use events from URLLoader to determine when the loading is complete. When complete, the text loaded is available in the data property of URLLoader.
Example:
var loader:URLLoader;
// ...
loader = new URLLoader();
loader.addEventListener(Event.COMPLETE, xmlLoaded);
var request:URLRequest = new URLRequest("file.xml");
loader.load(request);
//...
function xmlLoaded(event:Event):void {
var myXML:XML = new XML(loader.data);
//...
}
theHollow
July 25th, 2006, 11:22 PM
Where can i download the Flash 9 Player application from? I don't want the plugin.
senocular
July 26th, 2006, 12:16 AM
Where can i download the Flash 9 Player application from? I don't want the plugin.
When you download Flex Builder, the Flex SDK, or Flash Alpha 9, you will also get standalone versions of the player (links in the first post).
NiñoScript
July 26th, 2006, 02:21 AM
trace(value1, value2, value3);
is there anyway so i can make a function (or class method) that accepts any number of arguments?
Krilnon
July 26th, 2006, 05:14 AM
is there anyway so i can make a function (or class method) that accepts any number of arguments? Yep, use ... (rest). Senocular mentioned it in this post (http://www.kirupa.com/forum/showpost.php?p=1881430&postcount=23), and the documentation on it is here (http://livedocs.macromedia.com/flex/2/langref/statements.html#..._%28rest%29_parameter).
NiñoScript
July 26th, 2006, 11:44 AM
wow, thats cool!
now, one more question... is there anyway to pass that array as single arguments for another function?
something like:
function _trace(... rest):Array {
trace(rest);
/* well... this is not a good example
couse trace can accept an array as argument...
but think about a function that can accept any number of Numbers
but does nothing if you pass an Array to it */
return rest;
}
senocular
July 26th, 2006, 11:45 AM
use Function.apply() just like in AS1 and AS2
NiñoScript
July 26th, 2006, 01:57 PM
ohh, i never used that :P
thanks ;)
senocular
July 29th, 2006, 11:51 AM
The is operator (is operator (http://livedocs.macromedia.com/flex/2/langref/operators.html#is)) is a new keyword that lets you check to see if an instance is of a certain object type. This works for ActionScript 3 class instances checked against class types as well as interfaces. Ex:
var mySprite:Sprite = new Sprite();
trace(mySprite is Sprite); // true
trace(mySprite is DisplayObject); // true
trace(mySprite is IEventDispatcher); // true
The is operator is a replacement for instanceof (instanceof operator (http://livedocs.macromedia.com/flex/2/langref/operators.html#instanceof)) from ActionScript 1 and 2. The is operator, however, is specific to AS3 classes and is used to check the inheritance specific to those classes. This will not work on dynamic classes created with AS1-style constructor functions. In that situation, you would use instanceof since instanceof checks the prototype chain of an instance as opposed to class inheritance (which is does). Because an AS3 class's class inheritance is mirrored in its prototype chain, this means that instanceof will also work for AS3 classes, though is is prefered then (and less typing!).
var mySprite:Sprite = new Sprite();
trace(mySprite instanceof Sprite); // true
trace(mySprite instanceof DisplayObject); // true
trace(mySprite instanceof IEventDispatcher); // false - not in prototype chain
var AS1StyleClass:Function = function(){}
AS1StyleClass.prototype = new MovieClip();
var as1Instance:* = new AS1StyleClass();
trace(as1Instance instanceof AS1StyleClass); // true
trace(as1Instance instanceof MovieClip); // true
trace(as1Instance is AS1StyleClass); // true
trace(as1Instance is MovieClip); // false - cant see prototype chain
senocular
July 29th, 2006, 12:24 PM
In Flash 9 with AS3, you are able to associate all timelines with classes, including the root timeline. Movie clip timelines are associated with classes the same way as ActionScript 2 using the linkage dialog. The root timeline can be given a class association through the property inspector or through the publish settings (in ActionScript settings).
If you do not associate a timeline with a class, one is automatically created for that timeline by Flash. When this happens, variables become class variables, all named functions (declared using function functionName(){}) become methods of that class, and all scripts within the frames associated with methods that are automatically called when that frame is reached (minus the variable and method definitions). Because of this, you can only declare variables and named functions of any specific name for a function once since all variables on all frames are used in the same final class definition. Variables you can redefine, but not redeclare. Functions (methods) are locked. Note: You cannot mix classes associated with timelines and timeline scripts.
One thing to be careful of, is that though you may define a variable when you declare it, that definition will not appear with the declaration in the class. Definitions (values assigned to variables) are separated and handled in the frame scripts. So for any variable to have been defined in such an instance, the first frame would have to have run to set up those definitions.
The following timeline script in Flash 9
var num:Number = 1;
function showNum():void {
trace(num);
}
showNum();
essentially becomes the following AS3 class that gets associated with that timeline:
package {
class TimelineClass extends MovieClip {
public var num:Number;
public function showNum():void {
trace(this.num);
}
public function frame1():void {
num = 1;
showNum();
}
}
}
If you need variables to be defined immediately after instantiation, for example when creating an instance with the new keyword, then you may want to set up a custom method that can be called when the object is created to do that for you.
var num:Number;
function init(){
num = 1;
return this;
}
function showNum():void {
trace(num);
}
showNum();
becomes:
package {
class TimelineClass extends MovieClip {
public var num:Number;
public function showNum():void {
trace(this.num);
}
public function init():void {
num = 1;
return this;
}
public function frame1():void {
showNum();
}
}
}
Create it by using
var myMC:TimelineClass = new TimelineClass().init();
trace(myMC.num); // 1
senocular
July 29th, 2006, 12:49 PM
Here's an example of how one might validate email using ActionScript 3's Regular Expression class (Top level RegExp (http://livedocs.macromedia.com/flex/2/langref/RegExp.html)):
function isValidEmail(email:String):Boolean {
var emailExpression:RegExp = /^[a-z][\w.-]+@\w[\w.-]+\.[\w.-]*[a-z][a-z]$/i;
return emailExpression.test(email);
}
//...
trace(isValidEmail("senocular@example.com")); // true
trace(isValidEmail("@example.com")); // false
trace(isValidEmail("senocular@example")); // false
trace(isValidEmail("seno\\cular@example.com")); // false
senocular
July 29th, 2006, 01:16 PM
ActionScript has long since relied on the enterFrame (onEnterFrame) event for time-based actions, especially animation and actions relating to frame playback. In comparison, Director's Lingo language has, not only an enterFrame event, but two other frame events, prepareFrame and exitFrame. Though ActionScript 3 has not aquired prepareFrame or exitFrame, it has gained a new frame event, render, or Event.RENDER (flash.events.Event.RENDER (http://livedocs.macromedia.com/flex/2/langref/flash/events/Event.html#RENDER)).
The render event in AS3 is a frame event that occurs after enterFrame (flash.events.Event.ENTER_FRAME (http://livedocs.macromedia.com/flex/2/langref/flash/events/Event.html#ENTER_FRAME)) allowing one more chance to do what you need to do before the screen updates its display.
Unlike enterFrame, however, the render event will not be called unless the display object using it is attached to a stage (or in any display list attached to the stage). Also, render is not automatically called every frame, even if attached to the stage. In order for render to be called for the current frame, you must make a call to stage.invalidate() (flash.display.Stage.invalidate() (http://livedocs.macromedia.com/flex/2/langref/flash/display/Stage.html#invalidate()));
Ex:
var sprite:Sprite = new Sprite();
stage.addChild(sprite);
sprite.addEventListener(Event.ENTER_FRAME, enterFrame);
sprite.addEventListener(Event.RENDER, render);
stage.addEventListener(MouseEvent.CLICK, click);
function enterFrame(event:Event):void {
trace("enter frame");
}
function render(event:Event):void {
trace("render");
}
function click(event:MouseEvent):void {
trace("click");
stage.invalidate();
}
Output:
enter frame
enter frame
enter frame
click
enter frame
render
enter frame
enter frame
enter frame
enter frame
...
senocular
July 29th, 2006, 01:37 PM
E4X (XML used in ActionScript 3) has new operators to access values in XML. One operator is the @ operator which accesses attributes. It can be used in place of the attribute() (Top level XML.attribute() (http://livedocs.macromedia.com/flex/2/langref/XML.html#attribute())) method for obtaining attribute values. Ex:
var myXML:XML = <user name="senocular" id="2867" />;
trace(myXML.attribute("name")); // senocular
trace(myXML.attribute("id")); // 2867
trace(myXML.@name); // senocular
trace(myXML.@id); // 2867
You can also use an asterisk (*) with the @ operator to get a list of all attributes associated with an XML node in the form of an XMLList object. This is equivalent to the attributes() (Top level XML.attributes() (http://livedocs.macromedia.com/flex/2/langref/XML.html#attribute())) method. Ex:
var myXML:XML = <user name="senocular" id="2867" />;
var atts:XMLList;
atts = myXML.attributes();
trace(atts.toXMLString());
/* Output:
senocular
2867
*/
atts = myXML.@*;
trace(atts.toXMLString());
/* Output:
senocular
2867
*/
senocular
July 29th, 2006, 01:40 PM
sorry about the delay this week; I got slammed at work :)
Deviant1853
July 30th, 2006, 10:27 AM
ActionScript 3 lets you easily obtain any instances class name using a new function called getQualifiedClassName (flash.utils.getQualifiedClassName (http://livedocs.macromedia.com/flex/2/langref/flash/utils/package.html#getQualifiedClassName%28%29)).
ActionScript Code:
var sprite:Sprite = new Sprite();
trace(getQualifiedClassName(sprite)); // "flash.display::Sprite"
You can also use the getQualifiedSuperclassName (flash.utils.getQualifiedSuperclassName (http://livedocs.macromedia.com/flex/2/langref/flash/utils/package.html#getQualifiedSuperclassName%28%29)) function to find its superclass
ActionScript Code:
trace(getQualifiedSuperclassName(sprite)); // "flash.display::DisplayObjectContainer"
If you want to go backwards, and convert a string into an actual class reference, you can use getDefinitionByName (flash.utils.getDefinitionByName (http://livedocs.macromedia.com/flex/2/langref/flash/utils/package.html#getDefinitionByName%28%29)).
ActionScript Code:
trace(getDefinitionByName("flash.display::Sprite")); // [class Sprite]
With getDefinitionByName you should in theory be able to do some basic Object Reflection ? I guess you would have to do the method information manually though...
senocular
July 30th, 2006, 12:44 PM
With getDefinitionByName you should in theory be able to do some basic Object Reflection ? I guess you would have to do the method information manually though...
Did you see devonair's mention of describeType in the following post?
senocular
July 30th, 2006, 02:13 PM
ActionScript 3 now supports event propagation - the transference of a single event applying to multiple objects to each of those objects instead of one - in Display objects. In ActionScript 1 and 2, "Button" events (such as onPress, onRelease, etc.) handled by movie clips were not propagated to that movie clip's children. This means that though visually you were clicking on a child of a movie clip handling an onPress event, that onPress would never make it to the child because the parent movie clip handling the event would intercept it and prevent the propagation of the onPress event to that child.
Example; movie clip parent_mc contains child_mc:
// AS1 and AS2
parent_mc.onPress = function(){
trace("parent pressed");
}
parent_mc.child_mc.onPress = function(){
trace("child pressed");
}
/* click child output:
parent pressed
*/
// AS3
parent_mc.addEventListener(MouseEvent.CLICK, parentClick);
parent_mc.child_mc.addEventListener(MouseEvent.CLI CK, childClick);
function parentClick(event:MouseEvent):void {
trace("parent pressed");
}
function childClick(event:MouseEvent):void {
trace("child pressed");
}
/* click child output:
child pressed
parent pressed
*/
In ActionScript 1 and 2, the child is never able to receive the event. In ActionScript 3, both movie clips are able to receieve it as the event is propagated to each movie clip to which it applies.
senocular
July 31st, 2006, 12:06 PM
Using ActionScript 3 you can now obtain sound spectrum information from audio played through Flash. This lets you create visualizations like those seen in popular in media player applications. The class that provides this information is the SoundMixer class (flash.media.SoundMixer (http://livedocs.macromedia.com/flex/2/langref/flash/media/SoundMixer.html)). It's computeSpectrum method (static) places sound spectrum information in a ByteArray instance which can then be used to generate a visualization.
// play sound...
var spectrumInfo:ByteArray = new ByteArray();
SoundMixer.computeSpectrum(spectrumInfo);
// spectrumInfo is now a byte array with sound spectrum info
oybrator
July 31st, 2006, 04:51 PM
I apologize in advance if this seems horribly out of place, but here it goes:
Would it make sense to start learning ActionScript 3.0 without knowing 2.0?
I am a fairly experienced ActionScript developer and I've been working with flash since version 3. When ActionsScript 2.0 arrived I sort of missed the point and went on developing with 1.0, after all it gets the job done and I'm already fluent in it.
Now I'm sweating a bit over having not kept up with the evolution and have decided I'm well overdue for catching up. I know a few basics of AS 2.0, but have never built anything with it. Should I make an effort to learn it and use it before progressing to 3.0 or would it be just as sensible to go straight to 3.0?
Any opinions with be greatly appreciated :-)
Thanks!
icio
July 31st, 2006, 07:57 PM
If you're fluent in AS 1.0 it will only take a couple of days to learn what you need to do differently for AS 2.0
You've still got time before AS 3.0 is released with Flash 9 so I would take the time you have to catch up :)
oybrator
August 1st, 2006, 06:35 AM
If you're fluent in AS 1.0 it will only take a couple of days to learn what you need to do differently for AS 2.0
You've still got time before AS 3.0 is released with Flash 9 so I would take the time you have to catch up :)
So by that you mean that learning stuff that's "wrong" in terms of AS 3.0 is still the right way to go because it would be easier?
Thanks for your reply by the way!
icio
August 1st, 2006, 06:43 AM
Yes... I think that's what I'm saying.
The thing is, with learning AS 3.0 you pretty much learn all you need to know that's different from between AS 2.0 and AS 1.0.
Learning AS 2.0 would more acustom you to how AS 2.0 defines variables etc. Also, if you learn AS 2.0 you're going to be a more experienced developer :)
AS 3.0 isn't going to be mainstream for a while yet... you could probably do both :)
theHollow
August 1st, 2006, 06:46 AM
I'm guessing it is, but is AS 2.0 still going to be supported when AS 3.0 becomes mainstream?
senocular
August 1st, 2006, 12:53 PM
I'm guessing it is, but is AS 2.0 still going to be supported when AS 3.0 becomes mainstream?
Yes. AS3 represents a roadblock in terms of backwards compatibility. The only thing that can play AS3 is Flash 9. AS2 is essentially AS1 so even Flash Player 6 can play movies creates with AS2. Since the Flash player, as of 9, contains the VMs for both AS1/AS2 and AS3, AS1/AS2 will continue to be completely supported. And, really, AS1 will probably continue to be easier to use for designers since you have things like getURL("url string") and not navigateToUrl(new UrlReqest("url string")) and on events and things like that. But most importantly if that if you want to shoot for any earlier versions of the player, you'll be using AS1/AS2.
senocular
August 1st, 2006, 07:56 PM
In ActionScript 1 and 2, when you convert String values into their number equivalents using Number(), if the number was preceded by a "0", the value would be interpreted as an octal value (base 8) much in the same way a preceding "0x" means hex (base 16).
// ActionScript 1 and 2
trace(Number("010")); // 8
This could often cause problems for 'normal' values that, more often than not, you'd rather stay decimal (base 10). In ActionScript 3, this is no longer the case. String values with preceding "0"s are no longer treated as octals (though "0x" still means hex).
// ActionScript 3
trace(Number("010")); // 10
If you want to interpret a string as an octal, you would then use parseInt specifying a radix of 8
trace(parseInt("010", 8)); // 8
senocular
August 2nd, 2006, 12:33 AM
Garbage collection (GC) is the automatic process in Flash that removes variables from memory when they are no longer needed. There are two processes that handle garbage collection in Flash, reference counting, and mark and sweep.
Reference counting is a process that keeps track of all the variables referencing an object in memory. When a new reference is created to point to an object, its reference count is updated and incremented by one.
var a:Object = new Object(); // new Object in memory given reference count of 1
var b:Object = a; // Object now has reference count of 2
When ever there are no longer any references pointing to an object in memory, that object is purged from memory and permanently forgotten by the player.
delete a; // Object has reference count of 1
delete b; // Object has reference count of 0, removed from memory
Note: remember, the delete operator only removes variable association, it does not delete objects in memory, the GC is responsible for that. Also delete will only work on non class member variables.
There are certain times when reference counting does not work. For example, if you have two objects that reference themselves but reference nothing else, they remain to have a reference count greater than 0 but they are in no way accessible to you, the programmer, so are in all other means as good as gone.
var a:Object = new Object(); // reference(a) count 1
var b:Object = new Object(); // reference(b) count 1
a.b = b; // reference(b) count 2
b.a = a; // reference(a) count 2
delete a; // reference(a) count 1
delete b; // reference(b) count 1
Here both a and b are removed from the current scope so are no longer accessible. b is accessible from a and a is accessible from b, but since you can never get to a or b there's no way to get to b or a. These objects are as good as deleted from the programmer, however, they will remain in memory because they still contain a reference count greater than 0. This is where mark and sweep comes into play.
Mark and sweep is a process that scans all references and object from a base location (such as the root or stage scope) and marks each one found. All of those not found are inaccessible and are therefore deleted. Given the example with a and b, since a and b are no longer accessible from any object path derived from root, they are not marked and eventually get garbage collected.
[root] <- scan...
[objectRef (marked)] <- scan...
[objectRef (marked)] <- scan...
[objectRef (marked)] <- scan...
[objectRef (marked)] <- scan...
[objectRef (marked)] <- scan...
...
[delete all objects not marked]
Mark and sweep is a more expensive process compared to reference counting so it takes longer and is performed less often. In fact, provided little or no activity in your movie, many frames could elapse before mark and sweep kicks in. What this means is that you could potentially have variables in memory for a long time after you assumed them to be gone. For objects that have actions associated with them, such as events coming off of enterFrame events, this could be something to be concerned about since those events could still operate after the object should technically be deleted. You should always make sure you "cleanup" your events for situations where they might remain in memory longer than you want.
oybrator
August 2nd, 2006, 06:51 AM
Yes... I think that's what I'm saying.
The thing is, with learning AS 3.0 you pretty much learn all you need to know that's different from between AS 2.0 and AS 1.0.
Learning AS 2.0 would more acustom you to how AS 2.0 defines variables etc. Also, if you learn AS 2.0 you're going to be a more experienced developer :)
AS 3.0 isn't going to be mainstream for a while yet... you could probably do both :)
I'll take your word for it I've allready started reading "Essential ActionScript 2.0" (Moock) for the second time and I'm enjoying it!
Thanks!
jeromeribot
August 2nd, 2006, 10:38 AM
Here's a little something our resident Chris came up with:
http://www.flashcodersbrighton.org/wordpress/?p=9
thought i'd inform
;)
Jerome
senocular
August 3rd, 2006, 01:31 PM
If you want a reference to exist for an object that will not be counted towards the reference count used by the Garbage collector, then you can use a weak reference. Weak references are ignored by the reference counter and can exist even if the object is deleted.
You can't use weak references anywhere, however. There are only two places you can use weak references in ActionScript 3. One place is with Dictionary objects. The Dictionary constructor allows one optional parameter that specifies whether or not keys within the instance are weak references or not. False is the default value which means strong references. If you pass true, the Dictionary instance will use weak references
var dict:Dictionary = new Dictionary(true); // use weak references as keys
If you do this for Dictionary instances, the keys you use to store values will not be counted towards that object's reference count.
var obj:Object = new Object();
dict[obj] = true;
delete obj; // obj can be garbage collected since the dict reference isnt counted
The EventDispatcher's addEventListener is the other place you can specify weak references. addEventListener has a parameter that lets you specify the listener reference as being weak (since listeners internally require a reference to the object they are listening to).
// addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
addEventListener(MouseEvent.CLICK, clickHandler, false, 0 true); // use weak references
For addEventListener, the default is also false, using strong references, though it's good habit to use weak listeners to help with garbage collection.
senocular
August 4th, 2006, 01:52 PM
Flash 8 let you load bitmap information from the library using a linkage ID and the BitmapData.loadBitmap() method. This is no longer the case with Flash 9 and ActionScript 3. Now, as with timelines and movie clips in the library, Bitmaps are associated with classes. If you do not specify a specific class to be related to your bitmap in the library, you can name one which will be created automatically when publishing the SWF.
Classes associatated with bitmaps in the library are subclasses of BitmapData (flash.display.BitmapData (http://livedocs.macromedia.com/flex/2/langref/flash/display/BitmapData.html)). These are then instantiated as instances in ActionScript using the new keyword. As BitmapData instances, before being able to be seen on the screen, they would need to be associated with a Bitmap (flash.display.Bitmap (http://livedocs.macromedia.com/flex/2/langref/flash/display/Bitmap.html)) instance which is a display object capabale of being added to a display list (BitmapData instances cannot be added to display lists).
A side effect of extending the BitmapData class is, since the BitmapData class has two required parameters (width and height) for instantiation, so will bitmaps created from the library. Unlike direct BitmapData instances, however, the height and width has no bearing on the size of your library bitmap. It will always be created at its original size. So for instantiation, you can just pass 0's.
As an example, lets say you imported a bitmap of Rome in your library. In the linkage dialog for that bitmap, give it a class name of RomeImage - note that you don't have to create this class yourself; it will be created automatically. Then, to display it on the screen in ActionScript, use:
// create instance of RomeImage bitmap data
var romeImageData:RomeImage = new RomeImage(0, 0);
// create a bitmap instance that references the RomeImage instance
var romeImageBitmap:Bitmap = new Bitmap(romeImageData);
// add the new bitmap to the display list
addChild(romeImageBitmap);
cahlan
August 4th, 2006, 06:57 PM
Using ActionScript 3 you can now obtain sound spectrum information from audio played through Flash. This lets you create visualizations like those seen in popular in media player applications. The class that provides this information is the SoundMixer class (flash.media.SoundMixer (http://livedocs.macromedia.com/flex/2/langref/flash/media/SoundMixer.html)). It's computeSpectrum method (static) places sound spectrum information in a ByteArray instance which can then be used to generate a visualization.
FYI ...
There are some cool examples of this here: http://www.gotoandlearn.com/forum/viewtopic.php?t=3175
senocular
August 5th, 2006, 03:50 PM
The typeof operator lets you determine the basic type of any value. Note that this does not give you actual class association information, but only provides a simplistic indication of the type of variable its used with. For more information regarding specific class relation, use instanceof, getQualifiedClassName, or describeType.
In ActionScript 1 and 2, typeof returned the following values:
boolean
function
movieclip
null
number
object
string
undefined
In ActionScript 3, typeof returns:
boolean
function
number
object
string
xml
undefined
Notice that MovieClip instances are, in AS3, no longer recognized by typeof. They are now seen as objects. Additionally, there is no null value (also seen as an object) and xml is seen as being of type xml.
The new number types in AS3, int and uint, when used with typeof both return number.
Also, primitive values (boolean, number, and string) created with their constructors and the new keyword are now recognized as those primitive types by typeof and not as objects as they were in AS1 and AS2.
// AS1 & AS2
trace(typeof new XML()); // object
trace(typeof my_mc); // movieclip
trace(typeof null); // null
trace(typeof true); // boolean
trace(typeof 1); // number
trace(typeof ""); // string
trace(typeof new Boolean()); // object
trace(typeof new Number()); // object
trace(typeof new String()); // object
// AS3
trace(typeof new XML()); // xml
trace(typeof my_mc); // object
trace(typeof null); // object
trace(typeof true); // boolean
trace(typeof 1); // number
trace(typeof ""); // string
trace(typeof new Boolean()); // boolean
trace(typeof new Number()); // number
trace(typeof new String()); // string
trace(typeof int(1)); // number
trace(typeof uint(1)); // number
senocular
August 6th, 2006, 06:19 PM
Like ActionScript 1 and 2, ActionScript 3 has a getBounds() (flash.display.DisplayObject.getBounds() (http://livedocs.macromedia.com/flex/2/langref/flash/display/DisplayObject.html#getBounds())) method for determining the bounds of a movie clip (display object) in the coordinate space of any timeline. In ActionScript 3, however, getBounds has changed to return a Rectangle (flash.geom.Rectangle (http://livedocs.macromedia.com/flex/2/langref/flash/geom/Rectangle.html)) instance instead of a generic object with the properties xMin, xMax, yMin, and yMax.
ActionScript 3 also adds an additional method similar to getBounds called getRect() (flash.display.DisplayObject.getRect() (http://livedocs.macromedia.com/flex/2/langref/flash/display/DisplayObject.html#getRect())). The getRect() method works just like getBounds except it doesn't take into consideration strokes on shapes.
The following example shows the differences between the rectangle shape returned by getBounds and that returned by getRect.
var sprite:Sprite = new Sprite();
sprite.graphics.beginFill(0x999999);
sprite.graphics.lineStyle(10, 0x333);
sprite.graphics.drawCircle(100, 100, 50);
sprite.graphics.endFill();
addChild(sprite);
addChild(createRectShape(sprite.getRect(this), 0xFF00FF));
addChild(createRectShape(sprite.getBounds(this), 0xFF0000));
function createRectShape(rect:Rectangle, color:uint):Shape {
var rectShape:Shape = new Shape();
rectShape.graphics.lineStyle(0, color);
rectShape.graphics.drawRect(rect.left, rect.top, rect.width, rect.height);
return rectShape;
}
Running the above script draws a circle with a stroke of 10 px with two rectangles around it, one which fits to the vector shape of the circle (getRect) and the other which fits to the bounds of the whole object including the stroke (getBounds).
The rectangle returned by getRect relates to width and height values associated with the display object (which doesn't account for strokes) while getBounds returns a rectangle associated with the visual boundaries of the display object. Note that filters are not accounted for in either method.
bodyvisual
August 7th, 2006, 12:09 AM
god i'm so scared of as3 ok?
senocular
August 7th, 2006, 12:00 PM
ActionScript 3 has a new iteration statement: for each..in (for each..in (http://livedocs.macromedia.com/flex/2/langref/statements.html#for_each..in)). for each..in works much like for..in (for..in (http://livedocs.macromedia.com/flex/2/langref/statements.html#for..in)) execpt it loops through the values of an object rather than its keys. Example:
var object:Object = new Object();
object.name = "senocular";
object.id = 2867;
object.isModerator = true;
for each (var value:* in object){
trace(value);
}
/* Output:
true
2867
senocular
*/
Respectively, a for..in would look like:
var object:Object = new Object();
object.name = "senocular";
object.id = 2867;
object.isModerator = true;
for (var key:String in object){
trace(key + ": " + object[key]); // object[key] is value
}
/* Output:
isModerator: true
id: 2867
name: senocular
*/
Note that the key is not available in for each..in.
For dense arrays (arrays with no gaps in element definitions), ActionScript 3 also maintains array element order (using numeric array indices) when using for..in and for each..in rather than basing order off of when the value was created as was the case in ActionScript 1 and 2. Example:
var array:Array = new Array();
array[1] = 1;
array[0] = 2;
array[2] = 3;
for (var key:String in array){
trace("array[" + key + "] = "+ array[key]);
}
Output AS 1 & AS 2:
array[2] = 3
array[0] = 2
array[1] = 1
Output AS 3:
array[0] = 2
array[1] = 1
array[2] = 3
This provides a more intuitive order when iterating through arrays with for..in and for each..in.
Note: To use the for each..in statement with an instance of a user-defined class, you must declare the class with the dynamic attribute.
senocular
August 9th, 2006, 10:55 AM
ActionSript 3 now allows you to specify default values for your function's parameters. In doing so, that parameter then becomes optional and the default value assigned to the respective argument in the function call if a value is explicitly not provided.
function method(required:String, optional:String = "default"):void {
trace(required +" "+optional);
}
method("Hello"); // "Hello default"
You can only place parameters with default values after all required parameters. In other words you can't have
// Incorrect:
function method(required:String = "default", optional:String):void { ...
since there would be no way for optional to be set without required having to be set as well.
senocular
August 9th, 2006, 11:04 AM
Since ActionSript 3 checks argument count when functions are called you are not able to pass any number of arguments to any function like you could in ActionScript 1 or ActionScript 2. Instead, to allow for this, you need to use a new special kind of parameter called ...(rest) (Keyword: ...(rest) (http://livedocs.macromedia.com/flex/2/langref/statements.html#..._(rest)_parameter)).
The ...(rest) parameter is a special parameter placed at the end of a parameter list in a function that specifies that there can be any number of additional arguments of any type passed into that function when its called. The form of the parameter is 3 periods followed by a keyword. When the function is called, the additional arguments are assigned to that keyword in the form of an array.
function usingRest(required:Number, ... optionalArgs):void {
trace(required); // 1
trace(optionalArgs); // [2, 3, 4]
}
usingRest(1, 2, 3, 4);
senocular
August 9th, 2006, 11:14 AM
As with ActionScript 1 and ActionScript 2, ActionScript 3 has an arguments (Top level arguments (http://livedocs.macromedia.com/flex/2/langref/arguments.html)) object that is a special object created for each function call when it is executed in Flash. In ActionScript 3, however, there is no arguments.caller property. To get a reference to the caller, you must pass a reference to that function as an argument. The callee property still exists.
function args(str:String, num:Number):void {
trace(arguments);
}
args("a", 1); // ["a", 1]
Unfortunately, the arguments array does not exist when using the ...(rest) parameter meaning the arguments array can only be used when ...(rest) is not. This is something to consider if you are using ...(rest) but still want a reference to callee.
Increu
August 10th, 2006, 03:59 AM
Hey Sen, when you run out of ideas, maybe you can talk about ByteArray, it would be really cool
gburks
August 10th, 2006, 12:03 PM
RE: your tip of the day, "Detecting When the Mouse Leaves the Movie (http://www.kirupa.com/forum/showthread.php?p=1887831#post1887831)"
I noticed behavior that didn't exist in AS2 that now happens in AS3: When you use an externally loaded SWF to replace the mouse cursor, the loaded movie prevents the hit area from triggering if the movie is directly below the cursor.
I noticed this when trying to load an swf with animation. My buttons would return to the upState as the animation moved below the cursor, and again go back to the overState as the animation moved out of the way.
Attached is a modified version of your class that replaced the cursor. It includes a button on the stage and an animated externally loaded cursor. I left the real mouse pointer visible to demonstrate the "on-off" switching.
gburks
August 10th, 2006, 11:54 PM
solution -
mouseEnabled = false; on the externally loaded movie.
senocular
August 11th, 2006, 01:10 PM
ActionScript 3 now supports namespaces. Namespaces in AS3 are similar to namespaces in XML and provide a way to separate code in to separate "spaces" or collections identifiable through a name (namespace). Namespaces in this respect act much like packages. In the same manner that packages allow you to have different classes with the same name in one application (only defined in different packages), namespaces allow you to have different methods with the same name in one class (defined in different namespaces). Though you may not have known it, chances are you've already been using namespaces. Predefined namespaces include public, private, protected, and internal.
When you use a namespace, you have to declare it just like you declare any other class member. Namespaces are declared using the namespace keyword (namespace Keyword (http://livedocs.macromedia.com/flex/2/langref/statements.html#namespace)). Once declared you can use it to separate members into different namespaces. Ex:
package {
public class UsingNameSpaces {
public namespace company;
public namespace individual;
company var value:int = 10;
individual var value:int = 2;
public function UsingNameSpaces(){
}
company function showValue() {
}
individual function showValue() {
}
}
}
Two namespaces were used here, company and individual. They were used to defined a value variable and a showValue method - one for each namespace. Though they have the same names, since they are in different namespaces, they are allowed.
Additionally, namespaces can otionally be defined with a namespace uri when declared in the class:
package {
public class UsingNameSpaces {
public namespace company = "http://www.example.com/company";
public namespace individual = "http://www.example.com/individual";
company var value:int = 10;
individual var value:int = 2;
public function UsingNameSpaces(){
}
company function showValue() {
}
individual function showValue() {
}
}
}
senocular
August 11th, 2006, 01:10 PM
When you want to access a class member in a namespace, you need to reference that member through the namespace in which it was defined. One way to do this is through the name qualifier operator (name qualifier operator (http://livedocs.macromedia.com/flex/2/langref/operators.html#name_qualifier)).
The name qualifier operator takes the form of two colons that connects the namespace with the member of the class you are trying to access that exists within that namespace, eg. namespace::member. Ex:
package {
public class UsingNameSpaces {
public namespace company = "http://www.example.com/company";
public namespace individual = "http://www.example.com/individual";
company var value:int = 10;
individual var value:int = 2;
public function UsingNameSpaces(){
company::showValue(); // traces 10
individual::showValue(); // traces 2
}
company function showValue() {
trace(company::value);
}
individual function showValue() {
trace(individual::value);
}
}
}
Note that even though showValue is being called within the namespace, the namespace is still needed to reference variables (or other members) in namespaces used within the function body.
disobey design
August 11th, 2006, 02:29 PM
Very interesting stuff on namespaces, Senocular, but I have a question:
How would you reference class members from outside the class?
I assume it would be like this:
var myObj = new UsingNameSpaces();
myObj.company::showValue();
Is that correct? Are the namespace declarations treated as any other class property?
senocular
August 11th, 2006, 05:04 PM
Very interesting stuff on namespaces, Senocular, but I have a question:
How would you reference class members from outside the class?
I assume it would be like this:
var myObj = new UsingNameSpaces();
myObj.company::showValue();
Is that correct? Are the namespace declarations treated as any other class property?
namespaces, as I have written them, aren't necessarily like properties - they're more like classes.
The code you have is correct, but will not work with the UseNameSpaces class as I have written it since the namespaces were defined in the class body. For your code to work, you would need to define the namespaces in the package body (in the same block the class is defined).
package {
public namespace company = "http://www.example.com/company";
public namespace individual = "http://www.example.com/individual";
public class UsingNameSpaces { ... }
}
There is also a way to define namespaces as properties but I will cover that later.
a.neuhaus
August 11th, 2006, 05:06 PM
It might sound like a amenitie to developers, but I'm a designer so it is a bless to me.
What happened to it? All my attempts to import it return an error:
package{
import mx.effects.Tween;
import flash.display.MovieClip;
public class Main extends MovieClip{
public function Main(){
var t:Tween = new Tween();
}
}
}
Error #1046: Type was not found or was not a compile-time constant: Tween.
Is there a way to overcome this missing class?
Or, is there a class in the new API with its functionality?
Thanks in advance.
senocular
August 11th, 2006, 05:16 PM
this was addressed earlier in the thread ;)
matzo
August 11th, 2006, 05:36 PM
I don't know if this really is the place, but many people already asked their as3 questions here, so here I go. I tried the alpha version from flash 9 with this code
import flash.display.*;
var Filter:GradientGlowFilter = new GradientGlowFilter(4.0, 90,[0x00FF00], [50], [3], 4.0, 4.0, 1, 1, "outer");
var Movie:MovieClip = new MovieClip();
Movie.graphics.lineStyle(1);
Movie.graphics.drawRect(10,10,100,100);
addChild(Movie);
Movie.filters=new Array(Filter);
Now, I've tested it and it worked.(Jiehaa!)
But, then I notices that I forgot to import flash.filters.*;
Though, it worked without any problem?
Is this a bug, or is this really the intend of Adobe.
(yeah you may have noticed that English is not at all my native language so.., sorry:p:mountie: )
senocular
August 11th, 2006, 05:45 PM
in Flash 9 the classes inherent to Flash are automatically imported
senocular
August 12th, 2006, 12:55 PM
Like ActionScript 2, ActionScript 3 allows you to create dynamic classes using the dynamic keyword (dynamic keyword (http://livedocs.macromedia.com/flex/2/langref/statements.html#dynamic)). Dynamic classes are classes you can add properties to dynamically without needing to declare or define them within the class definition. An example of a dynamic class would be Array. When you create an Array instance, you can assign to it any variariable you want despite it not being within the Array class definiton.
In AS2, when you extended a class that was dyanmic, that subclass too became dynamic.
// superclass.as
dynamic class superclass {
}
// subclass.as
class subclass extends superclass {
}
// main movie
var instance:subclass = new subclass();
trace(instance.anything); // ok since subclass inherited dynamic
This is no longer the case with AS3. Subclasses of dynamic classes are no longer dynamic unless specified as being dynamic themselves
// superclass.as
package {
dynamic class superclass {
}
}
// subclass.as
package {
class subclass extends superclass {
}
}
// main movie
var instance:subclass = new subclass();
trace(instance.anything); // error, property not defined (not dynamic)
Increu
August 14th, 2006, 09:39 AM
I dont know if i am doing it rigth, but i tryed this:
ActionScript Code:
var cr = new vv1();
addChild(cr);
cr.x = 30;
var c2 = new mc2();
addChild(c2);
c2.x = 40;
var c3 = new mc3();
addChild(c3);
c3.x = 70;
cr.y = 100;
c2.y = 110;
c3.y = 120;
var sortedItems:Array = new Array(cr, c2, c3);
function arrange():void {
sortedItems.sortOn("y", Array.NUMERIC);
var i:int = sortedItems.length;
while(i++){
if( getChildAt(i)!= sortedItems[i]){
setChildIndex(sortedItems[i],i);
}
}
}
arrange();
And flash says:RangeError: the supplied index is out of bounds
senocular
August 14th, 2006, 12:57 PM
it should be while(i--)
Increu
August 14th, 2006, 01:56 PM
Oh, now is working!I dont know why Its always that little things that catch me!
Thanks Sen!!
senocular
August 15th, 2006, 09:28 AM
There are times where you might want to have actions only run when the mouse is within a sprite or movie clip. Director's Lingo programing language has a mouseWithin event that facilitates this. Flash, however, has no such event. However, with ActionScript 3's event model, you can easily create your own.
A mouseWithin event is essentially an enterFrame event that only runs when the mouse is within or touching the display object in which its associated. So, in making your own, all you need to do is define an enterFrame event when the mouse enters the object and remove it when the mouse leaves the object. And yes, technically you could do this in ActionScript 1 and ActionScript 2, but it would mean using up event handlers like onRollOver and onEnterFrame which could interfere with other actions for your movie clip (since you can only have one per movie clip).
For ActionScript 3, implementing a mouseWithin event just means giving your sprite or movie clip class a few event handlers and setting up some listeners, e.g.
// methods managing mouseWithin
private function addMouseWithin(event:MouseEvent):void {
addEventListener(Event.ENTER_FRAME, mouseWithin);
}
private function removeMouseWithin(event:MouseEvent):void {
removeEventListener(Event.ENTER_FRAME, mouseWithin);
}
private function mouseWithin(event:Event):void {
dispatchEvent(new MouseEvent("mouseWithin"));
}
// in constructor
public function MySpriteClass() {
addEventListener(MouseEvent.MOUSE_OVER, addMouseWithin);
addEventListener(MouseEvent.MOUSE_OUT, removeMouseWithin);
}
With that, a mouseWithin event fires every frame whenever the mouse is within the sprite. To add listeners for it, just use:
addEventListener("mouseWithin", mouseWithinHandler);
senocular
August 15th, 2006, 09:37 AM
The final keyword (Toplevel final keyword (http://livedocs.macromedia.com/flex/2/langref/statements.html#final)) is an attribute for classes and methods that lets you prevent overriding (methods) and subclassing (classes).
When a method is marked as final, no subclasses of that class can create a method of the same name that overrides that method. This ensures that when the method is called, it will always be the method marked final.
final public function methodName() {
// your statements here
}
Similarly, for classes, if a class is marked final, no subclasses can be created that extend that class.
package{
final public class ClassName {
// your statements here
}
}
Note: it is pointless to have methods marked as final in a class marked as final since that class cannot be extended. Since it cannot be extended, there would be no way for methods to be overridden as that only occurs within subclasses of the original class.
senocular
August 16th, 2006, 12:14 PM
If you're using MXMLC (the MXML and ActionScript 3 stand alone, command line compiler provided with the free Flex 2 SDK (http://www.adobe.com/products/flex/sdk/)) to compile your ActionScript 3 SWFs or use AS-only projects in Flex builder 2, you can use the SWF metadata tag to set common properties for your movie. The SWF metadata tag supports 4 properties
width
height
frameRate
backgroundColor
Example:
package {
[SWF(width="500", height="450", frameRate="24", backgroundColor="#FFFFFF")]
public class MyApp extends Sprite {
}
}
When compiled, the above makes a SWF 500x450 in size with a background color of white and a framerate of 24.
senocular
August 18th, 2006, 11:57 AM
ActionScript 3 introduces a new class to take the place of ActionScript 1 and ActionScript 2's addProperty method and __resolve handler for objects. This class is the Proxy Class (flash.utils.Proxy (http://livedocs.macromedia.com/flex/2/langref/flash/utils/Proxy.html)).
In ActionScript 1 and ActionScript 2:
addProperty() - used to dynamically add a getter/setter property for an object or class. This dynamically created a variable that was set and whose value was retrieved through functions passed into the addProperty call.
__resolve - a handler that, when defined for an object, would be called when a property or method was accessed that did not exist for that object. This let you capture unresolved references from an object and react accordingly
In ActionScript 3 you create a class that extends Proxy to take advantage of all its features. They include
Capturing property setting
Capturing property getting
Capturing property checking (if exists)
Capturing property deletion
Capturing method calls
Capturing decendant access
Capturing attribute checking
Handling property iteration
Though these features hold a lot of advange over what was available with AS1 and AS2, there are some drawbacks to using Proxy:
Instance typing is limited since classes need to extend Proxy; you tend to have to rely on interfaces
You cannot have Proxy classes that inherit from classes that don't already inherit from Proxy
Display objects cannot be Proxy classes
Proxy classes are generally used for variable container classes that need extra the flexibility.
The Proxy class will be covered in more detail in later tips
senocular
August 18th, 2006, 12:09 PM
The in operator (in operator (http://livedocs.macromedia.com/flex/2/langref/operators.html#in)) is a new operator in ActionScript 3 that is used to see if a value exists within an object. This is similar to hasOwnProperty but will also work for inherited values.
trace("PI" in Math); // true
trace("myProperty" in Math); // false
senocular
August 18th, 2006, 12:14 PM
getProperty and setProperty are methods used in Proxy classes that are used to manage property access. When a property not defined within a proxy instance is retrieved, getProperty is called to retrieve it. When set, setProperty is used to set it.
As with all methods of the Proxy class, getProperty and setProperty are defined within the flash_proxy namespace (flash.utils.flash_proxy) to prevent conflicts with public. When you override these methods within your own Proxy subclasses, you will want to be sure to use the flash_proxy namespace.
The following example, CustomObject, extends Proxy and uses getProperty and setProperty to manage dynamic properties set for its instances.
package {
import flash.utils.Proxy;
import flash.utils.flash_proxy;
dynamic public class CustomObject extends Proxy {
public var classProperty:String = "classProperty"; // generic class variable
private var customProperties:Object = new Object(); // store custom variables
public function CustomObject() {
}
// called when getting dynamic variables
override flash_proxy function getProperty(name:*):* {
if (name in customProperties) {
return customProperties[name];
}
return "Property does not exist";
}
// called when setting dynamic variables
override flash_proxy function setProperty(name:*, value:*):void {
customProperties[name] = "Property "+name+": "+value;
}
}
}
// usage example
var myObj:CustomObject = new CustomObject();
trace(myObj.foo); // Property does not exist
myObj.foo = "bar";
trace(myObj.foo); // Property foo: bar
trace(myObj.classProperty); // classProperty
myObj.classProperty = "bar";
trace(myObj.classProperty); // bar
Notice that when getting and setting the foo property, getProperty and setProperty are used to control its ultimate value which is stored within a customProperties defined for the class. Also, since classProperty is not a dynamic variables, instead being one defined for the class, getProperty and setProperty to not apply.
senocular
August 18th, 2006, 03:33 PM
In Flash 9 when you create MovieClip instance on the screen and give it an instance name, you are doing two things:
You're assigning the name property of the MovieClip instance to be the string equivalent to the instance name provided
You're creating a variable in the current timeline with the name of the instance name that references that MovieClip instance
Flash does this behind the scenes when you publish your SWF to help you manage your movie clips on the screen. It's important to note that this behavior (specifically #2) is not seen with ActionScript. For Example:
// my_mc is the instance name of a movie clip
// created on this timeline
trace(my_mc); // [object MovieClip]
trace(my_mc.name); // my_mc
// create a new movie clip via AS
// add it to my_mc
var another_mc:MovieClip = new MovieClip();
another_mc.name = "child_mc";
my_mc.addChild(another_mc);
// instance name not available in parent timeline
trace(another_mc); // [object MovieClip]
trace(my_mc.child_mc); // undefined
trace(my_mc.another_mc); // undefined
You can see that neither the instance name (name property) nor the variable to which the new MovieClip created with ActionScript was assigned is referencable through the movie clip in which it was added (my_mc). This is because another_mc was created and added to the timeline dynamically. Flash will only save instance names as variables for movie clips created on the timeline in Flash.
If you want to use an instance name to get a MovieClip (or any DisplayObject) instance from the timeline in which it exists, you can use getChildByName();
trace(my_mc.getChildByName("child_mc")); // [object MovieClip]);
This will work for all movie clips despite where or how they were located as long as they are within the timeline/movie clip from which getChildByName was used.
NiñoScript
August 18th, 2006, 11:07 PM
maybe you can do something like
my_mc.another_mc = new MovieClip();
my_mc.another_mc.name = "child_mc";
my_mc.addChild(my_mc.another_mc);
trace(another_mc); // [object MovieClip]
trace(my_mc.another_mc); // ???
(^thats a question^, i don't know if its that easy to make variables inside of movieclips)
senocular
August 19th, 2006, 12:28 PM
maybe you can do something like
You can assign the movie clip to the movie clip you place it in if you want. I was just showing that flash automatically does that with instances on the timeline.
snick
August 20th, 2006, 02:48 AM
The CustomDispatcher helper class above doesn't inherit from EventDispatcher but uses aggregation to obtain EventDispatcher functionality through an instance of EventDispatcher initialized in the constructor.
I was just wondering... if you were going to use a helper class anyway, why would you not just do this:
package test
{
import flash.events.Event;
public class Test
{
public function Test() {
var dispatcher:CustomDispatcher = new CustomDispatcher();
dispatcher.addEventListener("customEvent", handleEvent);
dispatcher.dispatchEvent(new Event("customEvent"));
}
private function handleEvent(event:Event):void {
trace(event.type); // "customEvent"
}
}
}
import flash.events.EventDispatcher;
class CustomDispatcher extends EventDispatcher
{
}
I'm just confused as to why one would want to abstract the EventDispatcher class in a helper. Is that so the helper could extend something else?
Nick
http://www.velloff.com
senocular
August 20th, 2006, 12:42 PM
I was just wondering... if you were going to use a helper class anyway, why would you not just do this:
...
I'm just confused as to why one would want to abstract the EventDispatcher class in a helper. Is that so the helper could extend something else?
It was just an example to show implementation. The helper class was used because MyDispatcher, as the application class, extends Sprite which already makes it an event dispatcher. To keep the example encapsulated in one file, I just used a helper class for the ED implementation.
senocular
August 21st, 2006, 12:42 AM
When working with E4X in ActionScript 3, you deal with 2 kinds of objects, XML (Top level XML (http://livedocs.macromedia.com/flex/2/langref/XML.html)) and XMLList (Top level XMLList (http://livedocs.macromedia.com/flex/2/langref/XMLList.html)), both of which are very similar in nature. The big difference between the two is that with XML you are dealing with one specific object (which could potentially contain any number of children) and with XMLList you are dealing with a collection of 1 or more objects. Consider the following:
// XML:
<foo>
<foo />
<foo />
<foo />
</foo>
// XMLList:
<foo />
<foo />
<foo />
Since you are dealing with one root node in the first example, it represents an XML object. In the second example, you have multiple nodes meaning you have an XMLList.
Unlike the old XML object (now XMLDocument) in previous versions of ActionScript, the XML and XMLList classes do not deal specifically with nodes. Though XML and XMLList can represent a collection of nodes, they can also represent other values such as attributes. Example:
var myXML:XML = <foo>
<foo bar="bar1" />
<foo bar="bar2" />
<foo bar="bar3" />
</foo>;
trace(myXML.foo.@bar.toXMLString());
/* Output:
bar1
bar2
bar3
*/
trace(myXML.foo.@bar is XMLList); // true
Note that attributes are always returned as XMLList instances, even if one value is returned. Consider getting the bar attribute value from the first foo node:
trace(myXML.foo[0].@bar is XMLList); // true
Though one element is returned, it is retuned as an XMLList. You can get the XML value of that attribute by returning the first value off of that list:
trace(myXML.foo[0].@bar[0] is XML); // true
The same applies to XML
var myXML:XML = <foo>
<foo />
</foo>;
trace(myXML.foo is XMLList); // true
The XML operations that can return more than one value (nodes, attributes, etc) will return XMLList instances.
senocular
August 22nd, 2006, 07:32 AM
ActionScript 3 allows you to define constants for your classes. Constants are special kinds of variables that can be defined only once. Typically you'll see constants defined with capital letters. Event.ENTER_FRAME, for example, is a constant.
You define constants in AS3 using the const keyword (const keyword (http://livedocs.macromedia.com/flex/2/langref/statements.html#const)). This is used in place of what would otherwise be var (var keyword (http://livedocs.macromedia.com/flex/2/langref/statements.html#var)).
package {
import flash.display.Sprite;
public class MyClass extends Sprite {
public const MY_CONSTANT:String = "constant";
public function MyClass () {
}
}
}
Though constants can't be redefined, if they are object values, methods can still be called that otherwise modify that value. If the constant is an array, for example, Array.push() can be used to add additional elements to that array. As a constant, it just means that the actual value of the variable itself can't be changed. That is to say that array variable will always be that same array and couldn't be defined as another or a new array.
package {
import flash.display.Sprite;
public class MyClass extends Sprite {
public const MY_CONSTANT:Array = new Array(1,2,3);
public function MyClass () {
MY_CONSTANT.push(4); // ok
MY_CONSTANT = new Array(5,6,7); // error
}
}
}
Deviant1853
August 22nd, 2006, 07:55 AM
This all works fine aslong as you dont have strict mode on. If you have the strict mode on it will have a compile error because the constant isnt set at the class initialization. It doesnt even allow it in the constructor funnily enough. The simple answer is to just work with strict mode off :)
senocular
August 22nd, 2006, 08:00 AM
This all works fine aslong as you dont have strict mode on. If you have the strict mode on it will have a compile error because the constant isnt set at the class initialization. It doesnt even allow it in the constructor funnily enough. The simple answer is to just work with strict mode off :)
Actually, I might be wrong on that one. I should do some testing before commiting to that behavior (I might be thinking of something else).
Ok, doesnt look like it enforces constants at all without strict, and AS3 isnt happy defining constants outside of the declaration so I'm going to keep it there - thanks for pointing that out Deviant1853 :)
Deviant1853
August 22nd, 2006, 09:21 AM
Any time Senocular :)
senocular
August 24th, 2006, 11:01 AM
ActionScript 3 no longer has a duplicateMovieClip method for MovieClip instances (or any DisplayObject instances). Instead, it's suggested that you just create a new instance of the display object you wish to duplicate using its constructor. This, however, is not the same as duplicateMovieClip, and, really, is more like using AS1 and AS2's attachMovieClip. For a more accurate representation of duplicateMovieClip in AS3, consider the following function:
package com.senocular.display {
import flash.display.DisplayObject;
import flash.geom.Rectangle;
/**
* duplicateDisplayObject
* creates a duplicate of the DisplayObject passed.
* similar to duplicateMovieClip in AVM1
* @param target the display object to duplicate
* @param autoAdd if true, adds the duplicate to the display list
* in which target was located
* @return a duplicate instance of target
*/
public function duplicateDisplayObject(target:DisplayObject, autoAdd:Boolean = false):DisplayObject {
// create duplicate
var targetClass:Class = Object(target).constructor;
var duplicate:DisplayObject = new targetClass();
// duplicate properties
duplicate.transform = target.transform;
duplicate.filters = target.filters;
duplicate.cacheAsBitmap = target.cacheAsBitmap;
duplicate.opaqueBackground = target.opaqueBackground;
if (target.scale9Grid) {
var rect:Rectangle = target.scale9Grid;
// WAS Flash 9 bug where returned scale9Grid is 20x larger than assigned
// rect.x /= 20, rect.y /= 20, rect.width /= 20, rect.height /= 20;
duplicate.scale9Grid = rect;
}
// add to target parent's display list
// if autoAdd was provided as true
if (autoAdd && target.parent) {
target.parent.addChild(duplicate);
}
return duplicate;
}
}
As you can see, this function (duplicateDisplayObject) takes care of making sure a duplicated instance also retains all the information retained by duplicateMovieClip such as transformation, filters, chaching as bitmap, etc.
Note: There is currently a bug in Flash Player 9 that causes incorrect values to be returned from the scale9Grid property of display objects. This function compensates for that but may need to be edited should this bug be fixed.
Usage:
import com.senocular.display.duplicateDisplayObject;
// create duplicate and assign to newInstance variable
// using true for autoAdd automatically adds the newInstance
// into the display list where myOldSprite is located
var newInstance:Sprite = duplicateDisplayObject(myOldSprite, true);
newInstance.x += 100; // shift to see duplicate
The only thing duplicateMovieClip does that this does not is copy dynamic drawing information. Currently, the graphics object in display objects cannot be duplicated so there is no way to obtain that information for duplicates in duplicateDisplayObject.
Deviant1853
August 24th, 2006, 11:42 AM
I am quite supprised that Adobe didnt create a non-final method clone() on Object to be overridden for each subclass. I cant see any reason why they wouldnt want to do this :S
senocular
August 24th, 2006, 12:28 PM
The callProperty method of the Proxy class lets you define an action for methods called from Proxy instances. When a method not defined within a proxy instance is called, callProperty is run passing the name of the method called along with an array of the arguments used.
As with all methods of the Proxy class, callProperty is defined within the flash_proxy namespace (flash.utils.flash_proxy) to prevent conflicts with public. When you override these methods within your own Proxy subclasses, you will want to be sure to use the flash_proxy namespace.
The following example, CustomObject, extends Proxy and uses callProperty to manage dynamic methods called for its instances.
package {
import flash.utils.Proxy;
import flash.utils.flash_proxy;
dynamic public class CustomObject extends Proxy {
private var variables:Object = new Object(); // stores variables
public function CustomObject() {
}
// called when calling dynamic methods
override flash_proxy function callProperty(name:*, ... args):* {
// convert name into string
name = String(name);
var callType:String = name.slice(0,3); // get or set
var callVariable:String = name.slice(3); // variable name behind get or set
switch(callType) {
case 'get':
// if get, get from variables object if exists
if (callVariable in variables) {
return variables[callVariable];
}
return null;
case 'set':
// if set assign to variables object
variables[callVariable] = args[0];
}
}
}
}
This example uses callProperty to accept generic get and set methods to get and set dynamic "variables" which are stored in the variables object.
// usage example
var myObj:CustomObject = new CustomObject();
trace(myObj.getMyVar()); // null
myObj.setMyVar("foo");
trace(myObj.getMyVar()); // foo
myObj.setMyVar("bar");
trace(myObj.getMyVar()); // bar
trace(myObj.MyVar); // doesnt exist (get property error)
at first getMyVar returns null since "MyVar" was not yet set (using setMyVar). After being set, getMyVar returns the value it was given through getMyVar.
ignitrix
August 24th, 2006, 12:44 PM
Nice work on the duplicateDisplayObject Senocular. I started doing some tests with it... if the constructor of the DisplayObject you are creating has 1 or more required parameters, it fails. Other than that, it seems to work excellent--even with complex Sprites.
~JC
senocular
August 24th, 2006, 12:45 PM
Though you can't directly copy graphics created in Sprite and Shape instances' graphics property in ActionScript 3, you can use the Proxy class to create a substitute graphics-like property that will be able to record all methods you use with graphics. Consider the following class, GraphicsCopy:
package com.senocular.display {
import flash.display.Graphics;
import flash.utils.flash_proxy;
import flash.utils.Proxy;
/**
* a graphics property substitute for DisplayObject instances
* that can be duplicated
*/
public class GraphicsCopy extends Proxy {
private var _graphics:Graphics;
private var history:Array = new Array();
/**
* graphics instance to recieve
* drawing commands given to this GraphicsCopy instance
*/
public function get graphics():Graphics {
return _graphics;
}
public function set graphics(g:Graphics):void {
_graphics = g;
// apply the graphics history to Graphics instance
copy(this);
}
/**
* constructor
* @param graphics Optional Graphics instance to recieve
* drawing commands given to this GraphicsCopy instance
*/
public function GraphicsCopy(graphics:Graphics = null) {
_graphics = graphics;
}
/**
* copies the graphics of a GraphicsCopy into this GraphicsCopy
*/
public function copy(graphicsCopy:GraphicsCopy):void {
var hist:Array = graphicsCopy.history;
history = hist.slice();
if (_graphics) {
var i:int;
var n:int = hist.length;
_graphics.clear();
for (i=0; i<n; i += 2) {
_graphics[hist[i]].apply(_graphics, hist[i + 1]);
}
}
}
// PROXY overrides
override flash_proxy function callProperty(methodName:*, ... args):* {
methodName = String(methodName);
switch(methodName) {
case "clear":
history.length = 0;
break;
default:
history.push(methodName, args);
}
if (_graphics && methodName in _graphics) {
return _graphics[methodName].apply(_graphics, args);
}
}
}
}
Instead of using the graphics property for your sprites or shapes, you can use a GraphicsCopy instance that references that object's graphics property. Then, every method used on the GraphicsCopy is recorded by GraphicsCopy but still applied to graphics thanks to Proxy and its callProperty method. Example:
// MyClass.as Shape class using GraphicsCopy
package {
import flash.display.Shape;
import com.senocular.display.GraphicsCopy;
class MyShape extends Shape {
// graphicsCopy property
private var _graphicsCopy:GraphicsCopy;
public function get graphicsCopy():GraphicsCopy {
return _graphicsCopy;
}
// constructor
function MyShape(){
_graphicsCopy = new GraphicsCopy(graphics);
}
}
}
// in Flash
// draw shape 1
var shape1:MyShape = new MyShape();
shape1.graphicsCopy.beginFill(0xFF80);
shape1.graphicsCopy.lineStyle(2, 0);
shape1.graphicsCopy.drawRect(0, 0, 50, 50);
// draw shape2 using shape1's copied drawing
var shape2:MyShape = new MyShape();
shape2.graphicsCopy.copy(shape1.graphicsCopy);
// add to display list
addChild(shape1);
addChild(shape2);
shape2.x += 100;
Running this will show to green squares, the first drawn using GraphicsCopy (shape1) and the other duplicated from GraphicsCopy (into shape2's GraphicsCopy) using the copy method of that class.
Note: Since Proxy classes cannot inherit from Graphics (its abstract anyway), GraphicsCopy instances do not have a Graphics class type associated with them so will not work with methods expecting a Graphics instance. I don't believe there are any inherit methods that use Graphics parameters, but you might make your own or have functions/methods from other sources that do. Using a type of Object or * would allow both Graphics and GraphicsCopy instances to work in that case.
senocular
August 24th, 2006, 12:53 PM
Nice work on the duplicateDisplayObject Senocular. I started doing some tests with it... if the constructor of the DisplayObject you are creating has 1 or more required parameters, it fails. Other than that, it seems to work excellent--even with complex Sprites.
~JC
Yeah, for the sake of simplicity I went with the assumption that display objects used would follow with the consistency of Flash display objects and require no constructor parameters :)
ignitrix
August 24th, 2006, 04:34 PM
...The Stage class (flash.display.Stage (http://livedocs.macromedia.com/flex/2/langref/flash/display/Stage.html)) is the class assigned to the stage object which is accessible from your main movie sprite/movie clip (or others within the same security sandbox) using the stage property... Is there anyway to give a static, non-DisplayObject class access to the stage? I tried many different workarounds, but could not figure out how to give it access to the stage without making it a non-static object...
Deviant1853
August 24th, 2006, 05:22 PM
Is there anyway to give a static, non-DisplayObject class access to the stage? I tried many different workarounds, but could not figure out how to give it access to the stage without making it a non-static object...
I have got around this problem by creating a singleton MyStage class. It requies on the root of your movie to use: MyStage.init(stage); but other than that it works pretty much how you want. It gives static access to the stage.
/**
My Stage
version 1.0.0
Created by Matthew Lloyd
http://www.Matt-Lloyd.co.uk/
This is release under a Creative Commons license.
More information can be found here:
http://creativecommons.org/licenses/by-nc-sa/2.0/uk/
----------------------------------------------------------------
*/
package com.deviant
{
import flash.display.*;
public class MyStage extends Sprite
{
public static var instance:MyStage = null;
public function MyStage()
{}
public static function getInstance():MyStage
{
if(instance == null)
instance = new MyStage();
return instance;
}
public static function getStage():Stage
{
return getInstance().stage;
}
public static function init(stg:Stage):void
{
stg.addChild(MyStage.getInstance());
stg.scaleMode = StageScaleMode.NO_SCALE;
stg.align = StageAlign.TOP_LEFT;
}
}
}
The scale mode and the alignment arent nessicary they are just very useful for my needs.
ignitrix
August 24th, 2006, 05:38 PM
This worked excellent! Thanks Deviant
icio
August 24th, 2006, 05:51 PM
I tried this code:
package {
import flash.display.Sprite;
public class stage_test extends Sprite {
public function stage_test() {
var myClass:MyClass = new MyClass();
}
}
}
import flash.display.Stage;
import flash.display.Sprite;
class MyClass {
public var stage:Stage = (new Sprite()).stage;
public function MyClass():void {
trace(stage);
}
}
But it didn't work. It would appear that the `stage` property of a Sprite isn't set when the Sprite is created. Where does the value of the `stage` property come from, then ?
Thanks
senocular
August 24th, 2006, 06:15 PM
I tried this code:
...
But it didn't work. It would appear that the `stage` property of a Sprite isn't set when the Sprite is created. Where does the value of the `stage` property come from, then ?
Thanks
display objects only have access to the stage when they are within a visible display list (or, rather, a display list attached to the stage). To be able to have a valid reference to the stage from a sprite, you'd have to use addChild to add it to a container - either the stage itself or some other container attached to it.
A suggestion I've used before was have your application or document class extend a custom subclass of sprite rather than sprite itself. This class could then have that static stage reference which would instantly available since the application/document class is inherently a child of the stage when the SWF starts.
On a similar topic, I have a class allowing you to detect when the stage property is available for a display object (i.e. when it has been added to a visible display list) but I was saving that for another tip of the day. If anyone is interested, I can post that one next.
Enemу
August 24th, 2006, 08:03 PM
Hi, Sen and everyone :)
I have a tip request: Singleton in AS3
private is no longer available as constructor's attribute, it makes me just unhappy :bored:
I've found two workarounds for this, here (http://www.flashcoder.net/blog/?p=81) about singletons in general and here (http://www.gskinner.com/blog/archives/2006/07/as3_singletons.html)
more concrete.
But, there are a lot of discussions and comments about what way is more hackish or useful. I'm confused.
The question: Singleton in AS3: best practice, the most common and easy to use (and understand) way, if any...
Thanks!
senocular
August 24th, 2006, 08:42 PM
Hi, Sen and everyone :)
I have a tip request: Singleton in AS3
private is no longer available as constructor's attribute, it makes me just unhappy :bored:
I've found two workarounds for this, here (http://www.flashcoder.net/blog/?p=81) about singletons in general and here (http://www.gskinner.com/blog/archives/2006/07/as3_singletons.html)
more concrete.
But, there are a lot of discussions and comments about what way is more hackish or useful. I'm confused.
The question: Singleton in AS3: best practice, the most common and easy to use (and understand) way, if any...
Thanks!
gskinners post is your best approach (private variable usage prefered over helper class).
Enemу
August 25th, 2006, 08:41 AM
gskinners post is your best approach (private variable usage prefered over helper class).
You mean throwing an error if allowInstantiation == false ?
But what about compile time errors?
senocular
August 27th, 2006, 12:37 PM
The TextField class (flash.text.TextField (http://livedocs.macromedia.com/flex/2/langref/flash/text/TextField.html)) in ActionScript 3 has a new method called appendText (flash.text.TextField.appendText() (http://livedocs.macromedia.com/flex/2/langref/flash/text/TextField.html#appendText())). This method allows you to add additional text onto the end of the text contained within the current text field. This should be used in place of TextField.text += newText since appendText is faster and more efficient.
var my_tf = new TextField();
my_tf.text = "Hello";
my_tf.appendText(" world!"); // my_tf.text == "Hello world!"
senocular
August 28th, 2006, 10:14 PM
ActionScript 3 continues to allow you to include code located in external files within your scripts at compile time using the include directive (include directive (http://livedocs.macromedia.com/flex/2/langref/statements.html#include)).
include "scripts/myscript.as"
Notice that the include directive in ActionScript 3 does not contain a # before "include" as it did in ActionScript 1 and 2.
Note: You should keep as files included in your ActionScript outside of your class path(s) so that they are not accidentally interpreted as classes.
senocular
August 28th, 2006, 10:31 PM
In ActionScript 1 and ActionScript 2, it was possible to define a variable twice in the same scope without error. For example:
// ActionScript 1 and 2
var i:Number = 1;
var i:String = 2;
This is no longer allowed in ActionScript 3. In ActionScript 3, once you define a variable for a scope, that variable is set for that scope and cannot be redefined as a new variable or as a new type. This, of course, doesn't mean you cannot change the value of a variable. It just means, essentially, that the var keyword should only be used once to declare/define any one variable given any scope.
// ActionScript 3
var i:Number = 1;
var i:String = 2; // ERROR: duplicate definition or undefined property
For ActionScript 3, if you need a new type, you will need to create a new variable to contain that type. Also, if you have situations where var was used twice in, for instance, two separate if blocks, you will want to first declare the variable outside the blocks and assign them within.
// ActionScript 3 INCORRECT
// (but works in AS1 and AS2)
if (my_btn.enabled == true) {
var returnValue:Number = 1;
}else{
var returnValue:Number = 0;
}
if (provideAsString == true) {
var returnValue:String = "1";
}else{
var returnValue:String = "0";
}
The correct way to do this for AS3 is:
// ActionScript 3 CORRECT
var returnValueNum:Number;
var returnValueStr:String;
if (my_btn.enabled == true) {
returnValueNum = 1;
}else{
returnValueNum = 0;
}
if (provideAsString == true) {
returnValueStr = "1";
}else{
returnValueStr = "0";
}
Notice that two different variables were used instead of 1 since they have different types. Also the variables were declared once outside of the if blocks instead of twice within. Alternatively, you could also use one variable with the * type.
// ActionScript 3 ALSO OK
var returnValue:*
if (my_btn.enabled == true) {
returnValue = 1;
}else{
returnValue = 0;
}
if (provideAsString == true) {
returnValue = "1";
}else{
returnValue = "0";
}
senocular
August 30th, 2006, 11:59 AM
In ActionScript 1 and 2, instances with button events like onPress and onRollOver intercepts control of all button events that occurred over that instance. This means that if there was overlap between two instances with button events, the events occuring within the overlapping area would always go to the instance on top and never on the one below since those events were intercepted by the overlapping instance. Events to the underlying instance could be accessible in those overlapping areas only if all button events were removed from the topmost instance.
In ActionScript 3, the same concept applies, but the behavior is no longer dependant on button events like onPress since events are now handled exclusively with EventDispatcher. Instead, a property is used: mouseEnabled (flash.display.InteractiveObject.mouseEnabled (http://livedocs.macromedia.com/flex/2/langref/flash/display/InteractiveObject.html#mouseEnabled)).
The mouseEnabled property actually kind of serves two purposes. First it prevents (true, default) or allows (false) mouse events going to instances below the topmost instance. It also enables (true, default) or disables (false) mouse instances from being dispatched to the that instance. It acts very much like the enabled property of AS1 and AS2.
Notice the behavior of the following AS3 script. The topmost circle will be clicked when it is enabled. When not, events will go to the underlying circle.
function createCircle(name:String = ""):DisplayObject {
var circle:Sprite = new Sprite();
circle.name = name;
circle.graphics.lineStyle(0);
circle.graphics.beginFill(0xFF8080);
circle.graphics.drawCircle(50, 50, 50);
return circle;
}
circle1 = createCircle("circle 1");
circle2 = createCircle("circle 2");
circle2.x += 25;
addChild(circle1);
addChild(circle2);
circle1.addEventListener(MouseEvent.MOUSE_DOWN, click);
circle2.addEventListener(MouseEvent.MOUSE_DOWN, click);
function click(e) {
trace(e.target.name + " clicked."); // trace name
// disable and re-enable circle2 with each click
circle2.mouseEnabled = !circle2.mouseEnabled;
}
Keep in mind that mouseEnabled is true by default. This means that even without button (or any) events associated with a display object instance, it will block events to those instances below it. If you don't want that to happen, you will have to appropriately set mouseEnabled = false where needed.
Enemу
August 30th, 2006, 03:01 PM
since appendText is faster and more efficient.
I'm just curious, what makes it faster?
Any ideas about what implementation brings this improvement are welcome.
senocular
August 30th, 2006, 03:34 PM
I'm just curious, what makes it faster?
Any ideas about what implementation brings this improvement are welcome.
Its an internal method that doesn't rely on the get/set of the text property. Essentially any single method used to replace += will be much more efficient.
senocular
September 3rd, 2006, 12:19 PM
The mouseChildren property (flash.display.DisplayObjectContainer.mouseChildre n (http://livedocs.macromedia.com/flex/2/langref/flash/display/DisplayObjectContainer.html#mouseChildren)) is a new property that allows you to essentially control the mouseEnabled of all the children of a sprite (or other display object container). This allows the parent sprite to have its own events without having to worry about interference with events coming from its children.
spriteInstance.mouseChildren = false;
Though ActionScript 3 now has a SimpleButton class (flash.display.SimpleButton (http://livedocs.macromedia.com/flex/2/langref/flash/display/SimpleButton.html)). this property would play an important role in making custom buttons with the MovieClip or Sprite classes. Consider what would happen if you created a rollover event that caused a sprite or movie clip-based button to remove its current graphics and create new ones for a rollover state. With the children of that sprite capable of receiving mouse events, events would fire for the children within the button - events which would propagate to the main sprite. This could mean duplicate events as well as making the event target for those events the children of the button instead of the button itself. Setting mouseChildren to false you can prevent that from happening.
The easiest demonstration is a simple click of a sprite containing another sprite. Change the value of mouseChildren between true and false and notice which sprite is designated as the target of the event:
// main button
var spriteButton:Sprite = new Sprite();
spriteButton.name = "spriteButton";
spriteButton.mouseChildren = true;
// graphics
var spriteGraphics:Sprite = new Sprite();
spriteGraphics.name = "spriteGraphics";
spriteGraphics.graphics.beginFill(0x4080A0);
spriteGraphics.graphics.drawCircle(50, 50, 25);
// add to display list
spriteButton.addChild(spriteGraphics);
addChild(spriteButton);
// events
spriteButton.addEventListener(MouseEvent.CLICK, click);
function click(evt:MouseEvent):void {
trace(evt.target.name);
}
When true (default), the sprite within the button that was clicked is marked as the target. When false, the button sprite itself is the target - something which is more desirable in this case.
mouseChildren = true; output
spriteButton
mouseChildren = false; output
spriteGraphics
senocular
September 3rd, 2006, 12:38 PM
The InteractiveObject class (flash.display.InteractiveObject (http://livedocs.macromedia.com/flex/2/langref/flash/display/InteractiveObject.html)) in ActionScript 3 has both rollOver and rollOut events as well as mouseOver and mouseOut events.
Both sets of events determine when a mouse enters or leaves the graphics area of an interactive object. The rollOver and mouseOver events fire when the mouse comes in contact with an interactive object, while rollOut and mouseOut occur when the mouse leaves the interactive object.
Where they differ is with their interaction with interactive object children. The roll events (rollOver and rollOut) simplify the process and prevent interference with child events. Essentially, this is the same as using mouseOver and mouseOut with mouseEnabled set to false. mouseOver and mouseOut with mouseEnabled provide a parent sprite with events from its children. rollOver and rollOut keeps the events on the parent object.
Example: toggle between the use of the ROLL_OVER & ROLL_OUT and MOUSE_OVER and MOUSE_OUT events.
// main button
var spriteButton:Sprite = new Sprite();
spriteButton.name = "spriteButton";
// graphics
var spriteGraphics1:Sprite = createGraphics("spriteGraphics1", 0xFF, 50, 50, 25);
var spriteGraphics2:Sprite = createGraphics("spriteGraphics2", 0x80, 50, 50, 15);
// add to display list
spriteButton.addChild(spriteGraphics1);
spriteButton.addChild(spriteGraphics2);
addChild(spriteButton);
// events
spriteButton.addEventListener(MouseEvent.ROLL_OVER , over);
spriteButton.addEventListener(MouseEvent.ROLL_OUT, out);
//~spriteButton.addEventListener(MouseEvent.MOUSE_OV ER, over);
//~spriteButton.addEventListener(MouseEvent.MOUSE_OU T, out);
function over(evt:MouseEvent):void {
trace("over: " + evt.target.name);
}
function out(evt:MouseEvent):void {
trace("out: " + evt.target.name);
}
// create circles
function createGraphics(name:String, color:uint, x:Number, y:Number, radius:Number):Sprite {
var circle:Sprite = new Sprite();
circle.name = name;
circle.graphics.beginFill(color);
circle.graphics.drawCircle(x, y, radius);
return circle;
}
You'll notice that with rollOver and rollOut, spriteButton is the target and doesn't receieve events from its children while the opposite is true for mouseOver and mouseOut.
rollOver and rollOut output
over: spriteButton
out: spriteButton
over: spriteButton
out: spriteButton
mouseOver and mouseOut output
over: spriteGraphics1
out: spriteGraphics1
over: spriteGraphics2
out: spriteGraphics2
over: spriteGraphics1
out: spriteGraphics1
senocular
September 3rd, 2006, 12:47 PM
With ActionScript 3, you can easily determine if a sprite or other display object container contains any otherr display object using the contains method (flash.display.DisplayObjectContainer.contains() (http://livedocs.macromedia.com/flex/2/langref/flash/display/DisplayObjectContainer.html#contains())). The contains method returns true if the display object passed is within the target display object container or any of its children.
Example:
var king:Sprite = new Sprite();
var queen:Sprite = new Sprite();
var jack:Sprite = new Sprite();
var joker:Sprite = new Sprite();
queen.addChild(jack);
king.addChild(queen);
addChild(king);
addChild(joker);
trace(king.contains(queen)); // true
trace(king.contains(jack)); // true
trace(king.contains(joker)); // false
If you just want to see if the instance is within the target only and not any of its children, just compare the target with the parent property of the instance you're checking for.
trace(queen.parent == king); // true
trace(jack.parent == king); // false
senocular
September 3rd, 2006, 01:14 PM
When dealing with display objects in ActionScript 3, its important to remember that they can exist when not actually within a display list or visible on the screen. By removing objects from a display list, you do not stop events from occuring within that object (save for mouse events, obviously). This means that enterFrame events will continue to run for display objects even when removed from the screen. This is contrary to the behavior in ActionScript 1 and 2 where removal from the screen also meant removal from the entire movie, killing off all events related to it.
If you want to events like enterFrame to stop when you remove a display object from a display list, you'll want to do that manually, cleaning up after yourself when through with your display objects. To make this easier, you can use the removed event to determine when the display object has been removed from its parent. You can even use the added event to determin when its been added (thereby letting you reinstate an enterFrame listener, for example).
Example:
var sprite:Sprite = new Sprite();
sprite.addEventListener(Event.ADDED, addEnterFrame);
sprite.addEventListener(Event.REMOVED, removeEnterFrame);
// add/remove enter frame event
function addEnterFrame(evt:Event):void {
trace("added");
sprite.addEventListener(Event.ENTER_FRAME, enterFrame);
}
function removeEnterFrame(evt:Event):void {
trace("removed");
sprite.removeEventListener(Event.ENTER_FRAME, enterFrame);
}
function enterFrame(evt:Event):void {
trace("Time: " + getTimer());
}
// add and remove by clicking
stage.addEventListener(MouseEvent.CLICK, addRemove);
function addRemove(evt:Event):void {
if (this.contains(sprite)) {
this.removeChild(sprite);
}else{
this.addChild(sprite);
}
}
If removed wasnt used to cleanup the enterFrame event listener for the sprite when it was removed from the current display list, it would continue to run even though the sprite was removed from the screen.
output
added
Time: 813
Time: 927
removed
added
Time: 2509
Time: 2597
removed
senocular
September 3rd, 2006, 01:20 PM
The added and removed events in ActionScript 3 let you detect when a display object is added to or removed from another display object container. These events, however, only work for the immediate parent of that display object. This means a sprite instance can be removed from the stage and not know it if its parent was removed from the stage and it continues to exist within the parent. Currently, there is no way to detect when this happens with Flash Player 9.0. The following StageDetection class (com.senocular.events.StageDetection (http://www.senocular.com/flash/actionscript.php?file=ActionScript_3.0/com/senocular/events/StageDetection.as)), can be used to do so, however:
package com.senocular.events {
import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.utils.Dictionary;
/**
* StageDetection
* Lets a DisplayObject know when its been added to
* a display list attached to the stage.
*
* Usage:
* // used in the constructor where addedToStage and removedFromStage
* // are event handler methods
* var stageDetect:StageDetection = new StageDetection(this);
* stageDetect.addEventListener(StageDetection.ADDED_ TO_STAGE, addedToStage);
* stageDetect.addEventListener(StageDetection.REMOVE D_FROM_STAGE, removedFromStage);
*/
public class StageDetection extends EventDispatcher {
protected var target:DisplayObject;
protected var parents:Dictionary;
protected var detect:String;
public static const ADDED_TO_STAGE:String = "addedToStage";
public static const REMOVED_FROM_STAGE:String = "removedFromStage";
/**
* Constructor
*/
public function StageDetection(targetObject:DisplayObject) {
target = targetObject;
// determine whether need to detect for added or removed
detect = (target.stage == null) ? Event.ADDED : Event.REMOVED;
// update parent listeners for detect events
updateListeners();
}
/**
* updates listeners from which ADDED and REMOVED events are to be received
*/
protected function updateListeners(newDetect:String = null):void {
// cleanup old listeners in parents
if (parents) {
for (var key:Object in parents) {
key.removeEventListener(detect, stageCheck, false);
}
}
// new event to detect if given
if (newDetect) detect = newDetect;
// set up detect event with current parents
parents = new Dictionary(true);
var parent:DisplayObject = target;
while (parent) {
parent.addEventListener(detect, stageCheck, false, 0, true);
parents[parent] = true;
parent = parent.parent;
}
}
/**
* event handler for ADDED and REMOVED events checking for stage access
*/
protected function stageCheck(evt:Event):void {
// only check for originating object
if (evt.target != evt.currentTarget) return;
// evt.type either ADDED or REMOVED
switch(evt.type) {
// parent added to another display object
case Event.ADDED:
// stage available, added to stage
if (target.stage != null) {
// added to stage, dispatch event, update
dispatchEvent(new Event(ADDED_TO_STAGE));
updateListeners(Event.REMOVED);
// stage inaccessible, added to some other display object not on stage
} else {
// display list has changed, update parent listeners
updateListeners();
}
break;
// parent removed from stage
case Event.REMOVED:
// removed from stage, dispatch event, update
dispatchEvent(new Event(REMOVED_FROM_STAGE));
updateListeners(Event.ADDED);
break;
}
}
}
}
Note: As of Flash Player 9.0.28.0, Event.ADDED_TO_STAGE ("addedToStage"), and Event.REMOVED_FROM_STAGE ("removedFromStage") are built into the player.
senocular
September 3rd, 2006, 02:02 PM
Along with event propagation in ActionScript 3 comes different phases of events with display objects. With propagation, you have events being propagated from display objects to other display objects, such as mouse click events being propagated from children to their parents. This lets clicks within children objects to be recognized by parents (since children make up the contents of their parents, its only natural for the parent to also have those same events). The phases of such an event represent the progression of the event as it makes its way through the parent and child objects.
Events actually start with parent objects (phase 1: capturing), starting with the top most parent (stage) and making its way down to the child where the event originated (phase 2: at target). Then after reaching the child it makes its way back up through all the parents again (phase 3: bubbling).
Phase 1: Capturing
event
+---------|----+
| parent | |
| +------V-+ |
| |child | |
| | | |
| +--------+ |
+--------------+
Phase 2: At Target
+--------------+
| parent |
| +------ -+ |
| |child | |
| |event X | |
| +--------+ |
+--------------+
Phase 3: Bubbling
+---------^----+
| parent | |
| +------|-+ |
| |child | | |
| | event| | |
| +--------+ |
+--------------+
The default listening behavior for addEventListener is to listen for both phases 2 and 3, the at target and bubbling phases. This lets your listener recieves events the target object recieves as well as all of those that bubble up from its children. Note: the bubbling phase does not include the event target, but since addEvent listener listens to both phases by default, it includes the target (at phase) with its default bubbling listening.
If you would want to listen for the capturing phase, addEventListener provides a third argument that allows you to do so.
var useCapture:Boolean = true;
target.addEventListener("event", listener, useCapture);
This, instead, allows a listener to receive events during the capture phase of an event. Unlike when not using capture (default behavior of addEventListener), using capture does not allow the listener function to be called when the event reaches the target at the at target phase. It only listens for the capturing phase.
To listen to all phases, you would use addEventListener twice
target.addEventListener("event", listener, true); // capturing
target.addEventListener("event", listener, false); // at target and bubbling
senocular
September 3rd, 2006, 02:10 PM
Sorry about the delay from before. I'll crank out a few more to keep myself ahead (though time will probably catch up quickly)
AdamSchroeder
September 3rd, 2006, 02:20 PM
These are great tips Senocular! Thank you so much for taking the time to write them and explain them.
I was wondering if you give a tip on the best way to capture the onMouseReleaseOutside event that existed in AS2.0 but no longer exist in AS3.0.
It would fit right in with your current tips explaining how the event system works.
senocular
September 3rd, 2006, 02:25 PM
Event listener functions in ActionScript 3 can dermine what phase they're being called from using the Event object (flash.events.Event (http://livedocs.macromedia.com/flex/2/langref/flash/events/Event.html)) that gets passed into function during the event. Each Event instance contains an eventPhase property that relates to the current phase of the event.
The eventPhase property is an integer value representing the phase. These values are contained as static properties of the EventPhase class (flash.events.EventPhase (http://livedocs.macromedia.com/flex/2/langref/flash/events/EventPhase.html)). They are as follows:
EventPhase.CAPTURING_PHASE EventPhase.AT_TARGET EventPhase.BUBBLING_PHASE
Example:
var circle:Sprite = new Sprite();
circle.graphics.beginFill(0x4080A0);
circle.graphics.drawCircle(50, 50, 25);
addChild(circle);
circle.addEventListener(MouseEvent.CLICK, clickCircle);
circle.addEventListener(MouseEvent.CLICK, clickCircle, true);
stage.addEventListener(MouseEvent.CLICK, clickStage);
stage.addEventListener(MouseEvent.CLICK, clickStage, true);
function clickCircle(evt:MouseEvent):void {
trace("clickCircle: " + getPhaseName(evt.eventPhase));
}
function clickStage(evt:MouseEvent):void {
trace("clickStage: " + getPhaseName(evt.eventPhase));
}
function getPhaseName(phase:int):String {
switch(phase) {
case EventPhase.CAPTURING_PHASE:
return "Capturing Phase";
case EventPhase.AT_TARGET:
return "At Target Phase";
case EventPhase.BUBBLING_PHASE:
return "Bubbling Phase";
}
return "Error: No Phase Detected";
}
Clicking around on the circle you can see the different phases as they occur within the movie. Note that the using capturing with addEventListener on the circle does nothing in this example since the circle has no children that would allow an event to pass through the circle for a capture phase.
clicking on circle output
clickStage: Capturing Phase
clickCircle: At Target Phase
clickStage: Bubbling Phase
clicking on stage output
clickStage: At Target Phase
senocular
September 3rd, 2006, 02:25 PM
These are great tips Senocular! Thank you so much for taking the time to write them and explain them.
I was wondering if you give a tip on the best way to capture the onMouseReleaseOutside event that existed in AS2.0 but no longer exist in AS3.0.
It would fit right in with your current tips explaining how the event system works.
Yes, I'm working up to that one ;)
senocular
September 3rd, 2006, 02:56 PM
If you want to prevent an event from propagating further, you can stop it from doing so within an event listener using stopPropagation() (flash.events.Event.stopPropagation() (http://livedocs.macromedia.com/flex/2/langref/flash/events/Event.html#stopPropagation())) or stopImmediatePropagation() (flash.events.Event.stopImmediatePropagation() (http://livedocs.macromedia.com/flex/2/langref/flash/events/Event.html#stopImmediatePropagation())). These methods are called from the Event objects passed into event listeners and essentially stop the event from happening - at least past that point.
stopPropagation prevents any objects beyond the current from recieving the event, and this can be within any phase of the event. stopImmediatePropagation does the same but also takes the extra step of preventing additional events within the current target receiving the event from happening too. So where as stopPropagation would prevent sprite A's parent from receiving the event, stopImmediatePropagation would prevent sprite A's parent as well as any other listeners listening to sprite A from receiving the event.
Example: toggle between using stopPropagation and stopImmediatePropagation
var circle:Sprite = new Sprite();
circle.graphics.beginFill(0x4080A0);
circle.graphics.drawCircle(50, 50, 25);
addChild(circle);
circle.addEventListener(MouseEvent.CLICK, clickCircle1);
circle.addEventListener(MouseEvent.CLICK, clickCircle2);
stage.addEventListener(MouseEvent.CLICK, clickStage);
function clickCircle1(evt:MouseEvent):void {
evt.stopPropagation();
// evt.stopImmediatePropagation();
trace("clickCircle1");
}
function clickCircle2(evt:MouseEvent):void {
trace("clickCircle2");
}
function clickStage(evt:MouseEvent):void {
trace("clickStage");
}
Click the circle and see how the event is stopped with each method. stopPropagation prevented the stage from receiving the event while stopImmediatePropagation also prevented clickCircle2 from recognizing the event
normal output
clickCircle1
clickCircle2
clickStage
stopPropagation output
clickCircle1
clickCircle2
stopImmediatePropagation output
clickCircle1
senocular
September 3rd, 2006, 03:13 PM
Sometimes in ActionScript you'll want to determine when an event happens globally, whether it starts on this object or that object or even no objects. For mouse clicks, ActionScript 1 and 2 had onMouseDown and onMouseUp events which were called globally despite the location of the mouse and which object it was over. If the mouse was clicked, these events would fire. In ActionScript 3, these events now only relate to mouse events specific to the object under the mouse. A normal sprite would not receive the mouseUp event if the mouse was over an empty area of the stage when the mouse was released.
To get these events to be recognized globally within ActionScript 3, you will need to have to use event listeners with the Stage object. Since the stage is the end parent of all display objects, all events pass through the stage.
Now, one might think a simple use of addEventListener with a listener function would be all you need, but its not that easy. What happens when someone listens for an event like mouseDown for a sprite and then stops propagation for that event? Then the event would never bubble up to reach the stage. However, the event would still reach the stage in the capturing phase so if a listener is set for the stage using capture, it will be recognized before it even reaches the target. This, however, does not account for instances where the stage itself was clicked. For that, you would need to use addEventListener twice for the stage, one for captures and one to get the at target phase of the event if the stage is clicked. The only problem with this is that if an instance on the stage is clicked and it doesn't stop propagation, the stage would receive the event twice, once during capture and once during bubbling. To prevent this, you can just have your listener function only react to the capturing and at target phases by checking the eventPhase property of the Event instance passed to it.
Example:
var circle:Sprite = new Sprite();
circle.graphics.beginFill(0x4080A0);
circle.graphics.drawCircle(50, 50, 25);
addChild(circle);
// using stage for a global mouse up
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp, true);
function mouseUp(evt:MouseEvent):void {
// only care about capturing and at target phases
if (evt.eventPhase == EventPhase.BUBBLING_PHASE) return;
trace("global mouseUp");
}
// circle stops propagation in its mouse up
circle.addEventListener(MouseEvent.MOUSE_UP, mouseUpCircle);
function mouseUpCircle(evt:MouseEvent):void {
trace("mouseUpCircle");
evt.stopPropagation();
}
Even though the circle here stops propagation of the event, the stage is still able to receive the event because it uses the capturing phase.
click stage output
global mouseUp
click circle output
global mouseUp
mouseUpCircle
senocular
September 3rd, 2006, 03:40 PM
Unlike ActionScript 1 and 2, there is no onReleaseOutside event for ActionScript 3. mouseDown (Event.MOUSE_DOWN) and mouseUp (Event.MOUSE_UP) events only fire for display objects when the mouse is over the display object. The only way to detect a mouseUp outside is to detect a global mouseUp after the target instance recieves a mouseDown. If the target of that mouseUp event is then not the object originally within the mouseDown, you have a mouseUpOutside. To handle a global mouseUp, you would check for mouseUp events coming from the stage.
The easiest way to go about this is to define one mouseDown event handler for your desired object, then, in that handler, define the stage mouseUp handler. stage access shouldn't be a problem in the mouseDown since for the user to click on the target object, it would have to be in the display list, so stage access is not something to worry about. The mouseUp handler will fire when the mouse is released for the stage, and this means anywhere, even if the mouse is not within the Flash movie. Once that happens, you can check the event.target to see if the mouseUp is happening for your original object (be sure to also check instances within it) or something else such as the stage or another display object.
Example:
// create a circle to click
var circle:Sprite = new Sprite();
circle.graphics.beginFill(0x4080A0);
circle.graphics.drawCircle(50, 50, 25);
addChild(circle);
circle.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
function mouseDown(event:MouseEvent):void {
// down, now check for global mouseUp
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
}
function mouseUp(event:MouseEvent):void {
if (event.target == circle || circle.contains(event.target)){
// mouse is up over circle (onRelease)
// (if circle is not a DisplayObjectContainer,
// you do not need to use the contains check)
}else{
// mouse is up outside circle (onReleaseOutside)
}
// be sure to clean up stage listener
stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp);
}
saxplayer13
September 3rd, 2006, 03:41 PM
@Senocular:
How would you direct all keyboard events to one class? I've tried doing this in a game I'm developing, but it is very buggy and it keeps losing focus... I think what I need is a way to lock focus on one DisplayObject, but I can't seem to figure it out.
senocular
September 3rd, 2006, 03:46 PM
@Senocular:
How would you direct all keyboard events to one class? I've tried doing this in a game I'm developing, but it is very buggy and it keeps losing focus... I think what I need is a way to lock focus on one DisplayObject, but I can't seem to figure it out.
Use the stage. See the tips above ^^^
AdamSchroeder
September 4th, 2006, 04:31 PM
Thanks for the these latest tips. Particurarly the onMouseReleaseOutside example was very helpful. All of these tips are so useful... saves you so much time seeing them explained properly with examples vs. trial and error on your own to figure out.
I do want to add one tip that others new to AS3.0 might run into. The stage is now longer global but is a property of a DisplayObject IF it has been attached to a DisplayObject already placed on the stage.
So
var s:Sprite=new Sprite();
s.stage //is null
addChild(s)
s.stage //correctly reference the stage.
In pratical terms if you are extending the MovieClip to make your own classes you can not add events to the stage in your constructor (unless an argument you pass has access to it).
I had to pull my event adding code into a seperate function to call after the movieclip was already added.
example:
var e:ExtendedMovieClipClass = new ExtendedMovieClipClass();
addChild(e);
e.setupEvents();
Maybe you could get a reference from the actual Stage (capital S) class, but I haven't looked into that yet.
senocular
September 4th, 2006, 05:09 PM
That is correct. The stage property is only accessible from display objects attached to the stage. There has been some discussion about this and approaches to access the stage eariler in this thread.
senocular
September 6th, 2006, 12:05 PM
ActionScript 3 with Flash 9 lets you specify a "Document Class" (aka Application class) for the main timeline. This represents the class of the root object - the display object in which (essentially) all other display objects are placed.
You can set the Document class in the Document Class option of the Property Inspector for a document with nothing selected. You can also set the Document Class in the ActionScript 3 Settings dialog using File > Publish Settings > Flash [Tab] > Settings... [Button (for ActionScript 3)]. When defining the Document class, you simply provide the name of the class which is to pose as the class for your document. Note: This class should exist within your class path.
The Document Class for Flash needs to extend Sprite or any subclass of Sprite (flash.display.Sprite (http://livedocs.macromedia.com/flex/2/langref/flash/display/Sprite.html)) to be valid. If you use the main timeline for ActionScript at all in Flash, you would want your document class to extend MovieClip (flash.display.MovieClip (http://livedocs.macromedia.com/flex/2/langref/flash/display/MovieClip.html)) since MovieClips, unlike Sprites, support frames.
A document class should also be public (along with its constructor which is inherently public). A non-public class will result in an error when you publish your movie.
When published from Flash, SWF meta tags within Document Classes are ignored and the settings within Flash are used.
Unlike other display object classes you make, the stage property of a Document class will always be accessible since the document class is inherently a child of the stage. Similarly, if you place any objects on the main timeline in Flash, the will already be children of the Document class when its instantiated.
Example of a Document class:
package {
import flash.events.Event;
import flash.display.MovieClip;
public class CustomDocument extends MovieClip {
public function CustomDocument() {
addEventListener(Event.ADDED, checkChildren);
checkChildren(new Event("initialize"));
}
private function checkChildren(evt:Event):void {
// only allow one child in root
if (numChildren > 1) {
throw (new Error("This movie can have only one child instance"));
}
}
}
}
This class only allows one child. If more are added, an error is thrown. Notice that the checkChildren method is also automatically called in the constructor since its possible that objects could have been added to the timeline within Flash which would have been before the added event listener was created.
v_gyku
September 7th, 2006, 03:05 AM
Will the following code run? or is it somthing more I need to code?
I copy pasted the following code in the actions panel and tested the movie.
It gave a compile error: 1037: Packages cannot be nested.
Output window: ReferenceError: Error #1065: Variable MainTimeline is not defined.
Am i doing somthing wrong?
So that example at livedocs makes it pretty clear... "stage" is a global object allowing you to view and change its properties or to register events with it.
ActionScript Code:
package {</p>
<p> import flash.display.Sprite;</p>
<p> import flash.display.StageAlign;</p>
<p> import flash.display.StageScaleMode;</p>
<p> import flash.events.Event;</p>
<p> </p>
<p> public class StageExample extends Sprite {</p>
<p> </p>
<p> public function StageExample() {</p>
<p> stage.scaleMode = StageScaleMode.NO_SCALE;</p>
<p> stage.align = StageAlign.TOP_LEFT;</p>
<p> stage.addEventListener(Event.ACTIVATE, activateHandler);</p>
<p> stage.addEventListener(Event.RESIZE, resizeHandler);</p>
<p> }</p>
<p> </p>
<p> private function activateHandler(event:Event):void {</p>
<p> trace("activateHandler: " + event);</p>
<p> }</p>
<p> </p>
<p> private function resizeHandler(event:Event):void {</p>
<p> trace("resizeHandler: " + event);</p>
<p> trace("stageWidth: " + stage.stageWidth + " stageHeight: " + stage.stageHeight);</p>
<p> }</p>
<p> }</p>
<p>}
@fabiopb: Why? Isnt this just a sign, that flash goes on pretty well? If your worried anout the Adobe Flash application itself, then you dont need to be... Flex is just for something else than Flash. It wont also disappear from the Internet as everybody has the plugin, people are used to use it and it still has great potential.
v_gyku
September 7th, 2006, 04:45 AM
Are there any basic tutorials or samples to start with action script 3?
I have developed many simple games in flash with AS 2.
What I tried to do with AS 3.0 is, simple on(press). which didn't work.
Can you tell me some basic tutorials, sort of "hello world" tutorials..
Thanks...
ven
September 7th, 2006, 06:08 AM
In the duplicateDisplayObject (http://www.kirupa.com/forum/showthread.php?p=1939827#post1939827) example i get an error which i dont quite understand:
Error: Access of possibly undefined property constructor through a reference with static type flash.display:DisplayObject.
var targetClass:Class = target.constructor;
Ive tried many diffrent changes and read around in the manual, but i cant understand what im supposed to do.
senocular
September 7th, 2006, 08:59 AM
Are there any basic tutorials or samples to start with action script 3?
I have developed many simple games in flash with AS 2.
What I tried to do with AS 3.0 is, simple on(press). which didn't work.
Can you tell me some basic tutorials, sort of "hello world" tutorials..
Thanks...
Like AS2, AS3 classes (those defined with package) must be placed in external files. Code on the timeline is not explicitly defined in classes (though becomes part of a class as explained in tip 38).
The first post in this thread has links to some documentation and tutorials.
senocular
September 7th, 2006, 09:17 AM
In the duplicateDisplayObject (http://www.kirupa.com/forum/showthread.php?p=1939827#post1939827) example i get an error which i dont quite understand:
Error: Access of possibly undefined property constructor through a reference with static type flash.display:DisplayObject.
var targetClass:Class = target.constructor;
Ive tried many diffrent changes and read around in the manual, but i cant understand what im supposed to do.
That is the result of having strict mode turned on in your ActionScript 3 settings. Strict mode uses a more strict compiler check to determine the validity of your code and it doesn't recognize the constructor property because it is added to Object's prototype dynamically (as mentioned in tip 21). To get rid of that error you can turn off strict mode or use something like
var targetClass:Class = target["constructor"];
which should be able to bypass it.
Also, in using that function with Flash 9, make sure that you with the symbol(s) you are duplicating you export for ActionScript and give them explicit class names (even if the class is auto-generated). Otherwise, duplicateDisplayObject will not be able to duplicate the class properly.
v_gyku
September 7th, 2006, 12:58 PM
There are two movie clips (background_mc, char_mc) on the main timeline.
This is the code on the keyframe inside char_mc.
_root.background_mc.gotoAndPlay(2);
I have searched macromedia live docs. I found that the closetst substitute for the _root is stage. I tried somthings which didn't work out.
any suggestion?
Thanks...
ignitrix
September 7th, 2006, 01:22 PM
...
_root.background_mc.gotoAndPlay(2);
I have searched macromedia live docs. I found that the closetst substitute for the _root is stage. I tried somthings which didn't work out...
There has been a fair amount of discussion throughout this thread about the "stage" that should more than thoroughly answer your question.
~JC
senocular
September 7th, 2006, 08:11 PM
I will try to make the next post a comprehensive stage access post.
v_gyku
September 8th, 2006, 04:05 AM
I tried this and it worked.
root.background_mc.gotoAndPlay(2);
There are two movie clips (background_mc, char_mc) on the main timeline.
This is the code on the keyframe inside char_mc.
_root.background_mc.gotoAndPlay(2);
I have searched macromedia live docs. I found that the closetst substitute for the _root is stage. I tried somthings which didn't work out.
any suggestion?
Thanks...
senocular
September 8th, 2006, 07:52 PM
In Flash it is often useful to reference the main timeline, or the root, of a movie. In ActionScript 3, the root instance of the SWF loaded into a player represents the first instance of the stage (flash.display.Stage (http://livedocs.macromedia.com/flex/2/langref/flash/display/Stage.html)). The stage object in Flash is the primary container in which all other display objects, including root, exist.
A Flash application only has one stage. However, there can be multiple root instances in an application if external content is loaded into the player using the Loader class (flash.display.Loader (http://livedocs.macromedia.com/flex/2/langref/flash/display/Loader.html)).
All DisplayObject (flash.display.DisplayObject (http://livedocs.macromedia.com/flex/2/langref/flash/display/DisplayObject.html)) instances have stage and root properties. These properties, however, are null unless the display object is attached to the stage or a display list that is attached to the stage. The stage property, when accessible, will always reference the stage object. The root property references different objects depending on the display object:
For the stage, root always references the stage
For the main timeline of the SWF and all display objects within it, root references the main timeline
If an object is added directly to the stage from any timeline, the root property for it and its children references the stage
For display objects in loaded SWF files, root references the main timeline of that SWF file
For loaded bitmap images, root references the Bitmap instance of the image loaded
Loader objects used to load external SWFs and images follow the rules of all other display objects within the SWF it is being used
Keep in mind that only display objects have access to stage and root and only when attached to the stage or a display list on the stage. This is contrary to ActionScript 1 and 2 in two respects:
All "display objects" (movie clips) in AS1 and AS2 were attached to the "stage" or an active timeline upon creation. This is no longer true with AS3; in fact, the only display object which is inherently attached to the stage upon instantiation is the document class (or, in Flash 9, objects existing on the timeline in the IDE before publish).
All ActionScript in AS1 and AS2 are defined in timelines, even classes. AS a result, essentially all scopes gained access to _root through the timelines (MovieClip instances) in which they were defined. Since classes in AS3 are not defined in timelines, they no longer have access to root (or stage) unless they themselves are DisplayObject instances already attached to the stage
This greatly limits your access to stage and root within your scripts. For example, non-display object classes in AS3 can only access stage or root if explicitly given a reference. Ex:
package {
import flash.display.Stage;
public class CustomObject {
private var stage:Stage;
public function CustomObject(stageRef:Stage) {
// stage access through
// constructor argument
stage = stageRef;
}
}
}
Also, your display object classes will not inherently have stage or root access in their constructor unless they are used for the document/application class of your movie.
package {
import flash.display.Sprite;
import flash.events.Event;
public class CustomDisplayObject extends Sprite {
public function CustomObject() {
// stage not acessible until
// added to stage or display
// list on the stage
trace(stage); // null
}
}
}
This can make it difficult if you need to access the stage for things like adding event listeners. You would need to either pass a reference of the stage (or root) to your custom display objects as with the CustomObject class or not attempt to access stage or root until the object has been added to a display list allowing it to be accessible. And for this you can manually call a setup or init function after the instance has stage accessible or detect it automatically using the StageDetection class (com.senocular.events.StageDetection (http://www.senocular.com/flash/actionscript.php?file=ActionScript_3.0/com/senocular/events/StageDetection.as)). Note: As of Flash Player 9.0.28.0 - which was released with Flash CS3 - you have 2 new, native ADDED_TO_STAGE and REMOVED_FROM_STAGE events for detection access to the stage.
Another approach to stage or root access would be to create a static property of a known class that would be accessible from any class. This class can be instantiated in the document class or it can be a DisplayObject subclass and you can have your document classes extend it as opposed to Sprite or MovieClip. For example, if you have your document classes always extend this TopLevel class, any class would be able to access stage or root (assuming they want root to be the document class extending this) using TopLevel.stage and TopLevel.root.
package {
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.Stage;
public class TopLevel extends MovieClip {
public static var stage:Stage;
public static var root:DisplayObject;
public function TopLevel() {
TopLevel.stage = this.stage;
TopLevel.root = this;
}
}
}
Example document class using TopLevel
package {
public class MyDocumentClass extends TopLevel {
public function MyDocumentClass() {
// code
}
}
}
Example non-DisplayObject class used in MyDocumentClass application accessing stage:
package {
public class RandomClass {
public function RandomClass() {
trace(TopLevel.stage); // [object Stage]
}
}
}
Of course, ideally, you wouldn't need reliance on a class like TopLevel, especially if you are developing classes that might be shared with other developers. If someone is not in a position to have their document class extend TopLevel or simply don't have access to the class, any other class referencing it would fail. Passing around a reference of the stage (or root) or using the added (or added to stage) event(s) would be a safer way to go.
senocular
September 11th, 2006, 08:11 PM
Like the name qualifier operator (name qualifier operator (http://livedocs.macromedia.com/flex/2/langref/operators.html#name_qualifier)), the use namespace directive (use namespace directive (http://livedocs.macromedia.com/flex/2/langref/statements.html#use_namespace)) is a way for specifying namespaces in ActionScript 3. Unlike the name qualifier operator, use namespace is more generalize and applies to entire blocks of code rather than specfic references.
When used it is placed in a code block (package, class, method) and applies to all references within that code block. Though you cannot nest use namespace commands, you can use the name qualifier operator to reference other namespaces.
Example:
package {
public namespace company = "http://www.example.com/company";
public namespace individual = "http://www.example.com/individual";
public class UsingNameSpaces {
use namespace individual;
company var value:int = 10;
individual var value:int = 2;
public function UsingNameSpaces(){
showValue(); // traces individual::2
company::showValue(); // traces company::2;
}
company function showValue() {
trace("company::" + value);
}
individual function showValue() {
trace("individual::" + value);
}
}
}
Notice the use namespace individual; line within the class block. This inherently implies that the namespace for all references in that block is for individual. This makes the first call to showValue call individual::showValue. company::showValue can still be referenced using the name qualifier, but because it wasnt used for the value variable within it, its value defaults to individual::showValue which is why it shows as 2 instead of 10.
Krilnon
September 11th, 2006, 08:53 PM
Are the namespace declarations supposed to be outside of the class definition? I run into errors when I have them declared outside of the class.
senocular
September 11th, 2006, 08:59 PM
Are the namespace declarations supposed to be outside of the class definition? I run into errors when I have them declared outside of the class.
You should be able to have them both out of and in the class. Having them in the class means that they are only accessible from within the class while outside in the package block, they are accessible anywhere the package is accessible. the mx_internal namespace, for example, would be defined in the package block outside of the class block (allowing you to import it).
I compiled this example using Flash 9 alpha, not mxmlc, so there might be some differences there. What kind of errors are you getting? The only thing I can think of off the top of my head is possibility that, like with classes and packaged functions, namespaces defined outside of class blocks might need their own .as file for mxmlc.
Krilnon
September 11th, 2006, 09:11 PM
Originally I was testing this in another class, but I just switched to your example and the same error comes up:
A file found in a source-path can not have more than one externally visible definition. company;individual;UsingNameSpaces
The only thing I can think of off the top of my head is possibility that, like with classes and packaged functions, namespaces defined outside of class blocks might need their own .as file for mxmlc.
That sounds reasonable.
Edit: These errors aren't at compile-time, they are just given by Flex before I try to debug, however, trace isn't outputting anthing.
ven
September 12th, 2006, 07:28 AM
About loading external xml
I have problems finding some kind of errorhandling, like Flash 8 XML.status (http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002880.html#wp518558)
[Edit]
Never mind, solved with:
try {
myxml.parseXML(loader.data);
trace(myxml);
} catch (error:Error) {
trace("Error: "+error);
}
And:Run-time Errors (http://livedocs.macromedia.com/flex/2/langref/runtimeErrors.html)
[Edit2]
Actually, do mind...
Cause using XMLDocument as i did ine the example (XMLDocument.parseXML) is the old XMLobject, while XML is the new E4X-one.
When trying to get data from:
myXML = loader.data;
i get "Type Coercion failed" (error 1034)
and when i try
myXML = loader.data as XML;
myXML still contains null (nothing)
[Edit3]
and thats solved so easy i have to take 100 pushups
try {
myXML = new XML(loader.data);
(...)
senocular
September 12th, 2006, 03:34 PM
ActionScript 3 does not have a Color class. Instead, you would use the ColorTransform class (flash.geom.ColorTransform (http://livedocs.macromedia.com/flex/2/langref/flash/geom/ColorTransform.html)). This is essentially the same ColorTransform class that was introduced in Flash Player 8. Though the Color class will continue to exist in Flash 9 using ActionScript 1 and 2, it will not be available when using ActionScript 3.
Note, in ActionScript 3, the rgb property of ColorTransform has been renamed to color.
// creates a red square
var square:Shape = new Shape();
square.graphics.beginFill(0x000000);
square.graphics.drawRect(0, 0, 100, 100);
var colorTransform:ColorTransform = square.transform.colorTransform;
colorTransform.color = 0xFF0000;
square.transform.colorTransform = colorTransform;
addChild(square);
senocular
September 15th, 2006, 11:59 AM
Flash Player 9 with ActionScript 3 now handles native run-time errors that can warn you of conflictions or errors experienced within your code. If you are using the debug versions of the player (these players are often used by SWF authoring tools), a dialog will appear explaining any runtime error that might have occured.
When such an error occurs, an instance of an Error object (Top Level Error (http://livedocs.macromedia.com/flex/2/langref/Error.html)) is created and is "thrown" causing the reaction by the player. Though the Error object existed in ActionScript 1 and 2, it was only used by developers to throw their own errors using the throw keyword (throw statement (http://livedocs.macromedia.com/flex/2/langref/statements.html#throw)); the Flash player did not throw errors itself as it does now with AS3.
Additional error types can be found in the top level (Top Level (http://livedocs.macromedia.com/flex/2/langref/package-detail.html)) and the flash.errors package (flash.errors (http://livedocs.macromedia.com/flex/2/langref/flash/errors/package-detail.html)). You can also create your own errors by extending the Error class which you would be able to throw yourself with throw.
An example of code that would generate a runtime error is:
var value:* = new Array();
trace(value.getChildAt(0));
This throws a TypeError (Top Level TypeError (http://livedocs.macromedia.com/flex/2/langref/TypeError.html)) since value is of type Array, not DisplayObjectContainer which is the class that really contains the getChildAt method.
More information on run-time errors (http://livedocs.macromedia.com/flex/2/langref/runtimeErrors.html)
senocular
September 15th, 2006, 12:59 PM
To handle errors, you would want to make use of the try..catch..finally statement (try..catch..finally statement (http://livedocs.macromedia.com/flex/2/langref/statements.html#try..catch..finally)). This statement lets you create codes block that can intercept thrown errors and deal with them appropriately (handle exceptions). If errors throw by the player aren't intercepted and "caught" the current script will terminate. Because ActionScript 3 throws errors on its own now, it will be increasingly more important to use this statement in your code.
Each try, catch, and finally (optional) represent 3 different types of code blocks that can be used within a try..catch..finally statement.
try {
// statements
} catch (error:Error) {
// statements
} finally {
// statements
}
The try block is the testing grounds that executes code that could potentially throw an error. This is the first block in the statement.
Following try is one or more catch blocks that can react to errors thrown in try. Each catch block is associated with an Error type that will run if that kind of error is thrown in try. If the type of the error thrown does not match the error type in the first catch block, the next catch block is checked until there is a match or until there are no more catch blocks to check (resulting in an uncaught exception). Because of this hierarchy of checking, its often a good idea to have your last catch block catch errors of type Error which would include all errors thrown.
After the catch block(s) comes one optional finally block which runs after the try and catch blocks. What's special about the finally block is that it will always run after try and catch, even if any one of those blocks used a return statement to exit the current function block or there is an uncaught error not handled in any of the catch blocks used (at which point any script following the try..catch..finally would not run).
Example:
try {
var value:* = new Array();
trace(value.getChildAt(0));
} catch(error:IOErrorEvent) {
trace("IOErrorEvent catch: " + error);
} catch(error:TypeError) {
trace("TypeError catch: " + error);
} catch(error:Error) {
trace("Error catch: " + error);
} finally {
trace("Finally!");
}
trace("Continuing with script...");
This outputs
TypeError catch: TypeError: Error #1006: getChildAt is not a function.
Finally!
Continuing with script...
The TypeError was recognized in the catch(error:TypeError) block, caught, and the script was able to continue normally, but not before finally runs, of course. Though a catch(error:Error) was used here, it was not used because a catch(error:TypeError) was included that correctly matched the error thrown. If the TypeError catch was not there, the Error catch would have been used instead. What about what happens if only the unrelated IOErrorEvent is used?
try {
var value:* = new Array();
trace(value.getChildAt(0));
} catch(error:IOErrorEvent) {
trace("IOErrorEvent catch: " + error);
} finally {
trace("Finally!");
}
trace("Continuing with script...");
Here is the output from Flash 9:
Finally!
TypeError: Error #1006: getChildAt is not a function.
at Timeline0_a24dfc5f2aa9864b9d4de27c9fa097db/::frame1()
No erorr was caught, so the script was terminated after the finally block and the default error message was raised.
senocular
September 15th, 2006, 01:27 PM
Some errors in ActionScript 3 do not occur at the time of a function call and, instead, occur sometime after the call, asynchronously. The most common example of this is loading content from the web. Consider a URLLoader instance (flash.net.URLLoader (http://livedocs.macromedia.com/flex/2/langref/flash/net/URLLoader.html)) loading content like xml from the web. If the url used in URLLoader.load is an invalid url, the Flash Player won't know until it has been given the time to attempt a connection with url and determine whether or not it exists. While it tries to do this, the script in the player will continue run normally until such an error occurs. Since the script continues, a try..catch..finally statement would be of no use in attempting to catch these asynchronous errors since no error happens at the time those blocks run.
Example:
var loader:URLLoader = new URLLoader();
loader.load(new URLRequest("Invalid XML URL"));
trace("Continuing with script...");
This outputs (Flash 9):
Continuing with script...
Error #2044: Unhandled ioError:. text=Error #2032: Stream Error. URL: file:///C|/DOCUME%7E1/senocular/LOCALS%7E1/Temp/Invalid XML URL
at Timeline0_5650dafd68b564789d938267b772078/::frame1()
The error here happened after the "Continuing with script..." trace showing that it did not relate to the load call itself but rather an error that occured in the background as the player was working on that request.
Instead, what you would need to do is use event handlers "catch" asynchronous errors during error-related events which essentially prevents the error from being thrown in the first place. This is all done automatically without the need of try..catch..finally. Simply having an error event handler allows the error to be caught.
var loader:URLLoader = new URLLoader();
loader.addEventListener(IOErrorEvent.IO_ERROR, catchIOError);
function catchIOError(event:IOErrorEvent){
trace("Error caught: "+event.type);
}
loader.load(new URLRequest("Invalid XML URL"));
trace("Continuing with script...");
This outputs:
Continuing with script...
Error caught: ioError
showing the error was caught within the event handler which traced the event type.
Depending on your code, you may find the need to use both try..catch..finally and error handlers together.
Yakuza
September 17th, 2006, 11:09 AM
err...sorry to interupt your tips...lol
want to ask question about Flash 9 actionscript 3.0 preview
I've tried the "stage.frameRate = 12;" to change my framerate dynamically...why it doesn't work? Even the trace will see as undefine object, do I need to import anything or what?
I'm not a coder for myself and I'm still pretty new to actionscript.
senocular
September 17th, 2006, 11:17 AM
If you have it on the timeline in Flash 9, it should work fine (make sure your publish settings are for AS3). Other than that, if you're using it in a class, you would have to make sure you have access to stage. There is mention of this a few tips back, but it can be confusing, especially for a new coder.
senocular
September 18th, 2006, 11:43 AM
As you've probably seen, using E4X with ActionScript 3, you can get a list of children from an XML object or List using the children dot (.) operator (XML dot operator (http://livedocs.macromedia.com/flex/2/langref/operators.html#dot_(XML))). Example:
var myXML:XML =
<foo>
<bar />
<bar />
<bar />
</foo>;
trace(myXML.bar.toXMLString());
Output:
<bar/>
<bar/>
<bar/>
This is the same as using the elements method in XML (XML.elements() (http://livedocs.macromedia.com/flex/2/langref/XML.html#elements())).
trace(myXML.elements("bar").toXMLString());
There's a similar operator that is two dots (..), the descendant accessor operator (descendant accessor operator (http://livedocs.macromedia.com/flex/2/langref/operators.html#descendant_accessor)). Its It works much like dot operator only it accesses not only children, but all children's children and their children etc. (decendants). Example:
var myXML:XML =
<note>
<replying-to>
<note>
<author>Julie</author>
<title>Reminder</title>
<body>Take out the trash</body>
</note>
</replying-to>
<author>Kevin</author>
<title>Re: Reminder</title>
<body>I will.</body>
</note>;
trace("Children:");
trace(myXML.author.toXMLString());
trace("Decendants:");
trace(myXML..author.toXMLString());
Output:
Children:
<author>Kevin</author>
Decendants:
<author>Julie</author>
<author>Kevin</author>
You can see where children stopped in the current node (the XML object itself) the decendants operator will pick up all descendants of the node. The method equivalent of the descendant accessor operator is decendants (XML.descendants() (http://livedocs.macromedia.com/flex/2/langref/XML.html#descendants())).
trace(myXML.descendants("author").toXMLString());
senocular
September 19th, 2006, 01:51 PM
The Array class (Top level Array (http://livedocs.macromedia.com/flex/2/langref/Array.html)) in ActionScript 3 has a few new methods associated with it. Two are indexOf and lastIndexOf
AS3 function indexOf(searchElement:*, fromIndex:int = 0):int
AS3 function lastIndexOf(searchElement:*, fromIndex:int = 0x7fffffff):int
These work just like String.indexOf and String.lastIndexOf allowing you to find the position of objects within an array. As with String, if an object doesn't exist, -1 is returned.
var sprite:Sprite = new Sprite();
var object:Object = new Object();
var boolean:Boolean = true;
var number:Number = 10;
var array:Array = new Array(sprite, object, number);
trace(array.indexOf(sprite)); // 0
trace(array.indexOf(number)); // 2
trace(array.indexOf(boolean)); // -1
senocular
September 19th, 2006, 02:05 PM
As with ActionScript 1 and ActionScript 2, ActionScript 3 allows you to associate ActionScript events with links in text. Though not much has changed functionally (you can still not detect link rollovers, only clicks), the name of the string used to associate links with script has changed from asfunction to now being simply event (flash.text.TextField.event:link (http://livedocs.macromedia.com/flex/2/langref/flash/text/TextField.html#event:link)) in AS3.
In addition, with the new method of event handling in AS3, event (asfunction) no longer calls a method you defined but, rather, sends out an TextEvent (flash.events.TextEvent (http://livedocs.macromedia.com/flex/2/langref/flash/events/TextEvent.html)) of the type TextEvent.LINK for the text field instance in which it exists. The text following the event: keyword in the link is accessible from the TextEvent object through its text property.
Example:
var linkText:TextField = new TextField();
linkText.htmlText = 'Link: <a href="event:Link Clicked">Click</a>';
addChild(linkText);
linkText.addEventListener(TextEvent.LINK, linkEvent);
function linkEvent(event:TextEvent):void {
trace(event.text); // Link Clicked
}
Ordinathorreur
September 19th, 2006, 02:20 PM
looking at your example, I suppose this means that AS3 now returns a reference to a dynamically created textfield?
senocular
September 19th, 2006, 02:59 PM
Do you mean through new TextField? new TextField is much different than createTextField. createTextField is a function that attaches a text field to the screen. With new TextField you have a text field class which you are instantiating with the new keword. Whenever you use new [class name] the result is a new instance of that class; there's no option on whether or not to return references as is the case with functions like createTextField. In ActionScript 3, attachMovie and createTextField no longer exist. Instead you just create new instances and add them to the screen using addChild, so its not exactly the same.
senocular
September 21st, 2006, 10:09 AM
Given the dynamic nature of Proxy (flash.utils.Proxy (http://livedocs.macromedia.com/flex/2/langref/flash/utils/Proxy.html)) instances, like with setProperty and callProperty, you are able to control Proxy instance enumeration (looping through properties of a Proxy instance using for..in and for each..in) using class methods. The methods that do this are:
nextName(index:int):String
nextValue(index:int):*
nextNameIndex(index:int):int
Both nextName and nextValue are the functions that let you decide what comes next in a for..in or a for each..in loop (nextName relates to for..in loops while nextValue relates to for each..in). The value returned by nextName is the key given in a for..in and the value returned by nextValue is a value for a for each..in. The index argument in their calls represents the number provided by nextNameIndex.
nextNameIndex is called before each loop iteration and allows you to do two things" a) set the index value that is to be received by nextName and nextValue (and itself for the following call) or b) stop the loop. Both of these are dictated by the return value coming from nextNameIndex. Any non-zero integer is used for the current loop interation and passed to nextName or nextValue which are called directly following nextNameIndex and a zero value stops the loop after nextNameIndex and exits the for..in or for each..in block used on the instance. The initial index value received by nextNameIndex is 0. Each subsequent value is the value it last returned (and was given to nextName and nextValue) unless 0 is returned and the loop is stopped. For example, assuming a proxy instance has 3 "properties" to loop over in a for..in, here is how nextNameIndex and nextName are used:
for (var prop:String in proxy) {
trace(prop);
}
for (var prop:String in proxy) {
[ proxy.nextNameIndex(0) -> return 1 ]
[ proxy.nextName(1) -> return "x" ]
[ prop = "x" ]
trace(prop); // x
(end for block, repeat)
[ proxy.nextNameIndex(1) -> return 2 ]
[ proxy.nextName(2) -> return "y" ]
[ prop = "y" ]
trace(prop); // y
(end for block, repeat)
[ proxy.nextNameIndex(2) -> return 3 ]
[ proxy.nextName(3) -> return "visible" ]
[ prop = "visible" ]
trace(prop); // visible
[ proxy.nextNameIndex(3) -> return 0 ]
(0 index, break from for block)
}
If a for each..in was used, nextValue would be called instead and the prop variable could be set to value, not just a string.
Because of the use of index to keep track of looping, you'll commonly see Proxy instances keep their enumerable properties or values in arrays. Then in nextName or nextValue you would just return the element in the array at index-1 (remember, nextName and nextValue would never receive 0 since that would have caused the loop to stop if returned from nextNameIndex). Here's an example of a proxy class that makes use of nextName and nextNameIndex and outputs what was seen above. Remmeber, proxy methods are defined in the flash_proxy namespace.
Class:
package {
import flash.utils.Proxy;
import flash.utils.flash_proxy;
public class ProxyEnum extends Proxy {
private var props:Array = ["x", "y", "visible"]; // properties array
// nextNameIndex called when the loop starts
override flash_proxy function nextNameIndex (index:int):int {
if (index < props.length) {
// first call is 0, return 1 + index the index
// starts with 1, then 2, then 3... etc.
return index + 1;
} else {
// after outside of props bounds,
// stop the loop returning 0
return 0;
}
}
// nextName called after nextNameIndex returns non-zero
override flash_proxy function nextName(index:int):String {
// return the array item in index - 1
// this relates to a property name in a for..in
return props[index - 1];
}
}
}
Usage:
var proxy:ProxyEnum = new ProxyEnum();
for (var prop in proxy) {
trace(prop);
}
/* output:
x
y
visible
*/
With this, you should also define nextValue and even getProperty to make sure that when users get these values in a for..in (or try a for each..in) its still valid. The modified class uses the same properties but adds a nextValue method and a getProperty to connect the dots between the values seen in for..in (making them relate to a display object passed into the proxy instance).
Class:
package {
import flash.display.DisplayObject;
import flash.utils.Proxy;
import flash.utils.flash_proxy;
public class ProxyEnum extends Proxy {
private var props:Array = ["x", "y", "visible"]; // properties array
private var _target:DisplayObject;
function ProxyEnum(target:DisplayObject) {
_target = target;
}
// nextNameIndex called when the loop starts
override flash_proxy function nextNameIndex (index:int):int {
if (index < props.length) {
// first call is 0, return 1 + index the index
// starts with 1, then 2, then 3... etc.
return index + 1;
} else {
// after outside of props bounds,
// stop the loop returning 0
return 0;
}
}
// nextName called after nextNameIndex returns non-zero
override flash_proxy function nextName(index:int):String {
// return the array item in index - 1
// this relates to a property name in a for..in
return props[index - 1];
}
// nextValue called after nextNameIndex returns non-zero
override flash_proxy function nextValue(index:int):* {
// return the array item in index - 1
// this relates to a property value in a for each..in
var prop:String = props[index - 1];
return _target[prop];
}
// gets a property by the name of name
override flash_proxy function getProperty(name:*):* {
return _target[name];
}
}
}
Usage:
var proxy:ProxyEnum = new ProxyEnum(my_mc);
for (var prop:String in proxy) { // nextName/nextNameIndex
trace(prop);
trace(proxy[prop]); // getProperty
}
/* output:
x
34
y
76
visible
true
*/
for each(var value:* in proxy) { // nextValue/nextNameIndex
trace(value);
}
/* output:
34
76
true
*/
senocular
September 21st, 2006, 11:58 AM
Though ActionScript 3 now supports event propagation (capturing, bubbling, etc). Events like mouse events still only occur for one specific target for each individual event. In other words, when you click the mouse button over some objects in a Flash movie, only one of those objects is going to recieve the event even though the mouse is physically over other objects as well.
This behavior is similar to ActionScript 1 and ActionScript 2 where buttons or movie clips with button events take precedence over any objects beneath them. So, if you have two buttons of the same shape in the same location and click them, the top button will be the only button to receive the event. This continues to be the case in ActionScript 3.
In AS1 and AS2, however, movie clips without button event handlers associated with them (onPress, onRelease, etc) did not capture events and instead allowed the events to go "through" and reach objects beneath them. This kind of event association is not recognized in ActionScript 3; i.e. assigning an event listener to a display object does not change that object's behavior. However, the same behavior of capturing or not capturing events can still be adjusted in ActionScript 3, only now, instead of being related to event handlers, its associated with a property called mouseEnabled (flash.display.InteractiveObject.mouseEnabled (http://livedocs.macromedia.com/flex/2/langref/flash/display/InteractiveObject.html#mouseEnabled)).
When the mouseEnabled property of a display object (of the type InteractiveObject - not all display objects) is true, that object and only that object will capture those mouse events preventing them from reaching objects beneath it. When false, the object will not receive the event and it will go through the object reaching any object that lies beneath it.
One important thing to keep in mind is that, in ActionScript 3, mouseEnabled is true by default. This means, without any event handlers or listeners used in a movie, every InteractiveObject instance will capture mouse events and prevent them from reaching any other objects beneath them. This is opposite of AS1 and AS2.
Example:
var upperCircle:Sprite = new Sprite();
upperCircle.name = "upperCircle";
upperCircle.graphics.beginFill(0xFF0000, .5);
upperCircle.graphics.drawCircle(75, 50, 50);
upperCircle.graphics.endFill();
var lowerCircle:Sprite = new Sprite();
lowerCircle.name = "lowerCircle";
lowerCircle.graphics.beginFill(0xFF, 1);
lowerCircle.graphics.drawCircle(50, 50, 50);
lowerCircle.graphics.endFill();
addChild(lowerCircle);
addChild(upperCircle);
lowerCircle.addEventListener(MouseEvent.CLICK, traceTargetName);
// upperCircle.mouseEnabled = false;
function traceTargetName(event:MouseEvent):void {
var circle:Sprite = event.target as Sprite;
if (circle) {
trace(circle.name);
}
}
In clicking on the overlapping area of where upperCircle covers lowerCircle, you can see that, with the current code, there is no trace even though there are no events associated with upperCircle, just lowerCircle. After setting mouseEnabled of upperCircle to false, events in that overlapping area are able to make it to lowerCircle. However, keep in mind too that this also means that and mouse event listeners for upperCircle would not fire since upperCircle has been effectively disabled from receiving them as a result of mouseEnabled being set to false.
shendel101
September 22nd, 2006, 12:33 AM
hey guys, i wanna ask how can i use the code in the first post... coz im having big trouble with this kind of situation(detecting the mouse if rolls out in the movie and play a certain movieClip) and i cant move on in my project.. should copy and paste the code in the action panel...? and the will work already.. is that it. please advise me...
senocular
September 22nd, 2006, 01:16 AM
Are you in the right thread? The first post here is only a list of additional posts. Most of the code in this thread would be used in external ActionScript 3.0 files (though many of the more recent posts would work as timeline scripts - Flash 9 alpha AS3 preview only)
senocular
September 22nd, 2006, 10:04 AM
Flash 9 offers a new ActionScript setting for ActionScript 3 called "strict mode" (Edit > Preferences > ActionScript > ActionScript 3.0 settings... > Strict mode). This mode essentially relates to the option of compile-time type checking. When enabled, strict mode will use compile-time checking to make sure your code is valid and if not, will throw an error preventing the SWF from being created.
There are times where you may need to turn strict mode off since it is more strict than runtime checking. Also, it does not accurately handle prototyped values since they are not part of typed definitions. For example, the constructor property of the Object class is prototyped (not a true property of the Object class's class definition). Because of this, if you ever try to access this property off of a non-dynamic subclass of Object, in strict mode, your code will not compile. Trying:
var mySprite:Sprite = new Sprite();
trace(mySprite.constructor);
will give you an error similar to
**Error** Scene 1, Layer 'Layer 1', Frame 1 : Line 2, Column 16 : [Compiler] Error #1119: Access of possibly undefined property constructor through a reference with static type flash.display:Sprite.
trace(mySprite.constructor);
ReferenceError: Error #1065: Variable Timeline0_9f132e9d986cc749b16415211316a5f0 is not defined.
For this instance, you can get around this by casting the instance down to Object which is dynamic and won't throw the error no matter what you access.
var mySprite:Sprite = new Sprite();
trace(Object(mySprite).constructor); // [class Sprite]
(There are some other cases which cause problems in strict mode; I'll try to post them here as they come to me)
senocular
September 22nd, 2006, 11:33 AM
The System class (flash.system.System (http://livedocs.macromedia.com/flex/2/langref/flash/system/System.html)) in ActionScript 3 has a new property called totalMemory (flash.system.System.totalMemory (http://livedocs.macromedia.com/flex/2/langref/flash/system/System.html#totalMemory)). This property provides the current memory usage of the Flash player in bytes. Examples:
var o:Object = new Object();
trace(System.totalMemory); // 4960256
var o:MovieClip = new MovieClip();
trace(System.totalMemory); // 4964352
ignitrix
September 22nd, 2006, 09:55 PM
ActionScript 3 lets you easily obtain any instances class name using a new function called getQualifiedClassName (flash.utils.getQualifiedClassName (http://livedocs.macromedia.com/flex/2/langref/flash/utils/package.html#getQualifiedClassName%28%29))... Similarly, is it possible to acquire a reference to a Function object from a String with the function's name?
~JC
senocular
September 22nd, 2006, 11:12 PM
finish reading that post :crazy:
senocular
September 25th, 2006, 11:40 AM
Previous versions of the Flash player could not close connections to the internet once a download into the player has started. For example, if you started loading a 50 Meg swf into the flash player but wanted to stop it once the user requested different content, you couldn't. The only way to prevent Flash from continuing to load that SWF would be to close the player (i.e. navigate away from that web page).
In Flash Player 9, using ActionScript 3, you can now stop connections and abort loading requests made by the player. Consider the Loader class (flash.display.Loader (http://livedocs.macromedia.com/flex/2/langref/flash/display/Loader.html)). Its a displayObjectContainer class that loads external content into the player acting like a cross between a MovieClip and a LoadVars class (from AS1 and AS2). You can load content into this class using the load method. To abort that loading process, you would use the close method. Example:
var loader:Loader = new Loader();
var request:URLRequest = new URLRequest("image.jpg");
loader.load(request);
addChild(loader);
// abort loading if not done in 3 seconds
var abortID:uint = setTimeout(abortLoader, 3000);
// abort the abort when loaded
loader.contentLoaderInfo.addEventListener(Event.CO MPLETE, abortAbort);
function abortLoader(){
try {
loader.close();
}catch(error:Error) {}
}
function abortAbort(event:Event){
clearTimeout(abortID);
}
Notice that the close() method was placed in a try..catch block. This is because close will throw an IOError if you use it on a Loader instance when there is no connection open (this should never happen in this case, though, since once loading is complete, the timeout is cleared - good practice none the less).
pet-theory
September 25th, 2006, 02:43 PM
After reading this tip, I looked up the loader and the sound class in the Adbobe documentation, trying to understand if it is possible to resume a download after the loading has been closed.
It doesn't look like it, but I'm still not clear. What do you think? Will Flash now save partially downloaded data, like a browser? (For that matter, I'm not that clear on the relation between browser memory and Flash memory).
The practical implications: if you could partially download pictures or sound in the background, then resume downloading when the users makes a choice, you could make some very snappy interfaces. (Let's say iTunes preloads half a second from twenty focused songs--the songs could start streaming immediately when the user chooses them. Losing that half a second makes for a whole new experience.)
Loving the tips.
Balala
September 25th, 2006, 04:37 PM
For example, if you started loading a 50 Meg swf into the flash player but wanted to stop it once the user requested different content, you couldn't. The only way to prevent Flash from continuing to load that SWF would be to close the player (i.e. navigate away from that web page).
What if overwrite the MovieClipLoader class?
var mc_load:MovieClipLoader = new MovieClipLoader();
mc_load.loadClip("large_file", target); // start download a 50mb SWF
mc_load.loadClip("small_file", target); // start, and complete download of 200kb SWF
It will be, the 50mb SWF download, interrupted?
senocular
September 25th, 2006, 05:31 PM
It is my undestanding that that will not close the original connection.
senocular
September 25th, 2006, 07:24 PM
ActionScript 3 introduces a new class to ActionScript called the Timer class (flash.utils.Timer (http://livedocs.macromedia.com/flex/2/langref/flash/utils/Timer.html)). This class is kind of like a suped-up setInterval (flash.utils.setInterval() (http://livedocs.macromedia.com/flex/2/langref/flash/utils/package.html#setInterval())) that sends event messages out over a period of time measured in milliseconds. Because it uses events (flash.events.TimerEvent (http://livedocs.macromedia.com/flex/2/langref/flash/events/TimerEvent.html)) and not a callback like setInterval, a single Timer instance can be used to call many different functions as long as they are made listeners of that instance. Additionally, Timer gives you the ability to control how many times it repeats, unlike setInterval which repeats indefinitely until clearInterval is used to shut it down, as well as the ability to start and stop the timer on command.
Example:
var timer:Timer = new Timer(500, 10);
timer.addEventListener(TimerEvent.TIMER, notifier);
timer.addEventListener(TimerEvent.TIMER, stopper);
stage.addEventListener(MouseEvent.CLICK, continuer);
function notifier(event:TimerEvent):void {
trace(timer.currentCount);
}
function stopper(event:TimerEvent):void {
switch (timer.currentCount) {
case 5:
timer.stop();
break;
case timer.repeatCount:
timer.reset();
break;
}
}
function continuer(event:MouseEvent):void {
timer.start();
}
timer.start();
This timer instance sends a TimerEvent.TIMER event every 500 milliseconds and repeats 10 times. There are 2 event listeners responding to these events, one tracing the current count of the timer and the other which will either stop (on current count of 5) or reset the timer (on current count of total count) based on the timer's current count. A mouse click to the stage will allow you to restart the timer as a result of it being stopped in the stopper listener. What you end up getting is
1
2
3
4
5
(pause; click to continue)
6
7
8
9
10
(pause; click to continue)
1
2
3
4
5
...
senocular
September 25th, 2006, 08:01 PM
The ActionScript virtual machine that runs ActionScript 3 code (AVM2) is completely different from the ActionScript virtual machin that runs ActionScript 1 and ActionScript 2 code (AVM1). Because of this, you cannot call commands in an AVM1 movie from and AVM2 movie or vise versa. The virtual machines just are not compatible in that respect and mostly run in their own kind of shell that allows it to only interact with code being played back in that same virtual machine. What that boils down to is that ActionScript 3 cannot talk to AS1 or AS2 - at least not directly.
One thing these two virtual machines have in common is their implementation of LocalConnection. Both virtual machines deal with local connections in essentially the same way - enough that local connections in AVM1 can receive events from AVM2 and vise versa. So should you come into a situation where you would need a movie published in ActionScript 3 to communicate with a movie published in ActionScript 1 or 2, using local connection is the way to go.
LocalConnection AS2 (http://livedocs.macromedia.com/flash/8/main/00002338.html)
LocalConnection AS3 (flash.net.LocalConnection) (http://livedocs.macromedia.com/flex/2/langref/flash/net/LocalConnection.html)
Example:
// ActionScript 2 file, AS2animation.fla
// one movie clip animation named animation_mc on the timeline
// local connection instance to receive events
var AVM_lc:LocalConnection = new LocalConnection();
// stopAnimation event handler
AVM_lc.stopAnimation = function(){
animation_mc.stop();
}
// listen for events for "AVM2toAVM1"
AVM_lc.connect("AVM2toAVM1");
// ActionScript 3 file, AS3Loader.fla
// local connection instance to communicate to AVM1 movie
var AVM_lc:LocalConnection = new LocalConnection();
// loader loads AVM1 movie
var loader:Loader = new Loader();
loader.load(new URLRequest("AS2animation.swf"));
addChild(loader);
// when AVM1 movie is clicked, call stopPlayback
loader.addEventListener(MouseEvent.CLICK, stopPlayback);
function stopPlayback(event:MouseEvent):void {
// send stopAnimation event to "AVM2toAVM1" connection
AVM_lc.send("AVM2toAVM1", "stopAnimation");
}
The AS3 movie loads the AS2 movie into a Loader instance and places it on the screen. As it plays, the user can click the animation which calls stopPlayback sending the "stopAnimation" event to the local connection named "AVM2toAVM1". The AS2 movie is then able to receive that event in its stopAnimation event handler and tell the animation_mc clip to stop.
ven
September 26th, 2006, 07:37 AM
How do i turn off strictmode for mxmlc.exe?
In mxmlc.exe -help -list i see compiler.strict and in -help -compiler.strict it says:
-compiler.strict
alias -strict
runs the AS3 compiler in strict error checking mode.
I guess im supposed to understand what to do now, but i dont...
I have tried various ways to edit in the lines in "Myclass.bat" made from senoculars "Make.bat", but nothing seems to work sofar.
Powered by vBulletin® Version 4.1.10 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.