Archive for September, 2008|Monthly archive page

Common AS3 Errors

Despite their seemingly over-abundance while getting started with AS3,  the new error messaging is extremely helpful and specific. While error messages are tedious at first, they eventually become extremely helpful once you understand what they mean. If you make a mistake, they tell you exactly what you did wrong.

So, here’s a short list of errors that I commonly encounter due to routine code clumsiness.

A. Compiler Errors (will prevent a movie from publishing.)

1067: Implicit coercion of type [datatype] to an unrelated type [datatype].

While the wording is fancy, the nature of this error is extremely simple: you’re trying to put a square peg into a round hole; or in technical terms, your data types don’t mesh. An example scenario that would cause this error is this:

var testing:int = new Date();

Notice the problem? The “testing” variable is typed as an “int” but is getting a “Date” object assigned to it. AS3 is very strict about data types, so will force you to make sure they always line up.

1120: Access of undefined property [name].

You’re trying to reference a value that was never created. If you get this while referencing a property of another object, you’re probably trying to access a property that is not defined as a public member of that object’s class. If you get this error in response to a value that you’ve defined within the script that you’re writing, then you probably forgot to declare the value with a “var” statement before its first reference.

1151: A conflict exists with definition [name] in namespace internal.

You’re trying to declare a value that has already been created. Make sure that you haven’t declared multiple variables by the same name within the same script. A common “gotcha” that I get hit with comes from using the same iterator for multiple loops, like so:

function errorDemo():void
{
    var list:Array = new Array(0, 1, 2);

    for (var i:int = 0; i < something; i++) {
        // do something.
    }

    for (var i:int = 0; i < something; i++) {
        // do something else.
    }
}

Notice the error? I’ve declared the “i” iterator variable with a “var” statement twice. To fix that, I’d need to use a different iterator name for the second loop, or else just declare the second iterator as “i = 0”.

B. Runtime Errors (will NOT prevent movie publishing; occur at runtime.)

Error #2006: The supplied index is out of bounds.

You’re trying to reference a depth (index) within an object’s display list that does not exist. For example, you’ll encounter this error if you call “removeChild(2);” on a display list that only has one child object. The third child that you referenced there (yes, third) does not exist. Keep in mind that display lists are zero-indexed, so the lowest item in the list has an index of “0” and the highest item in the display list has an index of “numChildren-1”.

Error #2007: Parameter child must be non-null.

You’re trying to supply a child-accessor method (addChild(), removeChild(), getChildAt(), etc) with a null object reference. An example scenario that would cause this error is this:

var child;
removeChild(child);

While the above example will compile, it will fail at runtime because the child reference is not populated with a valid DisplayObject target before being used in a child-accessor method.

Error #2025: The supplied DisplayObject must be a child of the caller.

Tricky one. The foundation principal behind this error is the definition of a parent-child relationship: a parent object contains a child object within its display list RIGHT NOW. As soon a child is removed from its parent’s display list, their parent-child relationship is broken. So, this error occurs when you perform an action like using “removeChild()” on an object that is not contained within the target’s display list. In other words, an object cannot remove a child that it does not contain. There are several patterns that you can use to avoid conflicts. Among my most common is this:

var child:DisplayObject;
if (child != null && this.contains(child))
{
    removeChild(child);
}

The above pattern will avoid both a #2007 and #2025 error, since we’ve validated that the child both exists and that it is contained within our display list before trying to remove it. Just be sure to test that the object is not null FIRST, otherwise the “contains()” operation could throw a #2007 error.

Another common cause of the #2025 error is when a child-accessor method tries to work with children that are contained within another object’s display list. It doesn’t work. Child-accessor methods only work on the callee’s own children. So, when working between object scopes, I find the most reliable method to work with child displays is to call all operations relative to the child, like so:

child.parent.removeChild(child);

In the above example, we can call this operation from any scope that has a reference to the child object, and we’re sure that the operation will target the correct parent.

Advertisements

The Singleton Pattern with AS3

