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();
}
}