A problem occured while loading the plugin: krl_flickr_photoset -> : Assigning the return value of new by reference is deprecated on line 18
kelvinluck.com: Actionscript 3: part 3!
Get Firefox! creative commons

Actionscript 3: part 3!

Update: The example swf doesn’t appear to be working in the new Beta of the Flash 8.5 player… I will look into this when I get a chance…

The evolution of my ActionScript 3 project has continued. Here is the current swf (remember you will need the Flash Player 8.5 to view it):

Sorry, you require Flash 8.5 to view this movie.

As you can see, it’s a whole heap more exciting now… It still creates the mosaic tiles from the original jpeg in the same way as the previous examples but now each tile also listens for an EventType.ENTER_FRAME event. This is basically the same as having a MovieClip.onEnterFrame event handler in older versions of Flash. Each tile is repulsed by the mouse using Barslund Repulsion (thanks to a script I grabbed from Solid Ether).

Here is the code for the example in it’s entirety:

ActionScript:
package
{
        import flash.display.Sprite;
        import flash.display.DisplayObjectContainer;
        import flash.display.Bitmap;
        import flash.util.trace;       
        import flash.display.Loader;
        import flash.display.StageScaleMode;
        import flash.display.BitmapData;
        import flash.net.URLRequest;
        import flash.geom.Rectangle;
        import flash.geom.Point;
        import flash.filters.BlurFilter;
       
        import flash.events.Event;
        import flash.events.EventType;
       
        [SWF(width="500", height="400", backgroundColor="#869CA7")]
        public class Mosaic2 extends Sprite
        {
                private var picLoader:Loader;
               
                public function Mosaic2()
                {
                        stage.scaleMode = StageScaleMode.NO_SCALE;
                       
                        picLoader = new Loader();
                        picLoader.addEventListener(EventType.COMPLETE, onPicLoaded);
                       
                        picLoader.load(new URLRequest("IMG_6032.jpg"));
                }

                private function onPicLoaded(event:Event):Void
                {
                        var mt:MosaicTray = MosaicTray(this.addChild(new MosaicTray(picLoader, picLoader.content)));
                }
        }
       
        private class MosaicTray extends Sprite {
               
                private var TILE_SIZE:uint = 8;
               
                public function MosaicTray(picSprite:DisplayObjectContainer, bitmap:Bitmap)
                {
                        this.x = 150;
                        this.y = 65;
                        var sourceBitmapData:BitmapData = bitmap.bitmapData;
                        var blurFilter:BlurFilter = new BlurFilter(255, 255, 3);
                        var halfTile:uint = Math.round(TILE_SIZE/2);
                        var p:Point = new Point();
                       
                        for (var i:uint=0; i<picSprite.width; i+=TILE_SIZE) {
                                for (var j:uint=0; j<picSprite.height; j+=TILE_SIZE) {
                                        var bd:BitmapData = new BitmapData(TILE_SIZE, TILE_SIZE, false);
                                        var r:Rectangle = new Rectangle(i, j, TILE_SIZE, TILE_SIZE);
                                        // blur the bitmap so we get a more acurate "average" for
                                        // each tile
                                        bd.applyFilter(sourceBitmapData, r, p, blurFilter);
                                        var col:uint = bd.getPixel(halfTile, halfTile);
                                        var mt:MosaicTile = new MosaicTile(i, j, col, TILE_SIZE);
                                        this.addChild(mt);
                                }
                        }
                }
        }
        private class MosaicTile extends Sprite {
               
                private var xHome:uint;
                private var yHome:uint;
                private var force:uint = 300; // experiment with different values
               
                public function MosaicTile(x:uint, y:uint, colour:uint, size:uint)
                {
                        this.x = xHome = x;
                        this.y = yHome = y;
                        graphics.beginFill(colour);
                        graphics.drawRect(0, 0, size-1, size-1);
                        graphics.endFill();
                        this.addEventListener(EventType.ENTER_FRAME, onEnterFrame);
                }
                public function onEnterFrame(evt:Event)
                {
                        // after trying to come up with this code myself and failing I found an
                        // implementation of "Barslund Repulsion" here (and ever so slightly
                        // adapted it to AS3):
        // http://www.solidether.com/luminance/examples/barslundRepulsion.html
                        var xDif:Number = parent.mouseX - x;
                        var yDif:Number = parent.mouseY - y;
                        var distance:Number = Math.sqrt(xDif*xDif+yDif*yDif);
                        var tempX:Number = x - (force/distance)*(xDif/distance);
                        var tempY:Number = y - (force/distance)*(yDif/distance);
                        x = (xHome - x)/2+tempX;
                        y = (yHome - y)/2+tempY;
                }
        }
}

Fairly simple really… And if anything it seems way more efficient and responsive than my attempt at bounce tweening in the last example…

Comments or suggestions for improvements appreciated :)

  1. Possibly add cacheAsBitmap = true in the MosaicTile constructor. That might speed it up quite a bit.
    Jon Bradley    Oct 31, 16:47    #
  2. Good point Jon… I didn’t think that would have much effect on such a simple example but just tried it and found it had a very noticable effect on my machine… Infact it changed the “feel” of the example quite alot and it seemed to lose some “fluidity”...

    Hard to explain but try it on the code above and you might see what I mean (or maybe you will see what I mean without cacheAsBitmap if your computer is faster than mine!).

    Anyway, amazing the difference it made and would definitely recommend it in situations where you were rendering bigger images than this.

    Thanks for the feedback :)
    Kelvin    Oct 31, 23:29    #