Since I mentioned it in a previous article, I’ll expand upon the Singleton design pattern and cover its implementation within AS3…

First, what is it? As the name implies, a singleton is a single-instance class created within your application. Why would you want to limit a class to being instantiated only once? Quite simply, for global use. When storing a single set of values that need to be accessible to all other objects within the application (such as application settings or scores), you want to make sure that all objects are looking to the same set of source values; at which time, a singleton is your best friend.

So, how do we limit a class to a single instance that all other objects can reference? The solution is brilliantly simple: store the one, single class instance as a static member of its own class; then all other objects can reference that one instance by importing the class and referencing the static attribute. However, this begs another question… why ever create a class instance when you could just store all the singleton’s data as static members, like we do with Flash’s “Math” class? This is a good consideration, and using a static model works fine when you just need a switchboard for storing values. However, the static model does not give us all the features and flexibility that an object instance might… for example, we cannot dispatch events when values are changed without an instance of an EventDispatcher at our disposal. So, we use the Singleton pattern when we need an object instance.

Finally, implementation… The Singleton pattern has a rigid structure and is ultra-simple to set up. The basic requirements are that we have a private static member to store a class instance, a public static getter that will either return the one class instance or else create it if it does not yet exist, and finally some means of security to prevent other objects from ever being allowed to create an instance of the class. So, here it is:

package
{
    public class Singleton extends EventDispatcher
    {
        private static var _instance:Singleton;
        public static function get instance():Singleton
        {
            if (_instance == null) _instance = new Singleton(new SingletonEnforcer());
            return _instance;
        }

        public function Singleton(enforcer:SingletonEnforcer):void
        {
            super();
        }
    }
}

internal class SingletonEnforcer {}

The above is the full extent of the AS3 singleton pattern. The only tricky aspect of this pattern is the “enforcer”, which prevents other classes from instantiating our singleton. This enforcer works thanks to AS3’s ability to define private classes available only to the main packaged class. By requiring a private class as an argument of the constructor, we are effectively eliminating the ability of any other object in our application to meet instantion requirements for our singleton… Incidentally, I’d like to extend a handshake to the diabolically clever AS3 engineer out there who thought up that security measure. It is truly brilliant.

So, from the above framework you just need to flesh out the class with additional instance properties and methods that are specific to your application. To access those properties and methods from other classes, you just need to import the Singleton class, and then reference attributes as Singleton.instance.myCustomValue.

Design Patterns 101

I wrote this article for the Lassie forums, and figured it was worth posting here as well. This is a brief overview that introduces the concept of design patterns without getting into anything technical.

Design Patterns.

Google that as a search term. I’m guessing you’ll get back more techno-babble about programming than you could ever want. Design patterns can be a scary thing to read about since people are so die-hard technical about them, but the fact that you have some background and foundation understanding of them automatically knocks you up three-fold in your experience (and value) as a programmer… even if you can just barely wrap your head around them.

So first, what the heck are design patterns? Basically, think of this along the lines of painting: any tom-fool can hold a brush and swirl colored pigments around on a canvas. However, the true artists can take those colored swirls and really craft them into masterful works with style, grace, elegance, and beauty. They create something that works (ie: is visually pleasing), using a carefully constructed technique that people admire and hail as efficient and effective. So to that end, do we say that there are varying degrees of talent among painters? There most certainly are! While I think of myself as a decent painter, I am no master!

So, this exact same premise is true about programmers. Any tom-fool can copy lines of code out of tutorials. Fledglings can write their own code, but do so with the precision of a surgeon operating with a shovel. However, the Michelangelos of the programming world can conceptualize brilliant programming models that are clean, simple, efficient, expandable, etc… And at the core, they “design” code patterns to do this. This is where creativity comes into programming. Only folks to don’t understand design patterns say that programming is not an art form. So, I guess where I’m going with this is that design patterns are where programming stops being about lines of code, and more about conceptual models that just happen to utilize lines of code for their implementation. These very frequently boil down to using real-world metaphors to model a system. This is why I say that–for as bad as the later Matrix movies were–the premise of The Matrix is spot-on with OO theory; The Matrix just happens to use the ENTIRE world as a programming metaphor.

