Results 166 to 180 of 663
Thread: ActionScript 3 Tip of the Day
-
August 20th, 2006, 11:42 AM #166It 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.
Originally Posted by snick
-
August 20th, 2006, 11:42 PM #167
XML: XML and XMLList
When working with E4X in ActionScript 3, you deal with 2 kinds of objects, XML (Top level XML) and XMLList (Top level XMLList), 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:
Code:// XML: <foo> <foo /> <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.Code:// XMLList: <foo /> <foo /> <foo />
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:
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:Code: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
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:Code:trace(myXML.foo[0].@bar is XMLList); // true
The same applies to XMLCode:trace(myXML.foo[0].@bar[0] is XML); // true
The XML operations that can return more than one value (nodes, attributes, etc) will return XMLList instances.Code:var myXML:XML = <foo> <foo /> </foo>; trace(myXML.foo is XMLList); // true
-
August 22nd, 2006, 06:32 AM #168
Constants
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). This is used in place of what would otherwise be var (var keyword).
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.Code:package { import flash.display.Sprite; public class MyClass extends Sprite { public const MY_CONSTANT:String = "constant"; public function MyClass () { } } }
Code: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 } } }
-
August 22nd, 2006, 06:55 AM #169
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
-
August 22nd, 2006, 07:00 AM #170Actually, I might be wrong on that one. I should do some testing before commiting to that behavior (I might be thinking of something else).
Originally Posted by Deviant1853
[edit]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
[/edit]
-
August 22nd, 2006, 08:21 AM #171
Any time Senocular
-
August 24th, 2006, 10:01 AM #172
duplicateMovieClip Replacement
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:
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.Code: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; } }
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:
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.Code: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
-
August 24th, 2006, 10:42 AM #173
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
-
August 24th, 2006, 11:28 AM #174
Proxy: callProperty
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.
This example uses callProperty to accept generic get and set methods to get and set dynamic "variables" which are stored in the variables object.Code: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]; } } } }
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.Code:// 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)
-
August 24th, 2006, 11:44 AM #17541AS3 denizen
postsNice 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
-
August 24th, 2006, 11:45 AM #176
Creating graphics Copies
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:
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:Code: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); } } } }
Code:// 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); } } }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.Code:// 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;
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.
-
August 24th, 2006, 11:53 AM #177
-
August 24th, 2006, 03:34 PM #17841AS3 denizen
postsIs 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...
Originally Posted by senocular
-
August 24th, 2006, 04:22 PM #179I 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.
Originally Posted by ignitrix
The scale mode and the alignment arent nessicary they are just very useful for my needs.PHP Code:/**
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;
}
}
}
Last edited by Deviant1853; August 24th, 2006 at 04:32 PM.
-
August 24th, 2006, 04:38 PM #18041AS3 denizen
postsThis worked excellent! Thanks Deviant



Reply With Quote

Bookmarks