Elastic String (残像版)
Elastic String(残像版)
Elastic Pixels(残像版) の発展
Elastic Pixels 2 残像版
Elastic Pixels 1
あちこちのコードをパッチワーク
// Elastic String(残像版)
// Elastic Pixels(残像版) の発展
//
// forked from Aquioux's forked from: Elastic Pixels(残像版)
// Elastic Pixels 2 残像版
// forked from Aquioux's Elastic Pixels
// Elastic Pixels 1
// あちこちのコードをパッチワーク
package {
/**
* @author YOSHIDA, Akio
*/
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.ColorTransform;
[SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "#000000")]
public class Main2 extends Sprite {
private var aryParticle:Array; // パーティクル格納配列
private var isMouseDown:Boolean = false; // マウスをダウンしているか否か
private var distanceOfReaction:uint = 100; // マウスに反応する距離
private var spring:Number = 0.075; // バネ係数
private var friction:Number = 0.93; // 摩擦係数
private var bmdCaptured:BitmapData; // Particle を打つ BitmapData
private var bmdDisplay:BitmapData; // 表示する BitmapData
private var tpx:TextPixelizer;
private const TONEDOWN:ColorTransform = new ColorTransform(1, 0.9, 0.25, 0.7);
// コンストラクタ
public function Main2() {
var w:uint = stage.stageWidth;
var h:uint = stage.stageHeight;
bmdCaptured = new BitmapData(w, h, true, 0xff000000);
bmdDisplay = new BitmapData(w, h, true, 0xff000000);
addChild(new Bitmap(bmdDisplay));
tpx = new TextPixelizer("_serif", 60, 0x000000);
tpx.addEventListener(PixelizerEvent.COMPLETE, completeHandler);
tpx.pixelize("wonderfl\nbuild flash\nonline");
}
private function completeHandler(e:PixelizerEvent):void {
var offsetX:Number = (stage.stageWidth - tpx.width) / 2;
var offsetY:Number = (stage.stageHeight - tpx.height) / 2;
var data:Vector.<Pixel> = tpx.data;
aryParticle = [];
for each(var pixel:Pixel in data) {
var alpha:uint = tpx.getAlpha(pixel.color);
if (alpha > 0x7f) {
var particle:Particle = new Particle(pixel.x + offsetX, pixel.y + offsetY);
aryParticle.push(particle);
}
}
tpx = null;
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
private function enterFrameHandler(e:Event):void {
bmdCaptured.lock();
bmdCaptured.fillRect(bmdCaptured.rect, 0x00000000);
var mousePoint:Point = new Point(mouseX, mouseY);
for each (var particle:Particle in aryParticle) {
particle.update(mousePoint, isMouseDown, distanceOfReaction, spring, friction);
bmdCaptured.setPixel32(particle.x, particle.y, 0xffffffff);
}
bmdCaptured.unlock();
bmdDisplay.colorTransform(bmdDisplay.rect, TONEDOWN);
bmdDisplay.draw(bmdCaptured);
}
private function mouseDownHandler(e:MouseEvent):void {
isMouseDown = true;
}
private function mouseUpHandler(e:MouseEvent):void {
isMouseDown = false;
}
}
}
import flash.geom.Point;
class Particle {
// 既定座標
private var localX:Number;
private var localY:Number;
// ベロシティ
private var vx:Number = 0;
private var vy:Number = 0;
// 現在座標
private var _x:Number;
private var _y:Number;
private var offset:int;
public function Particle(x:Number, y:Number) {
_x = localX = x;
_y = localY = y;
offset = Math.floor(Math.random()) * 30 - 15;
}
public function update(mousePoint:Point, isMouseDown:Boolean, distanceOfReaction:uint, spring:Number, friction:Number):void {
// 到達値
var dx:Number;
var dy:Number;
var distance:Number = Point.distance(mousePoint, new Point(localX, localY));
var direction:Number = isMouseDown ? 1 : -1;
if (distance < distanceOfReaction) {
var diff:Number = distance * direction * (distanceOfReaction - distance) / distanceOfReaction + offset;
var radian:Number = Math.atan2(mousePoint.y - localY, mousePoint.x - localX);
var diffPoint:Point = Point.polar(diff, radian);
dx = localX + diffPoint.x;
dy = localY + diffPoint.y;
} else{ // 位置を元に戻す
dx = localX;
dy = localY;
}
vx += (dx - _x) * spring;
vy += (dy - _y) * spring;
vx *= friction;
vy *= friction;
_x += vx;
_y += vy;
}
public function get x():Number { return _x; }
public function get y():Number { return _y; }
}
class Pixel {
private var _x:Number;
private var _y:Number;
private var _color:uint; // 32 bit color
public function Pixel(x:Number, y:Number, color:uint) {
_x = x;
_y = y;
_color = color;
}
public function get x():Number { return _x; }
public function get y():Number { return _y; }
public function get color():uint { return _color; }
public function set x(value:Number):void { _x = value; }
public function set y(value:Number):void { _y = value; }
public function set color(value:uint):void { _color = value; }
}
import flash.display.BitmapData;
import flash.events.Event;
import flash.events.EventDispatcher;
class Pixelizer extends EventDispatcher {
// ピクセル格納ベクター
private var _data:Vector.<Pixel>;
// スキャンサイズ
private var _width:uint = 0; // 幅
private var _height:uint = 0; // 高
public function Pixelizer() {}
// 走査
public function scan(bmd:BitmapData):void {
var w:uint = _width = bmd.width;
var h:uint = _height = bmd.height;
var i:uint = 0;
_data = new Vector.<Pixel>(w*h, true);
for (var y:uint = 0; y < h; y++){
for (var x:uint = 0; x < w; x++){
_data[i++] = new Pixel(x, y, bmd.getPixel32(x, y));
}
}
// BitmapData 消去
bmd.dispose();
// イベント発行
dispatchEvent(new PixelizerEvent(PixelizerEvent.COMPLETE));
}
// 32 bit color のアルファ値を取得
public function getAlpha(c:uint):uint {
return (c >> 24) & 0xff;
}
// getter(pixelize 実行後に有効)
public function get data():Vector.<Pixel> { return _data; }
public function get width():uint { return _width; }
public function get height():uint { return _height; }
}
import flash.display.BitmapData;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.geom.Matrix;
import flash.text.TextField;
import flash.text.TextFormat;
class TextPixelizer extends EventDispatcher {
// バックエンドクラス
private var px:Pixelizer;
// テキストフォーマット用変数
private var _font:String = "_serif";// フォント名
private var _size:uint = 16; // フォントサイズ
private var _color:uint = 0x000000; // フォントカラー
static public const TRANSPARENT:uint = 0x00000000;
public function TextPixelizer(font:String = "_serif", size:uint = 16, color:uint = 0x000000) {
_font = font;
_size = size;
_color = color;
}
// ピクセル情報作成
public function pixelize(str:String):void {
// バックエンドクラス設定
px = new Pixelizer();
px.addEventListener(PixelizerEvent.COMPLETE, completeHandler);
// TextField 生成
var fld:TextField = new TextField();
fld.defaultTextFormat = new TextFormat(_font, _size, _color);
fld.text = str;
fld.autoSize = "left";
// BitmapData 生成
var w:Number = fld.width - 4;
var h:Number = fld.height - 4;
var bmd:BitmapData = new BitmapData(w, h, true, TRANSPARENT);
bmd.draw(fld, new Matrix(1, 0, 0, 1, -2, -2));
// 走査
px.scan(bmd);
}
private function completeHandler(e:Event):void {
dispatchEvent(new PixelizerEvent(PixelizerEvent.COMPLETE));
}
// 32 bit color のアルファ値を取得
public function getAlpha(c:uint):uint {
return px.getAlpha(c);
}
// getter(pixelize 実行後に有効)
public function get data():Vector.<Pixel> { return px.data; }
public function get width():uint { return px.width; }
public function get height():uint { return px.height; }
// setter(pixelize 実行前のみ有効)
public function set font(value:String):void { _font = value; }
public function set size(value:uint):void { _size = value; }
public function set color(value:uint):void { _color = value; }
}
import flash.events.Event;
class PixelizerEvent extends Event {
public static const COMPLETE:String = "complete";
public function PixelizerEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
super(type, bubbles, cancelable);
}
public override function clone():Event {
return new PixelizerEvent(type, bubbles, cancelable);
}
public override function toString():String {
return formatToString("PixelizerEvent", "type", "bubbles", "cancelable", "eventPhase");
}
}