So, let’s look at a very common and basic design pattern known as “The Factory”. The factory pattern is very common for instantiating object types. Basically, we have a factory who’s job is to build products… These “products” can be anything from basic data to graphical DisplayObjects. A factory may have a single product, or multiple products. What the factory builds and returns to the customer who places an order depends on the order spec. But there’s the rub: instead of adding build-specification logic into your main program, you can just move it off into a factory. Your main program tells the factory what it needs and how many, and that factory figures out how to fulfill that order. You might even break a factory down into divisions that build multiple types of products, or you may just have multiple factories to do this. In the end, there’s no single way to do this. There are just good ways and better ways.

Nothing says that you NEED a design pattern to make an application work; in fact, most new programmers have never heard of the concept of design patterns and write plenty of functional code without them. Design patterns really aren’t a different type of code, they are just a different type of thought process… and for the most part, they tend to help tremendously in building much more robust OO applications.

In conclusion, look them up: design patterns! While there is no finite count as to the number of patterns that you can create with code, the experts in the field have narrowed it down to (as I recall) 14 foundation patterns that pretty much everything else is derived from. Two of the easiest and most handy patterns are the Singleton and the Factory. I’m also a huge fan of the Adaptor model. The Singleton is probably the single best way to get your feet wet if you’re new to design patterns because it’s extremely simple and remains useful even in larger and more advanced models.

Dynamically browsing MovieClip frame labels

Frame labels are great for keeping track of graphical states on a MovieClip timeline, but let’s face it: their usefulness was limited in AS2 due to the fact that you had to know that they existed before you could reference them. Any AS2 developer can probably think of a time in their past when they built a large state machine based on hard-coded frame labels that MovieClips would need to implement. Inevitably it didn’t matter how solid your code was in those cases; your app could–and would–still break unless you remembered to include ever silly “main”, “secondary”, and “my-cool-screen” frame label defined within code.

But there’s good news to be had here: all that has been addressed in AS3. In fact, the frame label model is unbelievably cool now! The first and most basic new feature is the MovieClip.currentLabel property. That gives us the frame label of the current timeline frame. While that may seem pretty straight forward, it’s a huge step up from AS2 where the current frame label was not available at run-time (…which always seemed like a pretty big oversight to me).

However, I think the best new feature is the MovieClip.currentLabels property, which gives an array of ALL frame labels on a timeline, along with their corresponding frame numbers. AWESOME. That means that we can quickly and easily set up a scenario that will let us browse all of a MovieClip’s labeled timeline frames at run-time. Here’s an example:

import flash.display.FrameLabel;

// _displayClip = MovieClip with timeline to access.
// _select = Flash UI ComboBox component instance.

_displayClip.stop();
_select.removeAll();
_select.addEventListener(Event.CHANGE, this._onSelectLabel);

// get and populate all of displayClip's frame labels in the select menu
for each (var j:FrameLabel in _displayClip.currentLabels)
{
    // add list items with FrameLabel object properties: name, frame.
    _select.addItem({label:j.name, data:j.frame});
}

function _onSelectLabel(evt:Event):void
{
    // update displayClip when a new frame is selected
    _displayClip.gotoAndStop(_select.selectedItem.data);
}

If you set that scenario up in a new Flash document and give the _displayClip a few frame labels to browse through, then you’ll be able to select and display the various frames in your MovieClip using the combobox (…just be sure to put different graphics on each labeled timeline frame so that you can see a change in appearance when you switch between frames!).

So, what can you do with this? I’ve used it in the new Lassie Shepherd editor so that a developer can select frame labels to display within externally loaded SWF media. It works like a charm. This would also be a good means to build a really simple navigation scheme: you’d set up and label different content frames along a timeline, load that movie into a shell, and then you could populate navigation options within the shell based on the frame labels. The beauty here is that if you ever added new content frames to the loaded media, they’d plug right into the shell movie that rendered the navigation.

