Chapter 4. Exploring the Benefits of Using ActionScript 3.0
It has been said, and generally agreed, that in spite of how funny it would make a person look, two heads are better than one. The point of this adage, of course, is that collaboration can be a remarkably productive venture. Flash Player 10 promotes this ideal thanks to its two virtual machines, the software modules inside Flash Player that execute ActionScript programs. Until Flash Player 9, only a single virtual machine was necessary. It handled (and still handles) everything code-related from the very beginnings of ActionScript to the formal object-oriented programming (OOP) paradigm introduced with ActionScript 2.0. The architectural changes and improvements introduced with ActionScript 3.0, however, were substantial enough in Flash Player 9 to warrant a new virtual machine specifically optimized for the new language.
This new module, named ActionScript Virtual Machine 2 (AVM2), works independently of the previous player codebase. It was unveiled in a prerelease version of Flash Player 9, originally slated as Flash Player 8.5. (There was no commercial release of Flash Player 8.5; in the final public release, its version number shipped as 9.) Legacy support is still handled by the previous codebase, now renamed ActionScript Virtual Machine 1 (AVM1) and remains as a companion module inside Flash Players 9 and 10 to support backward compatibility. Meanwhile, AVM2 ushers ActionScript 3.0 into an arena of increased performance, efficiency, and an internal consistency that makes the language easier for newcomers to learn. In this way, both old and new code are able to function with maximum efficiency and performance.
In addition to benefiting from two heads, so to speak, Flash Player 10 encourages another nuance on the concept of collaboration: that of adherence to standards. Because other Flash Platform development tools rely on the same ECMAScript specification as Flash CS4, your work in ActionScript 3.0 leads directly to portability among other Adobe technologies, such as Flex and Adobe Integrated Runtime (AIR), formerly codenamed Apollo. Learn ActionScript 3.0 in terms of the Flash authoring tool, and you already have a leg up on building online and desktop-based Rich Internet Applications (RIAs) and occasionally connected desktop applications.
Performance
In Adobe benchmarks, ActionScript 3.0 has been shown to increase application performance by an order of magnitude. This means that even complex programs can potentially execute with 10 times the speed and efficiency of ActionScript 2.0. That’s the sort of impressiveness that rivals a juggler with flaming bowling pins—who is also spinning plates, while riding a unicycle on a tightrope with no net. To be sure, some of this improvement results from enhancements to the Flash Player runtime itself, from successively better rendering with each release, the advent of bitmap caching in Flash Player 8, and hardware acceleration in Flash Player 9.0.115.0. Ultimately, though, performance depends on how well your code is written, on adherence to recommended best practices, and the boost of being executed on AVM2.
In early 2005, a participant in the Flash ActionScript support forum posed a question about using ActionScript to render something called the Mandelbrot set, which is one of the most popular examples of a series of infinitely complex geometric shapes called fractals. Chances are good you’ve seen the Mandelbrot set depicted on progressive rock album covers, as the underlying mechanism for computer-generated (CG) effects like realistic mountain terrains, or even as the printed pattern on a handful of bowties at a programming convention. The initial view of this geometric set, seen in Figure 4-1, is defined by a complicated mathematical formula. This trait makes it a good candidate for showcasing the speed increases of ActionScript 3.0, as the code discussed in 2005 can be compared side by side with a modern interpretation.
In fact, you can re-create a version of the original SWF file yourself and evaluate its performance against an ActionScript 3.0 version on your own computer.
Create a new ActionScript 2.0 FLA file. Use the Property inspector to set the document’s dimensions to
340
pixels by240
pixels and the background color to#000000
(black). Type the following code into frame 1 of a script layer:var startTime:Number = getTimer(); var image:MovieClip = this.createEmptyMovieClip("mcImage", 0); image._x = 240; image._y = 120; var colors:Array = new Array( 0x000000, 0x0E0E0E, 0x1C1C1C, 0x2A2A2A, 0x383838, 0x464646, 0x555555, 0x636363, 0x717171, 0x7F7F7F, 0x8D8D8D, 0xB9B9B9, 0xAAAAAA, 0xB8B8B8, 0xC6C6C6, 0xD4D4D4, 0xE2E2E2, 0xF0F0F0, 0xFFFFFF ); var k:Number = −120; var zArr:Array = new Array(); var myTimer:Number = setInterval(drawLine, 1);
This step sets up a
startTime
variable, which metaphorically clicks a stopwatch into action. This variable is compared to thegetTimer()
function again at the end, which then displays total elapsed seconds. Theimage
variable holds a reference to a movie clip, which is used as a canvas on which the Drawing API plots a series of line segments that represent the Mandelbrot set. Thecolors
variable points to an array of color values used during the drawing,k
andzArr
are used in the fractal calculation, andmyTimer
is eventually used to halt the repeated triggering of a customdrawLine()
function, as looped once every millisecond by thesetInterval()
function.Next comes the
drawLine()
function, which is the brain of the whole operation. Type the following code after the existing ActionScript code:function drawLine():Void { var j:Number = 0; var x:Number = 0; var y:Number = 0; var n:Number = 0; var zAbs:Number = 0; for (j = −240; j <= 100; j++) { x = 0; y = 0; n = 0; do { n++; zArr = f(x, y, j / 100, k / 100); x = zArr[0]; y = zArr[1]; zAbs = zArr[2]; if (n >= 20) { break; } } while (zAbs <= 4); if (zAbs > 4) { image.lineStyle(1, colors[n], 100); image.moveTo(j, k - 1); image.lineTo(j, k); } } k++; if (k >= 0) { clearInterval(myTimer); duplicate(); } }
For the sake of this demonstration, it doesn’t matter if the Mandelbrot formula seems clear as mud. Just count on it that the magic happens inside the
do..while
statement, one of whose lines calls a customf()
function. The line segments are drawn by the calls tolineStyle()
,moveTo()
, andlineTo()
, and the finalif
statement decides when to stop thesetInterval()
loop by callingclearInterval()
, then completing the mirror image of the drawing with a call to the customduplicate()
function.Here are the final short blocks of code, the
f()
andduplicate()
functions. Type the following code after the existing ActionScript code. Note that the last line of theduplicate()
function usestrace()
to report the elapsed time to the Output panel.function f(x:Number, y:Number, a:Number, b:Number):Array { var rPart:Number = x * x - y * y + a; var iPart:Number = 2 * x * y + b; return new Array(rPart, iPart, rPart * rPart + iPart * iPart); } function duplicate():Void { var flip:MovieClip = image.duplicateMovieClip("mcFlip", 1); flip._yscale = −100; flip._y -= 2; trace((getTimer() - startTime) / 1000); }
Select Control→Test Movie to see your handiwork (Figure 4-2).
Special thanks to Keith Gladstien, PhD, MD (http://www.kglad.com/), for permission to reprint a version of his code in this book. See Keith’s website for additional exploration of the Mandelbrot set in Flash.
Your own performance results may vary, depending on your computer’s power and speed. You may even want to test repeatedly and take an average of elapsed times, remembering that results will vary for individual users who view your published content. You’ll clearly see the sequential improvement when you configure the publish settings for this FLA file among various versions of Flash Player (File→Publish Settings→Flash→Version) Table 4-1 shows the averaged results of one such series of tests.
Flash Player version | ActionScript version | Elapsed time (in seconds) |
Flash Player 6 | ActionScript 2.0 | 21.847 |
Flash Player 7 | ActionScript 2.0 | 15.225 |
Flash Player 8 | ActionScript 2.0 | 13.729 |
Flash Player 9 | ActionScript 2.0 | 10.338 |
Flash Player 9 | ActionScript 3.0 | 2.853 |
Flash Player 10 | ActionScript 2.0 | 15.557 * |
Flash Player 10 | ActionScript 3.0 | 6.387 * |
* At the time of writing, Flash Player 10 actually performed more slowly than Flash Player 9. This should be addressed before Flash is publicly released.
Updating the Code to ActionScript 3.0
To experience the Mandelbrot set on your own in a matter of 2 to 3 seconds, save your current file as MandelbrotAS3.fla, and then complete the following steps. Great care has been taken to maintain the overall structure of this code, so that it parallels the ActionScript 2.0 version approximately line for line.
Configure the FLA file’s publish settings for Flash Player 9 or 10 (File→Publish Settings→Flash→Version), and then change the ActionScript version to ActionScript 3.0.
Update the existing code as follows (changes in are bold):
var startTime:int = getTimer(); var image:Sprite = new Sprite(); image.x = 240; image.y = 120; addChild(image); var colors:Array = new Array( 0x000000, 0x0E0E0E, 0x1C1C1C, 0x2A2A2A, 0x383838, 0x464646, 0x555555, 0x636363, 0x717171, 0x7F7F7F, 0x8D8D8D, 0xB9B9B9, 0xAAAAAA, 0xB8B8B8, 0xC6C6C6, 0xD4D4D4, 0xE2E2E2, 0xF0F0F0, 0xFFFFFF ); var k:int = −120; var zArr:Array = new Array(); var myTimer:Timer = new Timer(1, 0); myTimer.addEventListener(TimerEvent.TIMER, drawLine); myTimer.start();
This time, the
int
data type is used in cases where numerical values are integers, simply becauseint
values consume a smaller memory footprint thanNumber
values. Similarly,image
is set to an instance of theSprite
class, rather thanMovieClip
, becauseSprite
is perfectly adequate—it supports the necessary Drawing API—and it’s the smaller data type. In this case, the timer mechanism is an instance of theTimer
class.Here’s the updated version of the
drawLine()
function. Update the existing function to look like this:function drawLine(evt:TimerEvent):void { var j:int = 0; var x:Number = 0; var y:Number = 0; var n:int = 0; var zAbs:int = 0; for (j = −240; j <= 100; j++) { x = 0; y = 0; n = 0; do { n++; zArr = f(x, y, j / 100, k / 100); x = zArr[0]; y = zArr[1]; zAbs = zArr[2]; if (n >= 20) { break; } } while (zAbs <= 4); if (zAbs > 4) { image.graphics.lineStyle(1, colors[n], 100); image.graphics.moveTo(j, k - 1); image.graphics.lineTo(j, k); } } k++; if (k >= 0) { myTimer.stop(); duplicate(); } }
Not a whole lot changes, as you can see. The function now accepts a parameter, as required by the
TimerEvent
class, and its return value is changed fromVoid
to the lowercasevoid
. AppropriateNumber
types are changed toint
, and the Drawing API is now routed through aGraphics
instance, as referenced by theSprite.graphics
property. Rather thanclearInterval()
, the timer is halted by way of theTimer.stop()
method.Finally, here are the ActionScript 3.0 versions of the
f()
andduplicate()
functions. Update the last blocks of code to look like this:function f(x:Number, y:Number, a:Number, b:Number):Array { var rPart:Number = x * x - y * y + a; var iPart:Number = 2 * x * y + b; return new Array(rPart, iPart, rPart * rPart + iPart * iPart); } function duplicate():void { var bmpData:BitmapData = new BitmapData(340, 120, true, 0x000000); var mat:Matrix = new Matrix(1, 0, 0, 1, 240, 120); bmpData.draw(image, mat); var bmp:Bitmap = new Bitmap(bmpData); bmp.scaleY = −1; bmp.y = 238; addChild(bmp); swapChildren(bmp, image); trace((getTimer() - startTime) / 1000); }
The
f()
function doesn’t change at all. Since ActionScript 3.0 no longer supports the equivalent ofMovieClip.duplicateMovieClip()
, theduplicate()
function requires a few more lines than its ActionScript 2.0 counterpart. Here, theBitmapData
class is used to take a snapshot of the pixels drawn into theimage
sprite. These pixels are drawn into aBitmap
object, and then flipped to provide the mirror image. Because the line segments are drawn into the upper-left quadrant of the sprite—that is, left of 0 in the x-axis and above 0 in the y-axis—a matrix object is used to reposition the pixels into the lower-right quadrant (240 pixels over and 120 pixels down).Select Control→Test Movie to see the increased rendering speed. As an added bonus, note that rendering occurs even more quickly when the
image
sprite is added to the display list only after the Mandelbrot calculations are made. Add two slashes to line 6 of Step 2 to comment it out:var image:Sprite = new Sprite(); image.x = 240; image.y = 120; //addChild(image);
and then insert the same line into the
duplicate()
function of Step 4.function duplicate():void { var bmpData:BitmapData = new BitmapData(340, 120); var mat:Matrix = new Matrix(1, 0, 0, 1, 240, 120); bmpData.draw(image, mat); var bmp:Bitmap = new Bitmap(bmpData); bmp.scaleY = −1; bmp.y = 238; addChild(image); addChild(bmp); swapChildren(bmp, image); trace((getTimer() - startTime) / 1000); }
This step can shave off an additional second from the total elapsed time. Thanks again to Keith Gladstien, PhD, MD (http://www.kglad.com/) for input.
Efficiency
Imagine a warehouse with numerous and greatly varied products: everything from Fabergé eggs to collectible trading cards to garden rakes. In order to make shipping very easy, the warehouse manager has stocked a limited range of cardboard box sizes; in fact, all their dimensions are the same, one size fits all. As hoped for, everything is indeed easy to pack. The rakes fit into the boxes just fine, and so do the eggs and cards—it’s just that anything smaller than a rake also needs several bucketsful of Styrofoam peanuts. For small shipments, this arrangement isn’t so bad, but the trading cards happen to belong to a collectible franchise named Pokémon. One of these days—and the phenomenon will seem to explode overnight—several thousand customers are going to order individually wrapped packs of cards within the span of one week. When that happens, a vein will start to throb on the manager’s forehead. Obviously, the packaging for these cards will take up more room than necessary—considerably more—and it may not be possible to fit all the required boxes on the shipping dock.
Thanks mainly to the addition of runtime types in ActionScript 3.0, Flash Players 9 and 10 can generally avoid this sort of scenario. To continue the somewhat loose analogy, you can think of runtime types as a well-organized assortment of custom-fitted cardboard boxes. Because the boxes aren’t any larger than they need to be, storing them becomes a relatively efficient endeavor. In the real world, AVM2 is capable of requesting, or allocating, only the system memory it needs to create the objects called for by the various classes used in your code. Not only that, but the hierarchy of native ActionScript 3.0 classes has been considerably reorganized to take better advantage of a tiered system of complexity.
A quick look at the MovieClip
class illustrates this principle, though the same notion applies to most
other ActionScript 3.0 classes. First, consider the ActionScript 2.0 implementation of MovieClip
. Consulting the ActionScript 2.0
Language Reference in the onboard documentation, you’ll find that the
family tree for the MovieClip
class is
remarkably small. This class inherits from the Object
class alone (Figure 4-3), which is the base
class upon which all classes are established.
This characteristic means the ActionScript 2.0 version of the
MovieClip
class carries practically all
its own baggage. As often as not, this makes it heavier than it needs to
be from the standpoint of system resources. If you want a visual object
whose movement you can program around the stage, MovieClip
is generally the most appropriate
choice in ActionScript 2.0. All you really need for this sort of movement
is a pair of properties that relate to the movie clip’s x and y
coordinates. The ActionScript 2.0 MovieClip
class delivers the _x
and _y
properties right to your fingertips—but you also get a number of
properties you don’t really need in this situation, such as _currentframe
and _totalframes
(you won’t be using the movie
clip’s timeline), in addition to timeline-related methods like play()
, stop()
, gotoAndPlay()
, and so on. Even worse, the
ActionScript 2.0 version of MovieClip
includes a method for loading external assets (loadMovie()
), and several more for drawing
shapes (lineStyle()
, moveTo()
, lineTo()
, curveTo()
, and others). These additional class
members add to the overall weight of every MovieClip
instance, even if you don’t use
them.
In ActionScript 3.0, the MovieClip
class acquires most of its
functionality from the Sprite
class
(Figure 4-4). In fact,
movie clips are sprites; they’re just sprites with
timelines. In turn, the Sprite
class
inherits most of its functionality from DisplayObjectContainer
, which inherits most of
its features from InteractiveObject
, then DisplayObject
, EventDispatcher
, and finally Object
—each type getting progressively simpler
toward the parent side and taking up a smaller footprint of system
memory.
If you don’t need the overhead of a timeline, use Sprite
for your programmatic animation. It has
x
and y
properties, but isn’t encumbered by currentFrame
or totalFrames
properties, nor by the
aforementioned timeline- or drawing-related methods. The Sprite
class still lets you draw shapes—which
means the ActionScript 3.0 MovieClip
class does as well—but this set of functionality is deferred to the new
Graphics
class, and is associated with
a given sprite or movie clip by way of its graphics
property. Loading duties are separated
altogether, and are the new Loader
class’s responsibility.
By strongly typing your variables and function return values in
ActionScript 3.0, you give explicit instructions to the compiler to pack
its goods into the sort of cardboard boxes that fit like a glove. Strong
typing requires nothing more than a colon (:
) and data type name.
var intergerValue:int = 1; var nonIntegerValue:Number = 1.2; var aSprite:Sprite = new Sprite(); var someFunction():void { // function code here }
It’s true that variables and function return values could be strongly typed in ActionScript 2.0, and doing so was useful: the practice facilitated authoring tool assistance like code hinting, and provided more comprehensive error warnings at compile time—but compile time is where the benefits ended. Once a SWF file is produced, AVM1 loses any remembrance of an object’s type. AVM2 remembers.
Consistency
Ironically, one of ActionScript 3.0’s most elegant aspects is a
potential stumbling block to longtime Flash developers, only because, as
the adage goes, old habits die hard. Flash pioneers will remember when on()
and onClipEvent()
were not only the most popular
ways to handle button and movie clip events, they were the
only way. If you wanted to repeatedly trigger a
custom function or simply a handful of instructions, you could associate
your intentions with, say, the enterFrame
event of a particular movie clip
symbol. You could select the symbol, open the Actions panel—which was then
temporarily linked to that symbol—and then type something like
this:
onClipEvent(enterFrame) { // responsive code here }
If you wanted to handle another event, you would use the same
onClipEvent()
function (the same
formatting), in cahoots with that other event. Both event handlers were
attached to the object in question:
onClipEvent(enterFrame) { // responsive code here } onClipEvent(release) { // mouse-related code here }
When Flash MX hit the scene a few years later, the same basic concept took on a new alternative procedure, which was optional. In this other approach, event handling code could be attached to frames instead of directly to objects. This meant the desired recipient of your instructions—a movie clip, button, or the like—now needed an instance name, otherwise ActionScript would have no idea which object you were talking to. Instance names were usually provided by way of the Property inspector, but could also be determined by code. In the new format, dot notation provided the necessary association (here, the instance name is myClip):
myClip.onEnterFrame = function():Void { // responsive code here, inside // an anonymous function literal } myClip.onRelease = aNamedCustomFunction; function aNamedCustomFunction():Void { // mouse-related code here, inside // a named function definition }
The dot notation approach brought with it a number of benefits that often went unnoticed.
Finer grained control
11 button events, versus the previous 8
18 movie clip events, versus the previous 9
Easier maintenance, because code could be stored in a single frame, rather than scattered among potentially dozens of objects
More flexibility, as events could be assigned, deleted, and changed programmatically
As new versions of Flash Player continued to bring new
functionality, two additional event handling mechanisms entered the
developer’s lexicon: an addListener()
method, used by such classes as Stage
, MovieClipLoader
, Key
, and Mouse
, and an addEventListener()
method, used by ActionScript 2.0 components. Both of these new
formats worked in a similar way, requiring an Object
instance to act as liaison between the
object in question and the methods defined by its class. The two could
even share the same listener object:
var listener:Object = new Object(); listener.onKeyUp = keyUpHandler; listener.click = clickHandler; function keyUpHandler():Void { // keyboard-related code here } function clickHandler(evt:Object):Void { // button component code here } Key.addListener(listener); myComponentButton.addEventListener("click", listener);
Because these additions happened over subsequent releases of the Flash authoring tool, longtime developers could add them piecemeal to their skill sets, but you can easily see how a newcomer might be mystified by so many choices.
In ActionScript 3.0, event handling has very nearly been
consolidated into a single consistent approach, similar to the one used by
ActionScript 2.0 components. In fact, the only exception happens with the
NetStream
class, and even then, only when you need to respond to video
metadata or cue points. The exception still makes use of an Object
instance, and shares many elements of the
listener mechanisms in ActionScript 2.0 (exception cases in bold):
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
videoPlayer.attachNetStream(ns);
var listener:Object = new Object();
listener.onMetaData = metaDataHandler;
listener.onCuePoint = cuePointHandler;
function metaDataHandler(evt:Object):void {
// meta data code here
}
function cuePointHandler(evt:Object):void {
// cue point code here
}
ns.client = listener;
ns.play("someVideoFile.flv");
Everything else uses the new EventDispatcher.addEventListener()
method, which
is inherited by all classes capable of dispatching events. Inheritance
provides this event listening method in the same way it provides Sprite
methods (and other functionality) to the
MovieClip
class, as touched on in the
section entitled Efficiency of this chapter. Events of
all of these objects—movie clips, buttons, components, text fields, the
stage, sounds, programmatic tweens, instances of the new Timer
class, and more—are handled the same way
far and wide.
// Assuming instances of MovieClip, TextField, and Tween ... myClip.addEventListener(Event.ENTER_FRAME, enterFrameHandler); myTextField.addEventListener(Event.SCROLL, scrollHandler); myTween.addEventListener(TweenEvent.MOTION_FINISH,¬ motionFinishHandler); function enterFrameHandler(evt:Event):void { // responsive code here } function scrollHandler(evt:Event):void { // scroll-related code here } function motionFinishHandler(evt:TweenEvent):void { // tween-related code here }
Note
For additional examples of ActionScript 3.0 event handling, see the section Creating DragParrot, a Sample Class File in Chapter 2; the section ActionScript Can No Longer Be Attached to Objects in Chapter 5; and the practical examples in Part III and Part IV of this book.
In addition to bringing together a consistent event handling model,
ActionScript 3.0 unifies the approach employed to instantiate
objects. In previous versions of ActionScript, you could easily
create, for example, an array, string, or generic Object
instance. The new
statement neatly took care of it:
var a:Array = new Array(); var s:String = new String(); var o:Object = new Object();
Of course, some objects, such as these, had optional shortcut constructors (and still do):
var a:Array = []; var s:String = ""; var o:Object = {};
but in either case, the construction of the desired object was a tidy process.
For other ActionScript 2.0 classes, notably MovieClip
and TextField
, it wasn’t so graceful. Instantiation
of these objects required an existing MovieClip
instance (often the main timeline,
often referred to with this
), to use
the createEmptyMovieClip()
and createTextField()
methods:
var mc:MovieClip = this.createEmptyMovieClip("myClip", ¬ this.getNextHighestDepth()); var tf:TextField = this.createTextField("myTextField", ¬ this.getNextHighestDepth(), 0, 0, 100, 22);
As these objects were created, the MovieClip
instance on which these methods were
invoked became the immediate parent of the new movie clip or text field.
In the code shown, this parent is the main timeline, via this
, but any movie clip instance name would do,
in which case the referenced movie clip would become the new object’s
parent. Once it was established, you couldn’t change this parent/child
relationship.
In ActionScript 3.0, even movie clips and text fields can be
constructed with the new
statement:
var mc:MovieClip = new MovieClip(); var tf:TextField = new TextField();
At this point, the mc
and
tf
variables are bona fide instances of
their respective classes. The movie clip can be drawn into with the
Drawing API, positioned and animated over time. You can assign the text
field plain text or HTML formatted text, and so on. When either object is
ready for display, it can be added to the display list of any descendant
of the DisplayObjectContainer
class,
which includes the main timeline, movie clips, sprites, and any class that
supports the addChild()
method.
In this way, you can reparent visual objects in ActionScript
3.0 as often as you like.
Note
For more information on the display list concept, see the practical examples in Part IV of this book.
Standards and Portability Among Other Technologies
If your Flash development has led you into parallel work with HTML/XHTML, CSS, and JavaScript, you may already be familiar with the benefits of adherence to standards. The stakes in web development differ from those in Flash, because web developers have to make sure their content displays and behaves nearly the same—or, ideally, exactly the same—across a potentially sizeable number of browsers. This can be a sublimely challenging task, but the effort is reduced when browser manufacturers acknowledge and uphold the specifications on which these languages and technologies are based.
In contrast, Flash Player provides, for the most part, a single consistent runtime across any browser or operating system that supports the ActiveX control or plug-in. In the world of Flash development, the discipline involved in adhering to standards has already been taken care of. Adobe has leveraged this cohesive approach to let Flash developers step into the realms of Flex and AIR with relative ease. How? Because all of these tools rely on the same ActionScript 3.0 language, even though Flex and AIR support additional features.
Flex (http://www.adobe.com/products/flex/) is a highly productive, free open source platform for building and maintaining expressive web applications. The Flex framework, which includes dozens of visual layout components, user interface components, and data classes for connection to databases and web services, is written in ActionScript 3.0. This means that even though the Flex API contains new functionality, it operates with the same principles of performance, efficiency, and consistency demonstrated earlier in this chapter. Though its output overlaps with the sort of applications traditionally associated with Java or the .NET platform, Flex runs on ActionScript 3.0. If your interests lead you in the direction of Rich Internet Applications (RIAs), you’ll find that your barrier to entry is significantly reduced when you choose Flex as your path.
The Adobe Integrated Runtime (AIR) (http://www.adobe.com/products/air/) lets Flash, Flex, and Dreamweaver developers use their existing skills to build applications that deploy to the desktop. AIR integrates elements of the WebKit browser engine (used by Safari), Flash Player 10, and Acrobat to provide a rich environment for combining the benefits of traditional web technologies like HTML, CSS, and JavaScript with the multimedia aspects of Flash and the PDF file format. AIR also works with the SQLite database management system. Even among these varied avenues, ActionScript 3.0 provides a familiar apparatus for channeling the unique strengths of each into a unified user experience.
Get The ActionScript 3.0 Quick Reference Guide now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.