In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: Happy Birthday Koko ;-)

koko さんおたんじょうびおめでとーございまーす :-)
*  happy birthday な画像を使って happy birthday を作るよ。
*
*  @see http://www.flickr.com/groups/happybirthday/
/**
 * Copyright mickymac ( http://wonderfl.net/user/mickymac )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/9WWa
 */

// forked from soundkitchen's Happy Birthday Koko ;-)
/**
 *  koko さんおたんじょうびおめでとーございまーす :-)
 *  happy birthday な画像を使って happy birthday を作るよ。
 *
 *  @see http://www.flickr.com/groups/happybirthday/
 */
package
{
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.events.Event;

    import com.flashdynamix.utils.SWFProfiler;
    import org.libspark.thread.EnterFrameThreadExecutor;
    import org.libspark.thread.Thread;

    [SWF(width=465, height=465, frameRate=30, backgroundColor=0x000000)]

    /**
     *  document class.
     */
    public class HappyBirthdayKoko extends Sprite
    {
        /**
         *  constructor.
         */
        public function HappyBirthdayKoko()
        {
            Wonderfl.disable_capture();
            addEventListener(Event.ADDED_TO_STAGE, initialize);
        }

        /**
         *  initialize.
         */
        private function initialize(evt:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, initialize);

            if (!Thread.isReady)
            {
                //  setup stage.
                stage.align = StageAlign.TOP_LEFT;
                stage.quality = StageQuality.HIGH;
                stage.scaleMode = StageScaleMode.NO_SCALE;

                //
                Thread.initialize(new EnterFrameThreadExecutor());

                //  setup debugger.
                SWFProfiler.init(this);
            }

            new MainThread(this).start();
        }
    }
}

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Graphics;
import flash.display.Loader;
import flash.display.PixelSnapping;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLVariables;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.system.LoaderContext;

import com.adobe.serialization.json.JSON;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.*;
import org.libspark.betweenas3.tweens.ITween;
import org.libspark.thread.Monitor;
import org.libspark.thread.Thread;
import org.libspark.thread.threads.display.LoaderThread;
import org.libspark.thread.threads.net.URLLoaderThread;
import org.libspark.thread.threads.tweener.TweenerThread;
import org.libspark.thread.utils.ParallelExecutor;


/**
 *  main thread.
 */
internal class MainThread extends Thread
{
    private var _layer:DisplayObjectContainer;
    private var _jsonLoader:URLLoader;

    /**
     *  constructor.
     */
    public function MainThread(layer:DisplayObjectContainer)
    {
        _layer = layer;
    }

    /**
     *  show waiting message.
     */
    override protected function run():void
    {
        var th:Thread;

        th = new FixBackgroundThread(_layer);
        th.start();

        th = new WaitAnimationThread(_layer);
        th.start();
        th.join();

        next(loadData);
        interrupted(empty);
    }

    /**
     *  laod data from YQL.
     */
    private function loadData():void
    {
        var req:URLRequest,
            data:URLVariables,
            th:Thread;

        _jsonLoader = new URLLoader();

        data = new URLVariables();
        data['format'] = "json";
        data['diagnostics'] = "false";
        data['q'] = "SELECT * FROM flickr.photos.search(50) WHERE group_id = '62402008@N00'";

        req = new URLRequest();
        req.url = "http://query.yahooapis.com/v1/public/yql";
        req.data = data;

        th = new URLLoaderThread(req, _jsonLoader);
        th.start();
        th.join();

        next(animate);
        interrupted(empty);
    }

    /**
     *
     */
    private function animate():void
    {
        var json:Object,
            row:Object,
            urls:Vector.<String>,
            pool:ImagePool,
            tasks:ParallelExecutor;

        json = JSON.decode(_jsonLoader.data);
        urls = new Vector.<String>();
        for each (row in json.query.results.photo)
        {
            urls.push("http://farm" + row.farm + ".static.flickr.com/" +
                      row.server + "/" + row.id + "_" + row.secret + "_s.jpg");
        }

        Wonderfl.capture_delay(5);
        
        pool = new ImagePool();
        tasks = new ParallelExecutor();

        tasks.addThread(new LoadImageThread(urls, pool));
        tasks.addThread(new LoadImageThread(urls, pool));
        tasks.addThread(new LoadImageThread(urls, pool));
        tasks.addThread(new LoadImageThread(urls, pool));
        tasks.addThread(new LoadImageThread(urls, pool));
        tasks.addThread(new LoadImageThread(urls, pool));
        tasks.addThread(new DisplayImageThread(_layer, pool));

        tasks.start();
    }

    /**
     *  empty task.
     */
    private function empty(...args):void
    {
        //  nothing to do.
    }

    /**
     *  finalize the object.
     */
    override protected function finalize():void
    {
        _layer = null;
    }
}


