Everything listed under: AS3

  • AS3 - Dynamic Text with Embedded Font for Nice Smooth Text , Animation, Rotation, Alpha, Fading, etc

    Dammit again, Adobe.
    Where are the Convenience Functions?

    As usual I will start out by bashing adobe for creating this pain in the ass. I don't know what happened at adobe labs but somewhere in the remake of Flash's text rendering engine for AS3 (which was an awesome improvement, no doubt), convenience functions were apparently forgotten completely and thus it takes like 15 lines of code to get 1 line of decent dynamic text going... and embedding fonts, well, that's just plain weird unless you're using the Flash IDE.

    Oh well- here's a quick how-to for dynamically getting text on stage rotating with a nice font, in FlashDevelop.

    .embedFonts = true or Text is Un-Fun and Ugly

    Basically, to fade, rotate, or even just display nicely aliased text dynamically with the FlexSDK (I'm using Flash Develop + FlexSDK) you need to embed the font to compile with the SWF and assign it to a class name (see code comments below (this is my FlashDevelop / AS3 way of doing this) . Then, in your actionscript, you need to make sure that the textfield has the following pseudo-code equivalents:

    1. textfield's .embedFonts = true
    2. textfield's .antiAliasType = ADVANCED (see code below)
    3. your text format object needs to have .font set to the class name associated with your font.
    4. set textfield's text format object to format object with desired font after ANY change to the text in the textfield (will reset format on change of text string)

    Other ways to load embedded fonts

    There are other methods of going about this.  One worth noting that has worked well for me before, is to create a SWF for each font and load / use them as text containers dynamically, setting the text on the text box placed on stage with the Flash IDE ( i.e. loadedFontMC.textBox.text = "look aliased text!").  This is a somewhat sloppy way to get flash to embed a font, but it's a cool way to support LOTS of fonts externally without compiling them into and bloating the SWF.  This way, you don't have to preload them all just to run the app- plus using the Flash IDE is easy to choose the character sets from the  Flash properties menu and do more with the mouse than with code...

    However, I find that for most purposes you only need 1 or 2 nice embedded fonts to cover all content and titles.  For that type of purpose, I prefer this dynamic style method as it is pure AS3 + actual font .ttf files, and has no other dependencies on external files.  Wrap this up in a nice class for yourself so you can just pass a font name as a parameter and don't have to deal with this again.  Maybe I'll post something like that soon... until then:

    A Simple Demo Class Ready for FlashDevelop

    You will, as usual, need the FlexSDK downloaded on your computer and attached to your project either by classpath, flexSDK settings in program settings, or by attaching .swc to your project library... take your pic.

    Here's a full Main.as class that you can drop into a pure AS3 FlashDevelop project src/ directory and get your embedded font tested / working. Then, you can copy and paste the working code into your other projects.  Follow the instructions in the comments for adding the actual font's .ttf file to your lib/ directory (could be any directory really as long as the path is correct in your embed tag).

    ** Please note that this will embed the whole font into your compiled SWF (all crazy characters included).  To greatly reduce the size of the font added to the SWF, look into specifying the character set using the Embed tag and just embed the characters you need (like A-Z 0-1 and punctuation, not all the unnecessary German umlauts and whatnot).

    "Embed Font and Rotate Test" 
    Main.as Source:

    package 
    {
    	import flash.display.DisplayObject;
    	import flash.display.Sprite;
    	import flash.events.Event;
    	import flash.events.TimerEvent;
    	import flash.text.AntiAliasType;
    	import flash.text.TextField;
    	import flash.text.TextFieldAutoSize;
    	import flash.text.TextFormat;
    	import flash.text.TextFormatAlign;
    	import flash.utils.Timer;
    	
    	/**
    	 * This is a simple font embedding test that rotates the text to show if embedding worked properly.  
    	 * start by creating a new flash develop project and replacing the contents of the Main.as file with this entire source code
    	 * 1) Right click the "lib" folder in the project tab and then pick a font from your fonts folder.  
    	 * 2) Once the font file is added to the project view lib/ folder, right click the font and choose "Insert Into Document" to generate the basic Embed tag
    	 * 3) add the fontFamily="FontClassName" to the embed tag properties and no semi colon at the end of the line so it will link to the next line
    	 * 4) Add your class variable on the next line like... ((( public var FontClassName:Class; ))) with the same name as fontFamily
    	 * 5) Use any textField.embedFonts and textFormat.font = FontClassName to set the font.
    	 * 6) Rotation test below will demonstrate if it worked or not, non-embedded fonts will not rotate (will just disappear and not render until rotation is 0 again)
    	 * @author One Giant Media
    	 */
    	public class Main extends Sprite 
    	{	
    		//[Embed(source = '../../..some_path_use_FD_AddToProject_RCmenu../FDproject/lib/FooFont.ttf', fontFamily="FooFont")]
    		[Embed(source='../lib/GOTHIC.TTF', fontFamily="FooFont")]
    		public var FooFont:Class;
    		
    		private var _textField:TextField;
    		
    		public function Main():void {
    			if (stage) init();
    			else addEventListener(Event.ADDED_TO_STAGE, init);
    		}
    		
    		private function init(e:Event = null):void {
    			removeEventListener(Event.ADDED_TO_STAGE, init);
    			// entry point
    			
    			// create text
    			_textField = createTestText("test some text here");
    			
    			// rotation test
    			var rotateIt:Timer = new Timer(1 / 28);
    			rotateIt.addEventListener(TimerEvent.TIMER, rotateText);
    			rotateIt.start();
    		}
    		
    		public function createTestText($text:String):TextField {
    			var t:TextField = new TextField();
    				t.antiAliasType = AntiAliasType.ADVANCED;
    				t.embedFonts = true;
    				t.autoSize = TextFieldAutoSize.LEFT;
    				t.text = $text;
    				t.x = stage.stageWidth / 2;
    				t.y = stage.stageHeight / 2;
    				
    			var f:TextFormat = new TextFormat();
    				f.font = "FooFont";
    				f.align = TextFormatAlign.CENTER;
    				f.color = 0x333333;
    				f.size = 28;
    				
    			t.setTextFormat(f);
    			
    			return addChild(t) as TextField;
    		}
    		
    		private function rotateText(e:TimerEvent = null):void {
    			_textField.rotation++;
    		}	
    	}
    }
    

  • The Best Animation Engine for Flash / Flex - A Developer's Must-Have for Actionscript

    This is one of those things that is so good, you almost want to keep it to yourself just to have your own secret weapon.  Unfortunately, the generous author of such an ActionScript library, Jack Doyle, is such a good programmer and has given so much to the community that I feel obligated to pay it forward.

    IMHO- the Greensock Tweening Platform, TweenLite, TweenMax, etc... is the best animation engine and as3 utility library ever made.

    The Fastest.
    You can use the benchmarking application jack has on his site to test his engine with a particle generator script- check it's performance against Tweener, Flash, and other major tweening engines and the comparison is obvious- the particles fly fast and smooth at a much, MUCH higher count than any of the other engines can handle without looking like 3 fps.

    The Easiest.
    Besides being ridiculously easy to use with a quick 1-liner syntax, you can add event handlers and other interesting things all in line.  Here's a 1 second slide/fade in that cues a function called "nextAnimation()":

    TweenLite.to(anyObject, 1, {x: 100, ease: Strong.easeOut, alpha: 1, onComplete: nextAnimation} );

    The Smoothest.
    Watch your animations slide across the screen smoothly with plenty of well optimized easing classes included with the library.

    Thanks and kudos to Jack and his excellent work, the Greensock library has become a not-so-secret weapon for many flash developers. Check out the Greensock site to see how many other awesome classes you can get for things like full screen layouts, filter tweening, sequencing, easing, managing XML, and a lot more.

    Get the Greensock Tweening Platform and other great actionscript classes here.

  • Parsing XML in Actionscript (AS2 / AS3, Flash / Flex) - the EASY way

    AS2

    If you've come from a longer history with Actionscript & XML. you may have written some pretty elaborate / gnarly AS1/AS2 XML parsers in the past- and you probably know what a pain that can be.  (especially when someone tells you to change the spec!)

    If you are stuck in corporate America and thus still working in AS2, save yourself more headaches and get Jack Doyle's Greensock XML manager.  XPATH is great too, but this might be easier.  It allows you to convert XML to Object with arrays and properties, and reference nodes by name.  All in all, it's very well documented / explained with examples and very easy to use- yet another useful and stable class from Jack:

    http://blog.greensock.com/xmlparseras2/

    AS3

    If you are in AS3, you don't need much to parse XML anymore, thanks to E4X (an ECMA script approach to XML).  In fact...

    ...if you've written any for() loops to parse XML, you've already gone too far!!!

     

    Here's a great tutorial on E4X from Senocular:

    http://www.senocular.com/flash/tutorials/as3withflashcs3/?page=4#e4x 

    Here's another at dispatchEvent:

    http://dispatchevent.org/roger/as3-e4x-rundown/

  • AS3 MovieClip / Sprite / DisplayObejct Filters does not work like Array - .push() .pop() .slice()

    To apply effects filters to display objects (sprites, movie clips, etc) ActionScript 3 display objects have a nice little .filters property that allows you to set an Array of effects filters at runtime.  This is great for effects like Bevel, Drop Shadow, Glow, Blur, Inner Shadow, KnockOut, etc..

    ex:

    (assuming you've created the filter instances myBevelFilter, myGlowFilter, myDropShadowFilter)

    1) Works:

    _myMovieClip.filters = [myBevelFilter, myGlowFilter, myDropShadowFilter];

    2) Works:

    var fx:Array = new Array();
    fx.push(myBevelFilter);
    fx.push(myGlowFilter);
    fx.push(myDropShadowFilter);

    _myMovieClip.filters = fX;

    3) Doesn't Work:

     _myMovieClip.filters.push(myBevelFilter);
     _myMovieClip.filters.push(myGlowFilter);
     _myMovieClip.filters.push(myDropShadowFilter);

    You're not doing anything wrong, this is just how Adobe has created the filters property.  From AS3 docs:

    Changing filters at run time

    If a display object already has one or more filters applied to it, you can’t change the set of filters by adding additional filters to or removing filters from the filters property array. Instead, to add to or change the set of filters being applied, you must make your changes to a separate array, then assign that array to the filters property of the display object for the filters to be applied to the object. The simplest way to do this is to read the filters property array into an Array variable and make your modifications to this temporary array. You then reassign this array back to the filters property of the display object. In more complex cases, you might need to keep a separate master array of filters. You make any changes to that master filter array, and reassign the master array to the display object’s filters property after each change.

    http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7db3.html

    AS3 Filters:

    http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7dba.html

  • Common Flash/Flex AS3 Mistake... Loader Doesn't Work - No Events Working When Loading External URLs

    If you seem to have everything set up correctly with a Loader class instance, but there's just nothing happening... You probably made the same mistake I've made a number of times when coding a little too quickly:  attaching the event listeners to the Loader object itself, rather than your loader's property: .contentLoaderInfo - where all the information and events on loading status actually occur.

    For example...

     The Common Wrong Way:


    var myLoader:Loader = new Loader();
    myLoader.addEventListener(Event.COMPLETE, onLoadComplete);
    myLoader.load( new URLRequest("externalExampleImage.jpg") );

    ...and then you wonder why the event never fires, there is no error, and you know your image is there... doht!

    The Right Way:


    var myLoader:Loader = new Loader();
    myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
    myLoader.load( new URLRequest("externalExampleImage.jpg") );

    ... works every time!

    Adobe Documentation Reference:

    http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/LoaderInfo.html

  • FlashDevelop Error Creating New AS3 Projects in an Existing Project's Directory

    If you try to create a new as3 project in a directory of an existing project, you may get this error:

    Could not create the requested project:  The file '...\expressInstall.swf' already exists.

    ...or similar error for "swfobject.js'

    Careful!Don't delete these files or remove bin/ and create a new project b/c it will overwrite existing classes like Main.as!

    Your best bet is to copy your the entire existing project directory to a new directory and create a new project there. Then, copy over whatever is overwritten into the new project directory, and test build.

  • Flash/Flex AS3 - How to Select / Highlight All Text in an Input Text Field On Click

    This took forever to google for some reason...

    Issue:

    You want an input textbox to highlight everything in it when the user clicks it (on focus). Problem is, when the user clicks the text box places the carat, thus un-highlighting the text. I could be wrong, but the second problem seems to be that if you use the FocusEvent.FOCUS_IN event setting selection doesn't work, so you're forced to use MouseEvent.CLICK event... but if you highlight the entire box every time the user clicks, the user can't select any text because it always just highlights the entire box... also, once the box has been highlighted once, you want the user to be able to place the carat without re-selecting the entire box again.

    Solution:

    What you want to do is check if the user is highlighting or if the box was already highlighted since last focus, and if not, stop flash player from putting the carat at the location clicked with event.preventDefault() function, and then set selection from beginning to end. Event.preventDefault() is a sneaky little function you call right on the event object in your event handler, and it prevents whatever the default actions would be for that event (in this case, clear selected text and place carat)

    as3 code example:

    // assuming you have a textbox input called _myTextInputBox
    
    import flash.events.FocusEvent;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    
    _myTextInputBox.addEventListener(MouseEvent.CLICK, onClickTextBox);
    _myTextInputBox.addEventListener(FocusEvent.FOCUS_OUT, onTextBoxLoseFocus);
    
    var _highlightTextOnClick:Boolean = true;
    
    function onClickTextBox(e:Event):void {
    
      var didUserHighlight:Boolean = Boolean(e.target.selectionBeginIndex != e.target.selectionEndIndex);
    			
      if ( _highlightTextOnClick && !didUserHighlight)  {
        e.preventDefault();
        e.target.setSelection(0, e.target.text.length);
        _highlightTextOnClick = false;
      }
    
    }
    
    function onTextBoxLoseFocus(e:FocusEvent):void 
    {
      _highlightTextOnClick = true;
    }
    
  • AS3 / Flash / FlashDevelop - scaleY = 0 ... Bug with scaleY value on Custom Class

    I haven't found much on the web about this...

    Issue:

    Has anyone experienced an issue where a custom class extending a library MovieClip instantiated on stage has an initial scaleY value of 0, but scaleX is 1?

    example:

    - class MovieClipAndThenSome extends
    - class MovieClipPlus extends class FL_MCFromLibrary
    - class FL_MCFromLibrary is generated by flash when not found in the classpath (it is the linkage name of a library movie clip in flash) and extends MovieClip

    //as3 example..

    var newCustomMC:MovieClipAndThenSome = stage.addChild(new MovieClipAndThenSome());

    trace(" >> scaleX: " + newCustomMC.scaleX); // output: >> scaleX: 1
    trace(" >> scaleY: " + newCustomMC.scaleY);// output: >> scaleY: 0


    is this a known flash bug?

    solution:

    an obvious workaround... call this line after object is added to stage..

    this.scaleY = this.scaleX = 1;

  • AS3 - Load a Remote Image from Any URL / Domain with No Stupid Security Sandbox Errors

    Issue:

    You want to load an image from an unkown external URL. It works on your computer... Sandbox Security error online (and/or the annoying images just showing up as solid white feature).

    By default, Flash wants a crossdomain.xml file on the server you are loading from, but let's say there is none, because it's probably not your website.  Well, then the flash player isn't going to let you take that data and do what you want with it.

    Attempting to do so will give you some error similar to:

    *** Security Sandbox Violation ***
    SecurityDomain 'http://www.designercolin.com/temp/ispire/get_boards.php' tried to access incompatible context 'somewebsite.com/someImage_here.jpg'

    Half-Solution (aka the adobe way):

    According to adobe's docs you need to do a couple things to work around this (to not access this remote data directly)- bypass policy file, and don't manipulate it in any way (ahem-lame).  See the next solution if you need to access or smooth the bitmap data.

    1)  Use a LoaderContext instance with checkPolicyFile=false - this will tell it not to worry about the cross-domain issue and use the loader context object as 2nd parameter in Loader.load() call

    var lc:LoaderContext = new LoaderContext();
    lc.checkPolicyFile = false; // bypass security sandbox / policy file - does this effect quality when scaling?

    _myLoader = new Loader();
    _myLoader.contentLoaderInfo.addEventListener(Event.INIT, onImageLoaded);

    // load new url
    _myURLRequest = new URLRequest($url);
    _myLoader.load(_myURLRequest, lc);

     

    2) Show the loaded image - This is where you may get the error (this is what had me pulling my hair out) 

    Even with the checkPolicyFile = false set, I had to add the loader to a SPRITE (not movieclip, and not the loader content!), as this would be accessing data outside the sandbox

    private function onImageLoaded($e:Event):void
    {
      _innerImage = this.addChild(new Sprite());
      //_innerImage.addChild($e.currentTarget.content); // doesn't work. sandbox security error
      _innerImage.addChild(_myLoader);
    }

    ...by doing this, you will not have accessed this image data in any way to get the error, so you can load the image data but if you need to access the bitmapdata directly (or create a movie clip apparently?), I don't think it will work.

    I'm not sure exactly why adding to a Sprite() instead of MovieClip() allowed it to work for me, they both are DisplayObjects, maybe there is something in the MovieClip constructor that accesses the image data... Whatever, it's stupid that you have to do that in the first place, so why would the method make sense!  See the other / better solution below..

    Quality Question- for remote image data without policy file:

    What I really want to know is (for printing purposes) - using this method, since there is no access directly to the image data, when you scale the image... does it not render with smoothing / anti-aliasing?  Is it poor quality outside of native dimensions?  Or is it basically the same quality as scaling a local image within security domain?  Final conclusion is that it's better to use a proxy if the image has to be anything but native (original size/scale)...

     

    Better Solution- Go Around It

    Well, since flash is finicky and now has had different bugs with different flash player versions, the smart thing to do is cut your losses and just go around this issue.  A local .php file or similar service as a proxy to cross-domains URLs will do the trick and retrieve the images and flash will basically think they were hosted locally.

    Then, in flash you should set up a class that will prefix URLs for you, maybe extend the URLLoader...

    However you do it, you want to prefix remote URLs with your proxy URL, and pass along the intended URL something like:

    http://www.YourFlashSite.com/proxy/getimage.php?url=http://someOtherWebsite.com/someImage.jpg

    On creating the PHP proxy to retrieve the file.. theres a few you can find with google but i have had issues with the majority of them-

    One common proxy issue with Flash is that if your progressEvent.bytesTotal is 0 (making your preloader show Infinity) it may be because your server has gzip enabled.  You can use an app like Charles to see what your http activity looks like and see if there is gzip compression on the responses... turn off gzip for your proxy file and you're golden.