Flash Concepts FAQ

What is SWF format?

SWF is a bytecode format that bundles Flash-usable resources, including code, animation, sound, and binary or text data. A SWF file's resources are accessible as a unified namespace from within Flash. This means that if you have a resource named "MyResource" in the SWF, you should have a corresponding class named "MyResource" in your code that can be instanced to access the resource. Haxe's compiler model is code-centric and unlike the Flex compiler "MXMLC," Haxe does not have a direct method of embedding arbitrary assets. Instead, we use asset-oriented SWF compilers such as Swfmill or SamHaxe to build a library SWF, and compile the code with the "swf-lib" option to create a final SWF with all assets bound together.

SWFs can host other SWFs, a powerful but complex feature that enables multi-loading, pre-loaders, and other arrangements. Each SWF contains its own namespace and is responsible for its own security. Inter-SWF access is allowed through the ApplicationDomain and Security classes.

SWFs, being originally designed as an animation-centric format, embed the notion of frames of animation into their core. Each frame of the SWF can contain any number of assets. This allows Flash-IDE generated animation to call up assets needed exactly when they have to be displayed onscreen - a useful feature for streaming long animations. It also allows a method of preloading in two frames; on the first frame the preloader code is run. The second frame contains the rest of the application. When the preloader sees that the full SWF has finished loading, it can either tell Flash to proceed to the second frame, or call code in the second frame directly.

Flash requires some AVM bytecode stubs to recognize the existence of embedded assets. Flash IDE generates these automatically, as does SamHaXe; Haxe code compiled with the -swf-lib compiler directive requires stubs for assets to be included within the codebase. Swfmill does not generate stubs automatically, and Haxe does not generate SWFs containing more than one frame: the combined requirement of stub code on the second frame means that preloader creation is easiest using SamHaXe.

What is the Stage? What are DisplayObjects?

Flash's visuals and interface are focused around the Stage class. This class is not instanced directly, it is accessed in Haxe via flash.Lib.current.stage. There is only one stage; but recall that each SWF has its own namespace. From that we can see that "flash.Lib.current" refers to the current namespace, which automatically sits on top of the stage.

DisplayObjects are a set of classes that the Flash API understands how to use for drawing and interaction purposes. They can be added in a hierarchy, and input events can be attached to them. A clickable "Button" class, for example, might be composed as a Sprite with a TextField and a Shape as its children; the Sprite is the container object, while the Shape and the TextField draw the button graphics and the label, respectively. The Button would be made interactive with a call to addEventListener(). Finally, to make it show up on screen, one would add the Button(and not its children) to the stage.

There is a performance penalty for having a lot of DisplayObjects on the stage, because Flash has to traverse the hierarchy at least once to test and propagate events each frame.

I just want to draw bitmaps. How can I do that?

Create a new Bitmap object, and create a BitmapData for the Bitmap. The BitmapData contains the actual content of the bitmap; Bitmap, on the other hand, provides DisplayObject functionality, including rotation, scaling, filters, etc. Add the Bitmap to the stage, and you have a surface suitable for drawing. If you want to blit bitmaps, you have two choices: the slow draw() function which can access all the DisplayObject transformation functionality and render it into a new bitmap, and the fast copyPixels() function which does a straight blit routine.

The most generally performant method for 2D graphics is to prerender all transformations into a spritesheet, either at boot time with draw(), or within your data, and then to use a lookup table to blit different transformations. If you wish to have fine control over layering like what is provided from the Flash display lists, you can defer actual rendering into a queue for each layer and only do the render after all elements have added their draw commands.

What are my options for text?

The standard option for text in Flash is the TextField class, another kind of DisplayObject. TextField is a featureful but clumsy class, complemented by TextFormat, which does additional styling functionality. It has a toggle for user input, can use a non-standard subset of HTML with the htmlText field, and has options for controlling line length, auto-sizing, word-wrapping, alignment, and many other parameters. TextField has several unresolved bugs, mostly related to non-English language input.

New in Flash 10 is the "Text Layout Framework." This is a new text layout engine, accessible through flash.text.engine, which is even more feature-packed and complex than the standard TextField. Basic use now involves three different classes: TextLine, TextBlock, and ContentElement. If you are interested in advanced formatting with flowing around graphical elements, unusual styling, etc., this engine may interest you.

An important consideration about Flash's text support is the usage of fonts. You should not rely on system fonts for most applications because they will vary according to the user's platform, changing assumptions about size, alignment, etc. Instead, include a .ttf in your assets, and create your textFields with the property embedFonts set to true.

