forked from: ドット絵的ななにか
画像読み込んでゴニョゴニョするよ
// forked from soundkitchen's ドット絵的ななにか
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Loader;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.filters.BlurFilter;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.MouseEvent;
import flash.events.SecurityErrorEvent;
import flash.geom.Point;
import flash.net.URLRequest;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
[SWF(frameRate=60, width=465, height=465, backgroundColor=0x000000)]
/**
* 画像読み込んでゴニョゴニョするよ
*/
public class Main extends Sprite
{
/**
* 適当に選んだ Flickr のサムネイル画像の URL
*/
public static const IMAGE_URL:String = 'http://farm3.static.flickr.com/2320/2056363823_ee69da67b9_s.jpg';
/**
* ぽつぽつの半径
*/
public static const RADIUS:Number = 3;
private var parts:Vector.<Particle>;
private var canvas:Shape;
private var film:BitmapData;
/**
* コンストラクタ
*/
public function Main()
{
addEventListener(Event.ENTER_FRAME, this.enterFrameHandler);
}
/**
* stage を監視
* firefox3@mac対応
*/
private function enterFrameHandler(event:Event):void
{
if (stage.stageWidth && stage.stageHeight)
{
removeEventListener(Event.ENTER_FRAME, this.enterFrameHandler);
initialize();
}
}
/**
* stage のサイズが取得できた時の処理
*/
private function initialize():void
{
// stage の設定
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.MEDIUM;
stage.scaleMode = StageScaleMode.NO_SCALE;
// 色々書き込むためのキャンバス用 Shape
canvas = new Shape();
// 最終的に書き込まれるフィルム用 BitmapData
film = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0);
addChild(new Bitmap(film));
// 画像読み込み処理へ
loadImage();
}
/**
* 画像を読み込む処理
*/
private function loadImage():void
{
var req:URLRequest,
loader:Loader,
ctx:LoaderContext;
req = new URLRequest(IMAGE_URL);
ctx = new LoaderContext(true);
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadFailure);
loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, loadFailure);
loader.load(req, ctx);
}
/**
* 画像読み込み完了時の処理
*/
private function loadComplete(evt:Event):void
{
var i:uint,
w:uint, h:uint,
centerX:Number, centerY:Number,
angle:Number,
p:Particle,
bmd:BitmapData;
centerX = stage.stageWidth / 2;
centerY = stage.stageHeight / 2;
// 元画像を取ってくる
bmd = Bitmap(evt.target.content).bitmapData;
// 必要な数だけパーティクルを作る
parts = new Vector.<Particle>(bmd.width * bmd.height, true);
for (i=0; i<parts.length; i++)
{
// 縦・横のポジションを計算
w = Math.floor(i % bmd.width);
h = Math.floor(i / bmd.width);
// パーティクル作るよ。
p = new Particle();
// 色を元画像から取ってくる。
p.color = bmd.getPixel(w, h);
// 目標地点をセット
p.end = new Point(w * RADIUS * 2 + RADIUS,
h * RADIUS * 2 + RADIUS);
// スタート地点をセット
angle = Math.random() * Math.PI * 2;
p.start = new Point(Math.cos(angle) * 500 + centerX,
Math.sin(angle) * 500 + centerY);
// FIXME: ココがダサい
// スタート地点を現在地にコピー
p.x = p.start.x;
p.y = p.start.y;
// 配列に特攻む
parts[i] = p;
}
// 元画像を破棄
bmd.dispose();
// イベント群を登録
addEventListener(Event.ENTER_FRAME, step);
stage.addEventListener(MouseEvent.CLICK, toggleReverse);
}
/**
* 毎フレームでパーティクルを動かす
*/
private function step(evt:Event):void
{
var i:uint,
l:uint,
p:Particle,
g:Graphics;
l = parts.length;
g = canvas.graphics;
g.clear();
for (i=0; i<l; i++)
{
p = parts[i];
p.update(stage.mouseX, stage.mouseY);
g.beginFill(p.color);
g.drawCircle(p.x, p.y, RADIUS * p.scale);
g.endFill();
}
film.lock();
film.fillRect(film.rect, 0);
film.draw(canvas);
film.applyFilter(film, film.rect, new Point(0, 0), new BlurFilter(5, 5));
film.unlock();
}
/**
* stage をクリックされた時の処理
*/
private function toggleReverse(evt:MouseEvent):void
{
// reverse なフラグを逆にする
Particle.reverse = !Particle.reverse;
}
/**
* 読み込みエラー時の処理
*/
private function loadFailure(evt:Event):void
{
// トレースするだけ
trace(evt);
}
}
}
import flash.geom.Point;
class Particle
{
private const SPRING_CONST:Number = 0.11;
private const FRICTION:Number = 0.89;
public static var reverse:Boolean = false;
public var start:Point;
public var end:Point;
public var color:uint;
public var x:Number;
public var y:Number;
public var v:Number = 0;
public var tmpScale:Number = 0;
public var scale:Number = 0;
public function Particle()
{
}
public function update(mouseX:Number, mouseY:Number):void
{
var target:Point,
delta:Point;
target = reverse ? start : end;
delta = target.subtract(new Point(x, y));
x += delta.x * .1;
y += delta.y * .1;
var dx:Number = mouseX - x;
var dy:Number = mouseY - y;
var distance:Number = Math.sqrt(dx * dx + dy * dy);
if (distance < 100)
{
tmpScale = 1 + (10 / (distance / 10 + 1));
}
else
{
tmpScale = 1;
}
this.applyScale();
}
private function applyScale():void
{
var scaledis:Number = tmpScale - scale;
var a:Number = SPRING_CONST * scaledis;
v += a;
v *= FRICTION;
scale += v;
scale += v;
}
}