Script syntax coloring for an editable TextField

Syntax coloring makes a code developer’s life much easier. For those unfamiliar with the concept, consider how ActionScript renders in shades of blue with green strings (by default) within the Flash Actions panel. That color-coding helps focus the eye on relevant keywords in the script.

As I’ve been moving forward on developing Lassie Shepherd’s script panel, I wanted to incorporate some form of syntax coloring to aid the game developer. So, I wrote up a quick class to parse and apply keyword coloring based on standard scripting syntax. Valid keywords can be assigned within the class’ static “keywords” array. Also, this generation of the script only accepts single quotes (apostrophes) as string delimiters.

1) Save as: com/gmacwilliam/parse/SyntaxColoring.as

package com.gmacwilliam.parse
{
    import flash.text.TextField;
    import flash.text.TextFormat;

    public class SyntaxColoring
    {
        public static var keywords:Array = new Array("if", "gotoAndStop", "play", "true", "false");
        public static var backgroundColor:Number = 0xFFFFFF;
        public static var foregroundColor:Number = 0x000000;
        public static var keywordColor:Number = 0x0000FF;
        public static var stringColor:Number = 0x009900;

        public static function renderField(tf:TextField):void
        {
            // apply field background color
            tf.backgroundColor = backgroundColor;

            // set field-read starting index
            var index:int = 0;

            // render all lines of text
            while(index < tf.text.length)
            {
                index = renderLine(tf, index) + 1;
            }
        }

        public static function renderLine(tf:TextField, caretIndex:int):int
        {
            // create text formats
            var colorBase:TextFormat = tf.getTextFormat();
            colorBase.color = foregroundColor;

            var colorKeyword:TextFormat = tf.getTextFormat();
            colorKeyword.color = keywordColor;

            var colorString:TextFormat = tf.getTextFormat();
            colorString.color = stringColor;

            // get start and end indicies of the current line
            var sindex:int = tf.getFirstCharInParagraph(caretIndex);
            var eindex:int = sindex + tf.getParagraphLength(caretIndex);
            eindex = Math.min(eindex, tf.text.length);

            // if paragraph has any text
            if (sindex < eindex)
            {
                // apply black default text format
                tf.setTextFormat(colorBase, sindex, eindex);

                // extract source block of text to format
                var src:String = tf.text.substr(sindex, eindex-sindex);

                // strip all parenthesis and spaces from line and split into an array
                var raw:String = src.split(" ").join("");
                raw = raw.split("(").join(",");
                raw = raw.split(")").join(",");
                var lineWords:Array = raw.split(",");
                var index:int = 0;

                // KEYWORDS
                // loop through array of line words
                for (var j:int = 0; j < lineWords.length; j++)
                {
                    var word:String = lineWords[j];

                    // color any words that match a keyword
                    if (keywords.indexOf(word) > -1)
                    {
                        index = src.indexOf(word, index);
                        tf.setTextFormat(colorKeyword, sindex+index, sindex+index+word.length);
                    }
                }

                // STRINGS
                // reset render index
                index = 0;

                while(index > -1)
                {
                    // find index of next quote
                    index = src.indexOf("'", index);

                    if (index > -1)
                    {
                        // if quote was found...
                        var qo:int = index; // quote open
                        var qc:int = src.indexOf("'", index+1); // quote close
                        var so:int = sindex+qo; // string open
                        var sc:int = (qc < 0) ? eindex : so+(qc-qo)+1; // string close

                        // apply text color to closed string or to everything after quote
                        tf.setTextFormat(colorString, so, sc);

                        // update render index with close-quote position
                        index = (qc < 0) ? -1 : qc+1;
                    }
                }
            }

            // return end-index of rendered text line
            return eindex;
        }
    }
}

