I converted the old webcam motion detection thing to AS3 today. Not that it improves the performance much, just wanted to play around with it (source).
Category Archives: Software Engineering
Some light reading
Just finished ActionScript 3.0 With Design Patterns, recommended to me by a colleague. It introduces ActionScript 3.0 nicely, while pointing out the best practices and common pitfalls. It covers the more popular and useful design patterns and will change the way you code.
However, it had quite a few code typos – most are easy to spot and may be corrected in the next edition anyway – but you will need a sound knowledge of ActionScript already to find this book useful. Despite that, it’s well-structured and highly recommended.
Attaching a Bitmap – AS2 vs AS3
A common task that has changed drastically in ActionScript 3.0 is loading a library image via its linkageID into a BitmapData object and attaching it to a movieclip. In ActionScript 2.0, this can be done like so:
import flash.display.BitmapData var bmp:BitmapData = BitmapData.loadBitmap("linkageID"); var img = createEmptyMovieClip("img",0); img.attachBitmap(bmp,0);
In ActionScript 3.0 movieclips and bitmaps are not attached or created like this – everything is created with the new keyword. Also, a BitmapData object should be dropped into a new Bitmap, which can be added to the stage with the all-important addChild() method.
Since a library bitmap inherits from BitmapData, you now set the class of the bitmap its Linkage Properties in Flash CS3, instantiate it and wrap it in a Bitmap object that you add to the stage:
Where ‘Butterfly’ refers to the bitmap library item you’ve given the class definition ‘Butterfly’. The Base class is generated automatically. These five lines of code can be shortened to one, but is less readable:
var img = addChild(new Bitmap(new Butterfly(0,0)));
Note that in Flex Builder, unlike Flash CS3, you would embed an image using the embed meta tag, associating it with a variable, instead of its Linkage Properties dialog:
[Embed(source='image.jpg')] public var Butterfly:Class;
Building SWFs in Flex Builder is a whole different topic – so stay tuned!
A load of garbage collection
I recently had the pleasure of debugging an AS3 image viewer application that was crashing after an hour. It seemed to be some kind of memory leak, so I looked for objects not being cleared up by the Flash Player’s garbage collector. I found that, even with AS3’s mark and sweep garbage collection, BitmapData objects left stranded (with no external references) still hog RAM, even when their DisplayObject is deleted.
A similar problem existed in AS2, but will be more acute in AS3 I think, because removing a child DisplayObject from a display list does not delete it (as removeMovieClip() would in AS1/2). Try the following example with your Windows Task Manager or Mac Activity Monitor running, you should see what I mean:
import flash.display.* import flash.events.* // Add a main container sprite to the stage var main:Sprite = new Sprite(); addChild(main); // Add event listeners for mouse move and click stage.addEventListener(MouseEvent.MOUSE_MOVE, paint); stage.addEventListener(MouseEvent.CLICK, cleanup); // Draws bitmap noise at the mouse cursor function paint (e:MouseEvent):void { var b = new BitmapData(100,100,false,0xff0000); b.noise(int(Math.random()*int.MAX_VALUE)); var bmp = new Bitmap(b); var spr = new Sprite(); spr.x = e.stageX; spr.y = e.stageY; spr.addChild(bmp); main.addChild(spr); } // Removes all of main's children from the display list function cleanup (e:MouseEvent):void { while (main.numChildren>0) { main.removeChildAt(0); } }
Once the cleanup function runs, all of main’s sprites are removed from the display list, with no more references to them – so the garbage collector should clean things up. But it won’t dispose of the BitmapData objects automatically, so you eventually run out of RAM! This problem of memory hogging occurs even if you keep references to all the clips (in an array for example) and set them to null after removing them from the display hierarchy.
I can see a lot of problems occurring as developers move to AS3 without a firm understanding of how garbage collection works. One answer would be to manually dispose of BitmapData objects or handle the REMOVED_FROM_STAGE event and perform a cleanup as necessary. Here’s quick and dirty fix that cures the memory leak:
function cleanup (e:MouseEvent):void { while (main.numChildren>0) { main.getChildAt(0).getChildAt(0).bitmapData.dispose(); main.removeChildAt(0); } }