/**
 *
 */
internal class WaitAnimationThread extends Thread
{
    private var _layer:DisplayObjectContainer;
    private var _message:DisplayObject;

    /**
     *
     */
    public function WaitAnimationThread(layer:DisplayObjectContainer)
    {
        _layer = layer;
    }

    /**
     *
     */
    override protected function run():void
    {
        var txt:TextField,
            data:BitmapData,
            stage:Stage;

        stage = _layer.stage;

        txt = new TextField();
        txt.autoSize = TextFieldAutoSize.LEFT;
        txt.defaultTextFormat = new TextFormat("Lucida Grande", 36);
        txt.text = "click to start";

        data = new BitmapData(txt.width, txt.height, true, 0);
        data.draw(txt);

        _message = new Bitmap(data, PixelSnapping.AUTO, true);
        _message.blendMode = BlendMode.INVERT;
        _message.x = (stage.stageWidth - _message.width) >> 1;
        _message.y = (stage.stageHeight - _message.height) >> 1;
        _layer.addChild(_message);

        event(stage, MouseEvent.CLICK, clickHandler);
    }

    private function clickHandler(evt:MouseEvent):void
    {
        var th:Thread;

        th = new HideMessageThread(_message);
        th.start();
    }

    /**
     *
     */
    override protected function finalize():void
    {
        _layer = null;
        _message = null;
    }
}


/**
 *
 */
internal class HideMessageThread extends Thread
{
    private var _message:DisplayObject;

    /**
     *  constructor.
     */
    public function HideMessageThread(message:DisplayObject)
    {
        _message = message;
    }

    /**
     *  hide message.
     */
    override protected function run():void
    {
        var th:Thread;

        th = new TweenerThread(_message, {
            alpha: 0,
            time: 1,
            transition: "easeOutCubic"
        });
        th.start();
        th.join();

        next(complete);
        interrupted(empty);
    }

    /**
     *  remove message from parent.
     */
    private function complete():void
    {
        var parent:DisplayObjectContainer;

        parent = _message.parent;

        if (parent)
            parent.removeChild(_message);
    }

    /**
     *  empty task.
     */
    private function empty(...args):void
    {
        //  do nothing.
    }

    /**
     *  finalize the object.
     */
    override protected function finalize():void
    {
        _message = null;
    }
}


/**
 *  load image from flickr.
 */
internal class LoadImageThread extends Thread
{
    private var _data:Vector.<String>;
    private var _pool:ImagePool;
    private var _loader:Loader;

    /**
     *  constructor.
     */
    public function LoadImageThread(data:Vector.<String>, pool:ImagePool)
    {
        _data = data;
        _pool = pool;
    }

    /**
     *  load image.
     */
    override protected function run():void
    {
        var req:URLRequest,
            ctx:LoaderContext,
            th:Thread;

        if (!_data.length) return;

        _loader = new Loader();

        req = new URLRequest(_data.shift());
        ctx = new LoaderContext(true);

        th = new LoaderThread(req, ctx, _loader);
        th.start();
        th.join();

        next(complete);
        error(Error, failure);
    }

    /**
     *  stack data to queue and rewind.
     */
    private function complete():void
    {
        var data:BitmapData;

        data = new BitmapData(_loader.width, _loader.height, false, 0);
        data.draw(_loader);

        _pool.offer(data);

        _loader.unload();
        _loader = null;

        next(run);
    }

    /**
     *  error fallback.
     */
    private function failure(e:Error, t:Thread):void
    {
        _loader.unload();
        _loader = null;

        next(run);
    }

    /**
     *  finalize the object.
     */
    override protected function finalize():void
    {
        _data = null;
        _pool = null;
    }
}


/**
 *  show image.
 */
internal class DisplayImageThread extends Thread
{
    private var _layer:DisplayObjectContainer;
    private var _container:Sprite;
    private var _pool:ImagePool;
    private var _map:Vector.<uint>;
    private var _width:uint;
    private var _height:uint;
    private var _index:uint;

    /**
     *  constructor.
     */
    public function DisplayImageThread(layer:DisplayObjectContainer, pool:ImagePool)
    {
        _layer = layer;
        _pool = pool;
        _index = 0;
    }