Implementation of this class on a TextField is very simple, and the script is surprisingly efficient. Since AS3 can now track the caret’s line index within an editable text field, the full field only needs to be parsed and rendered once on initial load. After that, only the line containing the caret needs to be re-rendered when the field is changed. Here’s the implementation:

import com.gmacwilliam.parse.SyntaxColoring;

var color_txt:TextField; // << create an editable text field on stage
color_txt.addEventListener(Event.CHANGE, this.handleColorize);

// render field with initial formatting
SyntaxColoring.renderField(color_txt);

// handle field updates
function handleColorize(evt:Event):void
{
    SyntaxColoring.renderLine(color_txt, color_txt.caretIndex);
}

Wire it up and try entering “gotoAndStop(‘sfoo’);” in your editable TextField. It should look quite a bit like ActionScript!

Extracting class assets from an external SWF at runtime.

I find one of the single most powerful (and unbelievably cool!) new features in AS3 to be the ability to extract classes at runtime from an externally loaded SWF movie. I was really excited to take advantage of the feature while implementing the Lassie engine‘s new library system, which works by dynamically pulling classes out of an externally loaded SWF library and then composing them into a game layout on the fly. Now this process can be a bit cumbersome without helper methods; and in the case of a large dynamic asset management framework like Lassie, I’ve found it most convenient to just to standardize the SWF library publishing method for quick, easy, and reliable class accessibility.

So, the goal here is to create standardized SWF packaging with easily extractable class assets. That packaging should allows us to quickly read the class contents of the SWF and then to grab them out without hassle. As such, the logical place to start here is with an interface. So, here it is:

*Save as: com/lassie/lib/IMediaLibrary.as

package com.lassie.lib
{
    public interface IMediaLibrary
    {
        function get contents():Array;
        function getAsset(className:String):*;
    }
}

That interface gives us the ability to get “contents” which will return an array of class names that are contained within the library. We can then feed those class names (listed in the contents array) into the “getAsset()” method to retrieve an instance of that class. Now for the actual MediaLibrary class, which gets assigned as a document class to the library FLA document.

*Save as: com/lassie/lib/MediaLibrary.as

package com.lassie.lib
{
    import flash.display.MovieClip;

    public dynamic class MediaLibrary extends MovieClip implements IMediaLibrary
    {
        public function MediaLibrary():void
        {
            super();
        }

    // --------------------------------------------------
    //  Include a library media class
    // --------------------------------------------------

        public function addClass($class:Class, $path:String=""):void
        {
            if (($path.split(".")).length > 1)
            {
                this[$path] = $class;
            }
            else
            {
                var $cname:String = $class.toString();
                this[$cname.substr(7, $cname.length-8)] = $class;
            }
        }

    // --------------------------------------------------
    //  Get library contents (lists class names)
    // --------------------------------------------------

        public function get contents():Array
        {
            var classList:Array = new Array();
            for (var j:String in this)
            {
                classList.push(j);
            }
            classList.sort();
            return classList;
        }

    // --------------------------------------------------
    //  Extract library class asset
    // --------------------------------------------------

        public function getAsset(className:String):*
        {
            try
            {
                var classObj:Class = this[className];
                return new classObj();
            }
            catch(e:Error)
            {
                trace("error extracting requested class.");
            }
            return null;
        }
    }
}

That document class implements the two interface methods, plus gives us one additional feature: to add classes to the library. Classes are added with the “addClass()” method, which takes a reference to the class object and an optional string of the class’ fully qualified path. You can add classes from the first-frame timeline actions of the library FLA’s root timeline. To add a class:

addClass(com.project.MyMovieClip, "com.project.MyMovieClip");

Or if the class is unpackaged and has no class path, you can add it by direct reference (the class’ “toString()” value is logged as the path):

addClass(MyMovieClip);

Assuming that your MediaLibrary document publishes without errors, you can load it into another movie, get the MediaLibrary’s list of contents, and then start requesting those assets out of it with ease. The load/retrieval script goes something like this:

