Get the Flash Player to see the slideshow.

reflection [as3]

[we're not talking about those mirror-images that were hip in Flash for a year.] reflection allows your code to inspect its own properties, methods, type, parent-type… . used in recipes including copying xml values to object properties & creating a decorator which extends proxy. I’m putting useful examples below, in one convient spot.

ReflectionUtil.rtf includes:

inspecting an Object internally

  • returning the public instance properties/methods of an Object.
  • copying/duplicating public instance properties between Objects.
//----------------------------------------------------------------------------
//  Methods which inspect the public instance properties/methods of an Object
//----------------------------------------------------------------------------

/**
 * locates the public props of $obj
 * @param $obj: the object to inspect.
 * @param nodeName: 'variable' grabs properties, 'method' grabs methods
 * @return: dictionary of nodes in $obj identified by nodeName
 */

public static const VARIABLE:String = 'variable';
public static const METHOD:String = 'method';
public static function findPublic($obj:*, nodeName:String=VARIABLE):Dictionary
{
    var dict:Dictionary = new Dictionary(true);
    var nodeList:XMLList;
    switch (nodeName)
    {
        case VARIABLE:
            nodeList = describeType($obj)..variable;
            break;
        case METHOD:
            nodeList = describeType($obj)..method;
            break;
        default:
            throw new Error('node label is not handled.');
    }
    var n:int=nodeList.length();
    for(var i:int = 0; i < n; i++)
    {
        dict[String(nodeList[i].@name)] = true;
    }
    nodeList = null;
    return dict;
}

/**
 * sets public properties of parent object equal to matching properties of $obj
 * @param $obj: object whose matching name/type properties will be
 *    duplicated (primitives) or pointed to (complex data types)
 * @param cloneData
 */

public static function propsFromObject(copyFrom:*, copyTo:*, cloneData:Boolean=false):void
{
    var varList:XMLList = describeType(copyTo)..variable;
    var n:int=varList.length();
    for(var i:int=0; i < n; i++)
    {
        var prop:String = String(varList[i].@name);
        if (copyFrom.hasOwnProperty(prop))
        {
            copyTo[prop] = (cloneData) ? returnNewRef(copyFrom[prop], varList[i].@type) : copyFrom[prop];
        }
    }
    varList=null;
}

/**
 * used by propsFromObject if a new instance of the copied property is desired.
 * create additional cases as needed.
 * @param prop: the value being duplicated
 * @param type: the value's type
 * @return: a new instance of the value
 * @throws Error: if attempting to duplicate an Object which is not handled
 */

private static function returnNewRef(prop:*, type:*):*
{
    var cloneProp:*;
    switch (String(type))
    {
        case "Array":
            cloneProp = new Array().concat((prop as Array));
            break;
        case "flash.display::Bitmap":
            cloneProp = new Bitmap((prop as Bitmap).bitmapData);
            break;
        case "Number":
        case "int":
        case "uint":
        case "String":
        case "Boolean":
        case "Null":
        case "void":
            cloneProp = prop;
            break;
        default:
            throw new Error('returnNewRef:: create instantiation for '+type);
    }
    return cloneProp;
}

inspecting an Object type

  • checking whether two Objects are the same type
  • checking whether an Object extends another
//--------------------------------------
//  Methods which inspect Class names
//--------------------------------------

/**
 * checks whether two classes are of the same type
 * @param compareThis
 * @param toThis
 * @return
 */

public static function getIsSameType(compareThis:*,toThis:*):Boolean
{
    return (getClassName(compareThis) == getClassName(toThis));
}

/**
 * @param classIn
 * @return: the class name as String
 */

public static function getClassName(classIn:*):String
{
    /* === flash.utils.getQualifiedClassName(classIn).split("::")[1] */
    return describeType(classIn).@name.split("::")[1];
}

/**
 * checks whether one class is a child of another
 * @param doesThis: the possible child
 * @param extendThis: the possible parent
 * @return
 */

public static function getDoesExtend(doesThis:*,extendThis:*):Boolean
{
    var doesExtend:Boolean=false;
    var extendsL:XMLList = describeType(doesThis).extendsClass;
    var toThisClassName:String = getClassName(extendThis);
    for each( var i:XML in extendsL)
    {
        if (i.@type.split("::")[1]==toThisClassName)
        {
            doesExtend=true;
            break;
        }
    }
    extendsL=null;
    return doesExtend;
}

Robotlegs with BulkLoader. XML asset injection.

as a trainload of contrast to my last post, I’m playing with Robots. I created an integration of BulkLoader & Robotlegs. assets are grouped as specified in the accompanying assetsLoaded.xml. asset groups are loaded/unloaded on request, using Robotlegs commands.

observer pattern as MVC enabler

I had been building variations of MVC without implementing the Observer pattern. Now having studied Observer, I realize how to do MVC properly.

MVC without Observer is like NATO without formal delegates. You’d let every citizen in every nation contact every other directly.

We want our model to publish to a group of subscribers. Flex bindings can pull this off. Consider, however:

  1. Encapsulation recommends, and modularization implies, that not every class directly accesses every other. (Beware of EventBroadcaster use & Singleton abuse.)
  2. While you have a handful of models with a slew of listeners, EventListeners are firing constantly, listening for changes. This will affect memory consumption.

Observer allows for an easily-readable, encapsulated, relationship between Model and View. Your model extends a Publisher class. Publisher has a function which adds subscribers to its subscriber Array. The Publisher class also has a function to notify its group of subscribers. The Publisher knows that any Object which subscribes will implement the Subscriber class.

Views which require Model/Publisher data extend a Subscriber class. The parent Subscriber is a good place to declare your static constant strings — these describe data groups. (Having these outside the model better supports encapsulation, but I’ve seen them in the model in other examples.) Each Subscriber child has an Array which notes the data groups the Subscriber is interested in. Each Subscriber has an update function which is called by the Publisher when it sends data.

A third class keeps things organized and readable. It’s there you subscribe the Views to their Model or Models.

I searched for similar AS3 Observer implementation examples online and found but one. Hope my example helps your code find its way.

horizontal accordion component [as3]

Built a Horizontal Accordion component for the Boys & Girls Club. The Horizontal Accordion is made of different Panels, each of which automatically tab-order their child Sprites. Many Panels contain Text Input fields. Each Text Input field includes a Flex-style means to add Validation. … There’s other less-cool stuff being done all over the place too.

Am posting the major classes. All code will relate specifically to the blue Horizontal Accordion on the site.

view HorizontalAccordion class
view HAPanel class
view OnStageObject class
view TextInputMod class
view ValidatingObject class
view Validators class

object-oriented as2 development

built a game banner which published to flash 7. requirements included being <130 k with a <100 k second load.  posted it here.

have always used as2 on an as-needed basis, but decided this time to operate on it.  open it up. see how it works.  or doesn’t work. dragged as2 screaming into the year 2008. into the light.

the utility classes i found, modified, or extended are useful for anyone coming from an object-oriented background:

  • DocumentUtil allows you to specify a Document class (aka Main class). :: Ryan Taylor @ boostworthy.com
  • BezierTween creates beziers using little phrases that even Flash 7 can compile. :: Felix Turner @ airtightinteractive.com
  • MovieClipBubbler bubbles as2 MC events. it is not simpler to use than an Event Broadcaster.  it does have performance benefits over an Event Broadcaster. :: Ralf Bokelberg @ helpqlodhelp.com
  • Hitbox is an essential extension of MovieClipBubbler, at least in concept.  you should take my implementation and twist it to your ends.  using Hitbox avoids having to draw zero-alpha’d Hit areas on all your MovieClips.  in simplest execution, the MovieClip in your Library links to Hitbox (rt-click/Linkage/’Export for ActionScript’/Base Class).