Archive for the ‘Flash’ Category

The dropTarget conspiracy

Wednesday, May 7th, 2008
While working on an application that has some drag and drop functionality, I noticed something very interesting about the dropTarget property of the Sprite class. It seems that the dropTarget returns the DisplayObject that is at the bottom of the display list which may not yield the result you are expecting. I added a MouseEvent.MOUSE_MOVE event listener to the Sprite being dragged and traced out the dropTarget to see what kind of result I would get.

Instead of seeing the names of Sprite instances that were set-up on the timeline, the trace output was nothing but generic names such as instance42. The reason for this is that the object at the very bottom of the display list is not the Sprite that was created, but the contents of that Sprite such as a Shape or Bitmap. It seems that the Flash Player automatically creates a DisplayObject for these internal Sprite elements and assigns them a unique instance name. Tracing out the dropTarget.parent then reveals the DisplayObject that we're looking for. One thing to note is that a Sprite that only has visual elements that were created with the drawing API will not exhibit this behavior.

There are a couple of other things to be aware of when using the dropTarget. First, setting the mouseEnabled or mouseChildren properties to false will not keep a DisplayObject from being assigned to the dropTarget property. Second, depth has no effect on the assignment of a DisplayObject to the dropTarget propery. Objects at a higher depth than the object being dragged will react the same way as those that are under it. Third and probably the most important is that the assignment of the value for the dropTarget property is that of the DisplayObject that is directly under the mouse and has nothing to do with the bounding box of the DisplayObject being dragged. Lastly, there are definitely situations where the dropTarget will be null, so be sure to check for that before trying to access properties of the dropTarget or you'll get everyone's favorite error - TypeError: Error #1009: Cannot access a property or method of a null object reference.

example:
import flash.events.MouseEvent;
import flash.display.Sprite;

dragee.addEventListener(MouseEvent.MOUSE_DOWN,mouseDownHandler);
dragee.addEventListener(MouseEvent.MOUSE_UP,mouseUpHandler);
addEventListener(MouseEvent.MOUSE_MOVE,mouseMoveHandler);

function mouseDownHandler(evt:MouseEvent):void {
    dragee.startDrag();
}

function mouseUpHandler(evt:MouseEvent):void {
    dragee.stopDrag();
}

function mouseMoveHandler(evt:MouseEvent):void {
    if (dragee.dropTarget!=null) trace(dragee.dropTarget.name);
}
May the Null Object be your Friend.

Losing scope within a class

Wednesday, April 30th, 2008
Maintaining scope while writing object orientated code in Flash isn't always easy. Let's say you are loading some XML within a method in a class as in the following example:
class ExampleClass {
  var xml:XML;