var libLoader:Loader = new Loader();
// ... load your library SWF into the current movie ...
var lib:IMediaLibrary = libLoader.content as IMediaLibrary;
var mc:MovieClip = lib.getAsset(lib.contents[0]) as MovieClip;

Fun!

AS3 Key.isDown() behavior

Some game developers may have noticed that the Key.isDown() method is absent in AS3… which is a rather unhandy omission for developers trying to build a game with keyboard controls for avatar movement. Rather than just knowing when a key is pressed, you need to be able to check to see if the key is STILL pressed each frame. I’m not sure if Adobe deemed the Key.isDown() method as bad form or if they just figured that the average developer is smart enough to manufacture a replacement solution for it. Either way, here’s a AS3 replacement for those who miss it. You can call this test as: “isKeyPressed(keyCode);”

import flash.events.KeyboardEvent;
import flash.ui.Keyboard;

var _keys:Array = new Array();
stage.addEventListener(KeyboardEvent.KEY_DOWN, this.handleKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, this.handleKeyUp);

function handleKeyDown(evt:KeyboardEvent):void
{
    if (_keys.indexOf(evt.keyCode) == -1)
    {
        _keys.push(evt.keyCode);
    }
}

function handleKeyUp(evt:KeyboardEvent):void
{
    var i:int = _keys.indexOf(evt.keyCode);

    if (i > -1)
    {
        _keys.splice(i, 1);
    }
}

function isKeyPressed(key:int):Boolean
{
    return _keys.indexOf(key) > -1;
}

Writing Images out of Flash

There was a question on the forums recently about how to save/write an image out of Flash as a valid image file (such as a JPG or PNG). Ironically enough, this has come up in my office several times recently, so a couple weeks ago I built some resources to automate the process.

First off, we need the ability to write files out of Flash. As of Flash Player 10, we’ll be able to do this directly (hurray!). However, in the meantime we’re still dependent on a server-side technology like PHP. So, let’s get that out of the way first. Save the following script to a PHP enabled server at a publicly enabled URL:

<?php
    // com.gmacwilliam.images.ImageCaptureService
    // PHP file service.

    if (isset($_POST['tempfile']))
    {
        $temp = $_POST['tempfile'];
        $target = $_POST['newpath'];
        rename($temp, $target);
        echo "complete!";
    }
    else
    {
        $temp = "temp";
        $fp = fopen( $temp, 'wb' );
        fwrite( $fp, $GLOBALS[ 'HTTP_RAW_POST_DATA' ] );
        fclose( $fp );
        echo $temp;
    }
?>

The above is a dirt simple file-write script that I threw together in a couple minutes. Feel free to improve upon it with validation, type-checking, size restrictions, etc. And of course, nothing says that this file-write process needs to be done with PHP. Any server-side scripting language will work.

So, that gives us a place to send formatted image data to be written. Now we need to capture and encode image data within Flash. For encoding, we need the image resources provided in Adobe’s AS3 Corelib, available for free at: http://code.google.com/p/as3corelib/. Download the corelib and place the source in your script library.

Lastly, we need some logic to capture an image, send it through the encoder, then post the resulting data to our PHP service. To automate this process, I wrote a small class library. The package (com.gmacwilliam.images) contains one service abstract and two concrete service classes. Both the JPG and PNG capture classes are instantiated with a reference to the DisplayObject that you want to save an image of, and a file location on the server at which to place the file (the location should be formatted as: “path/filename.ext”. The “path/” value is relative to the PHP script’s location).

1) save to: com/gmacwilliam/images/ImageCaptureService.as
Note: update the “imageServiceURL” variable with the path to your PHP script.

