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.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() { // stage 上で会いましょう addEventListener(Event.ADDED_TO_STAGE, initialize); } /** * stage に乗ったときの処理 */ private function initialize(evt:Event):void { removeEventListener(Event.ADDED_TO_STAGE, initialize); // 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(); g.beginFill(p.color); g.drawCircle(p.x, p.y, RADIUS); g.endFill(); } film.lock(); film.fillRect(film.rect, 0); film.draw(canvas); 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 { 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 function Particle() { } public function update():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; } } ドット絵的ななにか