  public function ExampleClass() {
    xml = new XML();
    xml.load(data.xml);
  }
}
When the XML is done loading it is handled by a method on the XML class that the developer is meant to define such as:
xml.onLoad = function { // do something with the XML. }
Well, what if you want to do something within the context of the compositing class (ExampleClass) at this point. Any code that you put within the onLoad function definition will execute within the scope of the XML object and not your class. The XML object also has no reference to the parent class like a MovieClip does and you can not dynamically add properties to the XML object like a MovieClip either which would allow you to make an internal reference to the compositing class.

Fortunately Flash provides a really cool component for maintaining scope. Most developers don't even know this exists because it is a component and not listed with the main ActionScript Classes. The mx.utils.Delegate class will allow you to define the onLoad function, but within the scope of whatever object you specify. Let's see an example:
import mx.utils.Delegate;
class ExampleClass {
  var xml:XML;

  public function ExampleClass() {
    xml = new XML();
    xml.onLoad = Delegate.create(this,onXMLLoad);
    xml.load(data.xml);
  }

  private function onXMLLoad(success:Boolean):void {
    // this code will now execute within the scope
    // of the ExampleClass class.
  }
}
This works great in a variety of situations such as:
- adding event listeners
- defining event handlers like onRelease on child MovieClips of a class
- LoadVars
- NetStream

This is no longer a problem in AS3 because scope is automatically remembered which makes life a lot easier. Once you start using the Delegate class, you'll never know how you got along with out it.

Remoting for everyone

Monday, February 11th, 2008
Adobe opens up Flash Remoting (aka BlaszeDS) and the AMF protocol. How awesome is that? I've been a long time Remoting user and think it's the best way to go when you need data from a server. Although Adobe's offering is Java based, there are some really good PHP, .Net and other distributions. For more information on these check out The MidnightCoders, AMFPHP and OpenAMF.

Dispatching events between AS2 and AS3

Wednesday, February 6th, 2008
Even though AS3 has been out for some time now, there are still situations when you will need to load an AS2 compiled SWF into an AS3 compiled SWF and communicate with it. A good example would be if you need to use the ActionSource component for Omniture tracking or some other AS2 based Flash component in a Flash 9 or Flex 2 project. Well, what if you could simply dispatch an event and listen for it on the other side? That's what ASBridge does.

ASBridge consists of 4 classes, ASBridge and ASBridgeEvent classes for both AS2 (cookiejar package) and AS3 (sugarcookie package). The core idea of ASBridge comes from the Adobe LiveDocs LocalConnection entry, check out the second paragraph where it says that AS 1,2, and 3 can communicate with each other using a LocalConnection, that's where the magic is. Only thing to really be aware of is the 40kb limit on the amount of data that can be passed as arguments to the send() method.

Displayed below is the source code for the ASBridge_Example class which is the main class for the AS3 Project and the AS2_ASBridge class used in the Flash 8 Fla with brief descriptions. To get all the source code including the ASBridge classes for both AS2 and AS3, download all the source as an Eclipse ActionScript 3 Project.

To use the ActionScript 3 Project zip:
- unzip file anywhere
- open Eclipse
- File -> Import, choose Existing Projects into Workspace and click next
- browse for the root of the extracted directory
- click Finish

ASBridge_Example
Demonstrates loading a AS2 SWF into an ActionScript 3 Project generated SWF and using ASBridge to send and receive events with data between AS3 and AS2.

package {
    import com.sugarcookie.adapter.ASBridge;
    import com.sugarcookie.adapter.events.ASBridgeEvent;
    
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.URLRequest;

    public class ASBridge_Example extends Sprite {
        private var _adapter:ASBridge;
        private var _loader:Loader;
        
        public function ASBridge_Example() {
            _adapter = ASBridge.getInst();
            _adapter.addEventListener("onAdapterReady",onAdapterReady);
            
            _loader = new Loader();
            _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
             var request:URLRequest = new URLRequest("AS2_ASBridge.swf");
            _loader.load(request);

            addChild(_loader);
        }
        
        private function onLoadComplete(evt:Event):void {
            trace("onLoadComplete: "+evt.toString());
        }
        
        private function onAdapterReady(evt:ASBridgeEvent):void {
            trace("successfully received event with data from AS2");
            trace("onAdapterReady: "+evt.toString());
            _adapter.sendEvent("onBridgeComm",{id:"test data"});
        }
    }
}

AS2_ASBridge
Demonstrates sending and receiving events with data between AS2 and AS3 implemented as a class that is instantiated on the timeline of a Flash 8 Fla.
import com.cookiejar.adapter.ASBridge;
import com.cookiejar.adapter.events.ASBridgeEvent;

class AS2_ASBridge {
    private var _adapter:ASBridge;
    
    public function AS2_ASBridge() {
        _adapter = ASBridge.getInst();
        _adapter.addEventListener("onBridgeComm",this);
        _adapter.sendEvent("onAdapterReady",{status:true});
    }
    
    private function onBridgeComm(evt:ASBridgeEvent):Void {
        trace("successfully received event with data from AS3");
    }
}

Flex 2 and Flash 9 play nice
with DisplayObjectWrapper

Wednesday, October 17th, 2007
If you're a Flash developer making the switch to start using Flex, then this class from Grant Skinner is for you. DisplayObjectWrapper makes life much easier by enabling developers to easily get anything that inherits from DisplayObject (Sprite, Loader and Bitmap to name a few) to become a display child of a Flex container (Canvas, ViewStack, Accordion, etc). Awesome, now here are some code examples of how to work with SWFs in Flex 2.

This mxml file shows how to:
- load a Flash 9 SWF
- call a method within the document class of the SWF
- receive an event from the loaded SWF

One thing to keep in mind is the Flex security model. When you compile a Flex application it is by default set to be in the local-with-networking sandbox and the default for Flash 9 is local-with-filesystem which means the Flex application will not load the SWF when run locally. You will have to change the Local playback security setting in the Publish Setting window to Access Network Only.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" horizontalAlign="center" verticalAlign="middle" applicationComplete="init();">
    <mx:Script>
        <![CDATA[
            import com.gskinner.ui.DisplayObjectWrapper;
            import flash.display.Loader;
            import flash.events.*;
            import flash.net.URLRequest;
            import flash.system.ApplicationDomain;
            import flash.system.LoaderContext;
            
            private var loader:Loader;
            private var loadedSWF:DisplayObject;
            
            private function init():void {
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
                
                loader = new Loader();
                configureListeners(loader.contentLoaderInfo);
                
                var context:LoaderContext = new LoaderContext();
                context.applicationDomain = ApplicationDomain.currentDomain;
                var request:URLRequest = new URLRequest("fnine.swf");
                loader.load(request,context);
            }
            
            private function configureListeners(dispatcher:IEventDispatcher):void {
                dispatcher.addEventListener(Event.COMPLETE, completeHandler);
                dispatcher.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
                dispatcher.addEventListener(Event.INIT, initHandler);
                dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
                dispatcher.addEventListener(Event.OPEN, openHandler);
                dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
                dispatcher.addEventListener(Event.UNLOAD, unLoadHandler);
            }
            
            private function completeHandler(event:Event):void {
                trace("completeHandler: " + event);
                //add the loaded swf to the display list
                loadedSWF = loader.content;
                displayArea.addChild(new DisplayObjectWrapper(loadedSWF));
                
                //listen for an event from the loaded SWF
                loadedSWF.addEventListener("fnineEvent", onFnineEvent);
                //call a method on a loaded SWF
                loadedSWF["testCall"]();
            }
            
            private function onFnineEvent(evt:Event):void {
                trace("onFnineEvent: " + evt);
            }
    
            private function httpStatusHandler(evt:HTTPStatusEvent):void {
                trace("httpStatusHandler: " + evt);
            }
    
            private function initHandler(evt:Event):void {
                trace("initHandler: " + evt);
            }
    
            private function ioErrorHandler(evt:IOErrorEvent):void {
                trace("ioErrorHandler: " + evt);
            }
    
            private function openHandler(evt:Event):void {
                trace("openHandler: " + evt);
            }
    
            private function progressHandler(evt:ProgressEvent):void {
                trace("progressHandler: bytesLoaded=" + evt.bytesLoaded + " bytesTotal=" + evt.bytesTotal);
            }
    
            private function unLoadHandler(evt:Event):void {
                trace("unLoadHandler: " + evt);
            }
        ]]>
    </mx:Script>
    <mx:Canvas id="displayArea" width="500" height="300" backgroundColor="0xFFFFFF" />
</mx:Application>

Also noteworthy is that the DisplayObjectWrapper is actually the parent of the loaded SWF. In very simplistic terms the display hierarchy is Flex Application > Container > DisplayObjectWrapper > SWF.

This class is the Document class for the SWF.
package {
    import flash.display.Sprite;
    import flash.events.Event;
    
    public class fnineApp extends Sprite {
        public function fnineApp() {
            trace("fnineApp.swf constructor");
        }
        
        public function testCall():void {
            trace("testCall() method called on fnineApp.swf");
            dispatchEvent(new Event("fnineEvent",true));
        }
    }
}
This basic idea will allow you to do all kinds of fun stuff. Enjoy.

WebOrb Standard, FMS developer, etc…
No excuse not to learn

Tuesday, July 24th, 2007
Did you know that some of the most amazing server-side software for Flash is available for free? Most sever software products are available to developers for free with a 5 IP connection limit, but are full featured. Even with this limitation there are more than enough connections to be useful for learning how to take advantage of protocols like AMF and RTMP in your Flash applications.

You’ll probably want to set up a server as well, so re-purpose that old PC and install Linux on it to provide a separate server environment from your local development environment. Red Hat offers the latest version of it’s OS as Fedora Core, it’s easy to install, set-up and manage without having to do to much command-line.

Get your free software here:
Fedora Core
Flash Media Server
LiveCycle Data Services ES Express
WebOrb

Now there are no more excuses for not knowing how to use these tools to make your Flash as awesome as it can be. Having the skills to uses these tools is what could get you hired on my team! Good luck and happy coding.

SWFAddress helps make Flash applications
Search Engine compatible

Friday, July 20th, 2007
Flash has always suffered from being a black box to search engines. Even if SWFs were readable by search engines it wouldn’t help because any respectable RIA these days gets its content related data elsewhere. At the very minimum the content is stored in XML file(s) that don’t follow any kind of standard or in a database, both of which lock away your content from search engines. And if that weren’t enough, most Flash applications only have one HTML page and that doesn’t exactly increase your chances of a good ranking, no matter how good your alternate content and meta tags are.

Thankfully there are things like SWFAddress that can really make a difference in the SEO battle. SWFAddress allows you to have independent urls and titles for every page in your Flash site along with providing a mechanism for deep linking. Downloading SWFAddress gets you AS classes for all three flavors, the SWFAddress JavaScript file and a variety of excellent examples.

Combine this with the Sitemap Protocol and now we’re cooking with fire!

OnEnterFrameBeacon rocks, Yo!

Tuesday, July 10th, 2007
If I would have only know about this sooner - damn. You can do some really cool things with this and helps to break your MovieClip dependence. I found this article and it got me started. Based on what I learned I created this class based version.

import mx.transitions.OnEnterFrameBeacon;

class NonMovieClipEnterFrameHavingClass {
  public function NonMovieClipEnterFrameHavingClass() {
   OnEnterFrameBeacon.init();
   MovieClip.addListener(this);
  }

  public function onEnterFrame():Void {
   trace("OnEnterFrameBeacon, Yo!");
  }
}

How to delete a Singleton

Tuesday, June 26th, 2007
Add this to the MySingleton class in the previous post and add the ability to clear out a Singleton.
public static function kill():Void {
 inst=null;
}

How to extend a Singleton

Saturday, June 23rd, 2007
The answer is easier than you think. If you stop and ponder how extending a class works, it makes sense that when the subclass calls super() that it works since it’s just a plain old constructor, except that it’s private, but that doesn’t have any effect in this situation. Basically you side-step the static getInst() call. Here’s an example:
class MySingleton {
 private static var inst:MySingleton=null;
 private fucntion MySingleton() {}
 public static function getInst():MySingleton {
  return MySingleton(inst?inst:inst=new MySingleton());
 }
}
Now let’s extend that:
import MySingleton;
class MyExtendedClass extends MySingleton {
 public function MyExtendedClass() {
  super();
 }
}
That’s it, it’s really that easy. Stay tuned for how to kill a Singleton.

Working with Flex 2/AS3 will influence your AS2 development

Wednesday, June 13th, 2007
There are a lot of really great features within Flex 2 that Flash developers dream of having, but few know they already exist. When I moved to Flex 2 from Flash based AS2 development it was nice to see some native classes that had similar functionality to those that I had developed for my AS2 class library. In fact it gave me some really great ideas on how to improve some of my AS2 classes and even develop others from scratch. It's not too hard to emulate portions of the Flex 2 framework within AS2.

Once you start to use Flex 2 classes like the ArrayCollection, ObjectUtil and Logger it will be easy to see why you should take the time to make this functionality available to you in AS2. Be sure to peruse the Flex 2 Language Reference for some good ideas. You'll also probably want to start using Eclipse for your AS2 development, if so you should check out ASDT or FDT.

The reality for most Flash developers that are getting into Flex 2 or AS3, is that you will continue to have to do both AS2 and AS3 for some time to come. It would be great if the adoption rate of new Flash versions by clients would be as fast as the plug-in. But don't forget, there are still poor soles that are required to develop in Flash 6. Let's give them a moment of silence...

Testing Flash and Flex Applications

Friday, May 4th, 2007
I was on a call today with a client and their hosting vendor discussing the finer technical points of a new Flex 2/Flash 9 project that we are working on and the topic of load testing came up. The hosting vendor talked about load testing Flash as if it was something that was always done. I never really gave it much though before, normally I would just load test the server-side services and any other code that my Flash/Flex applications would connect to and figured that was all that could be done. Besides, does load testing even apply to code running in a browser? Where does the load come from if there is only one user? Where I work we would call this monkey clicking if anything. Monkey clicking is where the user clicks much faster than the developer would expect them to. Most sites built with Flash can be broken this way and is considered by my team the pinnacle of ActionScript development - to have a site that can survive monkey clicking.

So what are all the ways that a Flash/Flex application can be tested? First and foremost there is good old QA. There is no better substitute for a good QA a person, especially one that really understands how to properly test a Flash or Flex application. We were lucky enough to find someone who not only had previous experience QA'ing Flash, but was also an ex-game tester. Video games actually have a lot in common with Flash interfaces, something to consider when hiring a new QA person. The QA persons job is to test for monkey clicking, making sure links go to the right place, forms work properly with validation and tabbing, animations are doing what they are supposed to and so on.

Second is unit testing. Wikipedia describes the benefits of unit testing as: The goal of unit testing is to isolate each part of the program and show that the individual parts are correct. A unit test provides a strict, written contract that the piece of code must satisfy. As a result, it affords several benefits. This is a great way to go, especially if you use a class library in all of your projects. By using reusable code that has been throughly tested, you effectively reduce the amount of QA needed for any project that uses your library because you can have very reliable nut and bolts to build with. If you don't have your own application and/or architectural framework to build upon there are many to choose from, such as Cairngorm and As2lib.

Third is load or stress testing. There are many tools that can be used to test your PHP, .NET, JAVA or whatever your using, but what about ActionScript? A good load testing program will "record" a users actions and then play them back over and over to simulate multiple users at once. This might work for an HTML based site, maybe Silverlight will do better with this, but Flash is somewhat of a black box in this department. So far I have not found anything to simulate a user within a Flash application. Sure I could write a special testing application in ActionScript to make calls to the server in the same way that my application does, but is this cost effective? I think the problem lies in the fact that every Flash application is created with it's own custom logic, unlike HTML where everything is built with the same components. Links, buttons and forms will always work the same in HTML, but not true in Flash - maybe Flex. There is a load testing framework for Flex, but it mostly concentrates on load testing Flex Data Services and can be found on Adobe Labs. Even this uses a special application to simulate the calls to the server and not the actual application you created.

As in most interactive marketing based work, especially those that are built in Flash, things like QA, unit testing and load testing don't get done or gets very little time because of poor scoping, budget, project delays or little understanding for the importance of testing. It's a constant fight for us developers, sometimes I think we're the only ones who consider what we do is actually software development and not just brochureware. My previous boss (who was the GM of our office) actually ridiculed me in front of all the senior managers in our office because I tried to make this point, which ended up being the beginning of the end for me at that job. I realized that my methodologies on web development would never be taken seriously, hence I would not get the time and resources to do the job right, so I left and got a new job. Too bad for them, she was pissed when I left. I guess that makes my point as clear as possible.

Preparing for ActionScript 3

Thursday, May 3rd, 2007
We're about to start some pretty big projects for some great clients and best of all they are going to be Flex 2/Flash 9. It's nice to have clients that want to use the latest and greatest just because they are. They scary part is that we have a lot to learn in short period of time, so I thought I would share what we're doing to ramp up for the challenge. Mainly there's a lot of reading. Here's a few titles that are already available at your book store that are always worth the cover price.
  • ActionScript 3.0 Cookbook:
    Solutions for Flash Platform and Flex Application Developers
  • Foundation Actionscript 3.0 Animation: Making Things Move!
As usual not all the classics are out yet, mainly Colin Moock's book. But there is a ray of hope and a way to get it before it comes out. O'Reilly has this new feature called 'Rough Cuts' that allows you to get PDF versions of upcoming releases well before they come out. Go to www.oreilly.com, search for the following titles and buy the Rough Cuts. It costs $9.99 to start which gets you the PDF of the book in it's current iteration. When it comes out you get charged the remaining price of the book and it ships to you. The best part is that you can give feedback to the authors and potentially help shape the final outcome of the book. Here's the one's that I got:
  • ActionScript 3.0 Design Patterns
  • Essential ActionScript 3.0
  • Programming Flex 2.0
There are also a fair amount of sites that have great information, but here is one that I found particularly interesting that a co-worker sent to me. http://actionscriptcheatsheet.com/blog/quick-referencecheatsheet -for-actionscript-20/

This is also a good resource by Adobe:
http://livedocs.adobe.com/flex/2/langref/migration.html

As we get more into the development of our projects I'll post more about our experiences, sample code and eventually the sites themselves.