    /**
     *  create map.
     */
    override protected function run():void
    {
        var i:uint, j:uint,
            l:uint, m:uint,
            txt:TextField,
            map:BitmapData,
            stage:Stage;

        stage = _layer.stage;

        txt = new TextField();
        txt.autoSize = TextFieldAutoSize.LEFT;
        txt.defaultTextFormat = new TextFormat("Arial", 18, 0x000000);//, true);
        txt.text = "Happy\nBirthday\nKoko";

        _width = txt.width >> 0;
        _height = txt.height >> 0;

        map = new BitmapData(_width, _height, true, 0);
        map.draw(txt);

        _map = new Vector.<uint>();
        for (i=0; i<_height; i++)
        {
            for (j=0; j<_width; j++)
            {
                if (map.getPixel32(j, i))
                {
                    _map.push(i*_width+j);
                }
            }
        }
        map.dispose();

        _container = new Sprite();
        _container.transform.matrix = new Matrix(.08, 0, 0, .08,
                                                 stage.stageWidth>>1,
                                                 stage.stageHeight>>1);
        _layer.addChild(_container);

        next(update);
    }

    private function update():void
    {
        var i:uint,
            data:BitmapData,
            bitmap:Bitmap,
            th:Thread,
            tw:ITween,
            angle:Number,
            strength:Number,
            tx:Number, ty:Number;

        if (_pool.check())
        {
            bitmap = new Bitmap(_pool.pickup());

            i = Math.random() * _map.length >> 0;
            i = _map.splice(i, 1).pop();

            tx = int(i % _width) * bitmap.width - _width * bitmap.width / 2;
            ty = int(i / _width) * bitmap.height - _height * bitmap.height / 2;

            angle = Math.random() * Math.PI * 2;
            strength = Math.random() * 200 / _container.scaleX;

            bitmap.alpha = 0;
            bitmap.x = tx + Math.cos(angle) * strength;
            bitmap.y = ty + Math.sin(angle) * strength;
            bitmap.scaleX = bitmap.scaleY = 2 / _container.scaleX;

            tw = BetweenAS3.serial(
                BetweenAS3.addChild(bitmap, _container),
                BetweenAS3.to(bitmap, {
                    x: tx,
                    y: ty,
                    scaleX: 1,
                    scaleY: 1,
                    alpha: 1
                }, 1.5, Expo.easeIn)
            );
            tw.play();
        }
        next(_map.length ? update : complete);
    }

    private function complete():void
    {
        var tw:ITween;

        tw = BetweenAS3.tween(_container, {
            transform: {
                colorTransform: {
                    redMultiplier: 5,
                    greenMultiplier: 5,
                    blueMultiplier: 5
                }
            },
            _glowFilter: {
                color: 0xFFFFFF,
                alpha: .5,
                blurX: 32,
                blurY: 32
            }
        }, {
            _glowFilter: {
                color: 0xFFFFFF,
                alpha: 0,
                blurX: 0,
                blurY: 0
            }
        }, 1.6, Cubic.easeIn);

        tw = BetweenAS3.serial(
            BetweenAS3.delay(tw, 1.6),
            BetweenAS3.reverse(tw)
        );
        tw.play();
    }

    /**
     *
     */
    override protected function finalize():void
    {
        _layer = null;
        _container = null;
        _pool = null;
    }
}


/**
 *  fix background layer.
 */
internal class FixBackgroundThread extends Thread
{
    private var _layer:DisplayObjectContainer;
    private var _background:Shape;

    /**
     *  constructor.
     */
    public function FixBackgroundThread(layer:DisplayObjectContainer)
    {
        _layer = layer;
    }

    /**
     *
     */
    override protected function run():void
    {
        _background = new Shape();
        _layer.addChild(_background);

        update();
    }

    private function update():void
    {
        var stage:Stage,
            gr:Graphics;

        stage = _layer.stage;

        if (!stage) return;

        gr = _background.graphics;
        gr.clear();
        gr.beginFill(0);
        gr.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
        gr.endFill();

        event(stage, Event.RESIZE, resizeHandler);
        interrupted(empty);
    }

    private function resizeHandler(evt:Event):void
    {
        update();
    }

    private function empty(...args):void
    {
        //  nothing to do.
    }

    /**
     *  finalize the object.
     */
    override protected function finalize():void
    {
        _layer.removeChild(_background);
        _layer = null;
        _background = null;
    }
}


/**
 *  image pool
 */
internal class ImagePool
{
    private var _pool:Vector.<BitmapData>;
    private var _monitor:Monitor;

    /**
     *  check pool is empty.
     */
    public function get isEmpty():Boolean
    {
        return _pool.length == 0;
    }

    /**
     *  constructor.
     */
    public function ImagePool()
    {
        _pool = new Vector.<BitmapData>();
        _monitor = new Monitor();
    }

    /**
     *  check data available.
     */
    public function check():Boolean
    {
        var f:Boolean = true;
        if (isEmpty)
        {
            f = false;
            _monitor.wait();
        }
        return f;
    }

    /**
     *  pickup image.
     */
    public function pickup():BitmapData
    {
        return _pool[int(Math.random() * _pool.length)];
    }

    /**
     *  stack new data.
     */
    public function offer(data:BitmapData):void
    {
        _pool.push(data);

        _monitor.notifyAll();
    }
}