package com.gmacwilliam.images
{
    import flash.events.EventDispatcher;
    import flash.events.Event;
    import flash.utils.ByteArray;
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    import flash.net.URLRequestMethod;
    import flash.net.URLVariables;

    public class ImageCaptureService extends EventDispatcher
    {
        public static const FILE_WRITE_COMPLETE_EVENT:String = "ImageFileWriteComplete";
        public static var imageServiceURL:String = "http://your-image-service-path.php";

        private var _servicePath:String="";
        private var _filePath:String="";

        public function ImageCaptureService(filePath:String=""):void
        {
            super();
            _servicePath = ImageCaptureService.imageServiceURL;
            _filePath = filePath;
        }

        /* write
         * @desc: Writes image data to file.
         * @param: image data byte array.
         */

        protected function write(img:ByteArray):void
        {
            // configure data to send
            var req:URLRequest = new URLRequest(_servicePath);
            req.contentType = "application/octet-stream";
            req.method = URLRequestMethod.POST;
            req.data = img;

            // send data to file service
            var write:URLLoader = new URLLoader();
            write.addEventListener(Event.COMPLETE, this._onWriteComplete);
            write.load(req);
        }

        private function _onWriteComplete(evt:Event):void
        {
            // cleanup write operation
            var write:URLLoader = evt.target as URLLoader;
            write.removeEventListener(Event.COMPLETE, this._onWriteComplete);
            dispatchEvent(new Event(ImageCaptureService.FILE_WRITE_COMPLETE_EVENT));

            // move created file to target location
            _moveFile(write.data);
        }

        /* _moveFile
         * @desc: Moves created file to target location.
         * @param: reference to newly created file on server.
         */

        private function _moveFile(tempFile:String):void
        {
            var vars:URLVariables = new URLVariables();
            vars.tempfile = tempFile;
            vars.newpath = _filePath;

            var req:URLRequest = new URLRequest(_servicePath);
            req.method = URLRequestMethod.POST;
            req.data = vars;

            var moveto:URLLoader = new URLLoader();
            moveto.addEventListener(Event.COMPLETE, this._onMoveComplete);
            moveto.load(req);
        }

        private function _onMoveComplete(evt:Event):void
        {
            var moveto:URLLoader = evt.target as URLLoader;
            moveto.removeEventListener(Event.COMPLETE, this._onMoveComplete);
            dispatchEvent(new Event(Event.COMPLETE));
        }
    }
}

2) save to: com/gmacwilliam/images/JPGCapture.as
Implementation: new JPGCapture(clipToCapture:DisplayObject, filePath:String, [quality:int=0-100]);

package com.gmacwilliam.images
{
    import flash.display.DisplayObject;
    import flash.display.BitmapData;
    import com.adobe.images.JPGEncoder;

    public final class JPGCapture extends ImageCaptureService
    {
        public function JPGCapture(clip:DisplayObject, filePath:String="", quality:int=50):void
        {
            super(filePath);
            var jpg:JPGEncoder = new JPGEncoder(quality);
            var bmp:BitmapData = new BitmapData(clip.width, clip.height, false, 0xFFFFFF);
            bmp.draw(clip);
            write(jpg.encode(bmp));
        }
    }
}

3) save to: com/gmacwilliam/images/PNGCapture.as
Implementation: new PNGCapture(clipToCapture:DisplayObject, filePath:String);

package com.gmacwilliam.images
{
    import flash.display.DisplayObject;
    import flash.display.BitmapData;
    import com.adobe.images.PNGEncoder;

    public final class PNGCapture extends ImageCaptureService
    {
        public function PNGCapture(clip:DisplayObject, filePath:String=""):void
        {
            super(filePath);
            var bmp:BitmapData = new BitmapData(clip.width, clip.height, true, 0x00000000);
            bmp.draw(clip);
            write(PNGEncoder.encode(bmp));
        }
    }
}

This was a pretty fast and unrefined implementation that I threw together while bidding a project with this technology. As such, there’s some redundancy in the server communication. This service currently makes two server calls: one to post the data and a seperate call to move the file since I was running into problems with putting text and bianary data in the same server post. I remember reading something on Grant Skinner’s blog a while back about mixing data formats in a server post, so I’ll have to look that up and post and updated version once these service calls have been consolidated.