Two alternative text options in Haxe involve bitmap fonts. One is the "bitmapfont" library and works with an external tool, the Angelcode Bitmap Font Generator, to create a packed spritesheet and an XML file. The other is in the "polygonal" library and generates code from .ttfs that prerenders glyphs using Flash 10's new vector drawing commands. Both are much more performant than a TextField in situations where you need to dynamically render new glyphs and have no need for text input; however, if you have mostly static text, you can get results nearly as fast by using cacheAsBitmap, or draw() to do your own caching.

Regardless of the solution you use, for most cases, it is simplest to create convenience functions or subclasses for each font, style, and alignment you plan to work with.

How do I access input devices?

You attach an event listener for a KeyboardEvent or MouseEvent to a DisplayObject. Then the DisplayObject will pick up keypresses or mouse clicks. Note that Flash is finicky about which kind of DisplayObject you are applying the listener to, and where it is located: MouseEvents will not trigger on Bitmaps(wrap them inside a Sprite instead), and they'll automatically be filtered by image size and shape - even TextFields are affected by this.

How does timing in Flash work?

Flash uses an "elastic racetrack" model; this means that in each frame, some amount of time will be allocated between rendering and code, and the amount of time will adjust depending on previous frame performance.

SWF files specify a desired framerate, which has a major influence in the render/code tradeoff.

You have three general choices of timing: A Timer class, flash.Lib.getTimer(), and listening for the onEnterFrame event.

The onEnterFrame event will give the most reliable results if you want to lock your timing to the SWF framerate.

getTimer() is most useful for measuring time intervals, and can be used in combination with onEnterFrame to create delta-times if you want a FPS counter or a simulation that runs with a variable timestep. This is the most flexible option for games, and can be used reliably even in situations needing recording/playback synchronization if you also record the delta times. A cap on maximum timestep is recommended to cover worst-case situations where the simulation will break or the game becomes unplayable because deltas are too large.

The Timer class is good if you want "independently timed" actions going on simultaneously, or if you have a long-term process that needs to be split up to avoid the Flash Player's 15-second default timeout; you can use "new Timer(1,1);" to create a timer that fires in one frame. You may also use onEnterFrame, as long as you're careful to remove the event.

What's the difference between Flash 9+ and older Flash?

Flash has a JIT VM starting with Flash 9; this change also included a new API. With Flash 10 additional API extensions have been introduced. To use the newest version use "-swf9 myswf.swf" and "-swf-version 10" (or whatever version is newest).

What are some performance tips for Flash?

In Flash 10 you have many options if you are bound by code performance.

First, make sure you are avoiding Dynamic and untyped{} where performance is critical; the JIT uses type information to speed things up. Second, you have the choice between Vector, List, and FastList as alternatives to Array(which is usually the slowest option). If you install ListTools, you may also use the list class included there, which is again optimized in another way from the other List classes. If you are instancing lots of objects in a short period of time, pre-instancing them and maintaining an object pool that pulls them in and out as necessary is preferred by Flash's memory management system.

Finally, you may use the flash Memory API, which lets you allocate a chunk of memory as a ByteArray and access its bytes directly.

If rendering is slow(it is considerably slower outside of the Windows player), avoid alpha transparency and usage of advanced DisplayObject features(rotation, scaling, 3D, filters). Prefer bitmaps to vectors; if you have a complex DisplayObject, you may want to try using cacheAsBitmap for a simple speedup. Try to reduce the quantity of rendering with early elimination tests, if they're possible and not too expensive.

AVM2 does not prefer Int over Float in standard arithmetic performance; however, bitshift-based arithmetic can speed up integers considerably. Examples

There is no built-in integer division, only truncated Float division(with implicitly upcasted Ints). A self-implemented integer divide is ~50% faster than floating-point division + flooring:

class IntDivision
{
    inline static function abs(x : Int) {return ((x) < 0 ? ~(x)+1 : (x));}

    public static inline function posIntDiv(num : Int, denom : Int)
    {
      var a=0;
      var b=0;
      var i= 31; // CAREFUL: works only on int=32-bit machine!
      /* Work from leftmost to rightmost bit in numerator */
      while(i>=0) {
        /* appends one bit from numerator to a */
        a = (a << 1) + ((num & (1 << i)) >> i);
        b = b << 1;
        if (a >= denom) {
          a -= denom;
          b++;
        }
      i--;
      }
      return b;
    }
    
    public static inline function intDiv(a : Int, b : Int)
    {
        var dividend = abs(a);
        var divisor = abs(b);
        
        if (divisor==0) return 0;
        
        else if (divisor > dividend) 
        {
            return 0;
        }

        else if (divisor == dividend) 
        {
            return 1;
        }
        
        else
        {
        
            var quotient = posIntDiv(dividend,divisor);
            
            if (a<0) { if (b>0) return ~quotient+1; else return quotient; }
            else { if (b<0) return ~quotient+1; else return quotient; }
        }
    }
}
version #8382, modified 2010-04-02 07:21:41 by rtf