forked from: Saqoosha challenge for professionals(ゆらゆら)
/**
* Copyright Aquioux ( http://wonderfl.net/user/Aquioux )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/4jTc
*/
// forked from checkmate's Saqoosha challenge for professionals
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.display.BlendMode;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.BitmapFilterQuality;
import flash.filters.BlurFilter;
import flash.filters.ColorMatrixFilter;
import flash.filters.DisplacementMapFilter;
import flash.filters.DisplacementMapFilterMode;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
[SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "#000000")]
public class Main extends Sprite {
private const STAGE_WIDTH:uint = stage.stageWidth;
private const STAGE_HEIGHT:uint = stage.stageHeight;
// 表示文字列
private const LETTER:String = "ゆらゆら";
//private const LETTER:String = "布瑠部由良由良止布瑠部";
// 各 BitmapData
private var textBitmapData:BitmapData; // 表示文字列用
private var noiseBitmapData:BitmapData; // perlinNoise 用
private var canvasBitmapData:BitmapData; // 表示用
// BitmapData 用
private const RECT:Rectangle = new Rectangle(0, 0, STAGE_WIDTH, STAGE_HEIGHT);
private const ZERO_POINT:Point = new Point(0, 0);
// マウスイベントリスナーを登録する Sprite
private var mouseEventLayer:Sprite;
// フィルター
private var dmf:DisplacementMapFilter;
private var blur:BlurFilter;
// perlinNoise 用
private var offset:Array = [new Point()];
private var colorCnt:Number = 0;
private var mouseDownCnt:Number = 0; // マウスダウン時間計測用
private const MOUSEDOWN_MAX:uint = 32; // 上記最大値
private const MOUSEDOWN_MIN:uint = 0; // 同最小値
public function Main() {
setupBitmapData();
setupLetter();
setupCanvas();
setFilter();
setExplain();
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
mouseEventLayer.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}
// イベントハンドラ
private function mouseDownHandler(event:MouseEvent):void {
removeEventListener(Event.ENTER_FRAME, mouseUpEnterFrameHander);
addEventListener(Event.ENTER_FRAME, mouseDownEnterFrameHandler);
}
private function mouseUpHandler(event:MouseEvent):void {
removeEventListener(Event.ENTER_FRAME, mouseDownEnterFrameHandler);
addEventListener(Event.ENTER_FRAME, mouseUpEnterFrameHander);
}
// マウスダウン中に ENTER_FRAME に付加する処理
private function mouseDownEnterFrameHandler(event:Event):void {
mouseDownCnt++;
if (mouseDownCnt > MOUSEDOWN_MAX) {
mouseDownCnt = MOUSEDOWN_MAX;
removeEventListener(Event.ENTER_FRAME, mouseDownEnterFrameHandler);
}
}
// マウスアップ後に ENTER_FRAME に付加する処理
private function mouseUpEnterFrameHander(event:Event):void {
mouseDownCnt -= 0.1;
if (mouseDownCnt < MOUSEDOWN_MIN) {
mouseDownCnt = MOUSEDOWN_MIN;
removeEventListener(Event.ENTER_FRAME, mouseUpEnterFrameHander);
}
}
private function enterFrameHandler(event:Event):void {
updatePerlinNoise();
updateDisplacementMapFilter();
updateFade();
canvasBitmapData.draw(textBitmapData);
}
// 初期化処理
// 各 BitmapData 生成
private function setupBitmapData():void{
textBitmapData = new BitmapData(STAGE_WIDTH, STAGE_HEIGHT, true, 0x00000000);
noiseBitmapData = textBitmapData.clone();
canvasBitmapData = textBitmapData.clone();
}
// 文字列生成およびマウスイベントリスナー登録 Sprite 生成
private function setupLetter():void {
var textFormat:TextFormat = new TextFormat(null, 100, 0xFFFFFF);
textFormat.letterSpacing = -5;
var textField:TextField = new TextField();
textField.defaultTextFormat = textFormat;
textField.text = LETTER;
textField.autoSize = TextFieldAutoSize.LEFT;
// TextField を BitmapData 化
var textBitmapData1:BitmapData = new BitmapData(textField.width, textField.height, true, 0x00000000);
textBitmapData1.draw(textField, new Matrix(1, 0, 0, 1, -2, -2));
var rect:Rectangle = textBitmapData1.getColorBoundsRect(0xFF000000, 0x00000000, false);
var textBitmapData2:BitmapData = new BitmapData(rect.width + 4, rect.height + 4, true, 0x00000000);
textBitmapData2.draw(textBitmapData1, new Matrix(1, 0, 0, 1, -rect.x + 2, -rect.y + 2));
textBitmapData1.dispose();
var tx:Number = (STAGE_WIDTH - textBitmapData2.width) / 2;
var ty:Number = (STAGE_HEIGHT - textBitmapData2.height) / 2;
// textBitmapData 確定
textBitmapData.draw(textBitmapData2, new Matrix(1, 0, 0, 1, tx, ty));
// マウスイベントリスナー登録 Sprite 生成
var margin:uint = 30;
mouseEventLayer = new Sprite();
mouseEventLayer.graphics.beginFill(0xFFFFFF, 0);
mouseEventLayer.graphics.drawRect(tx - margin, ty - margin, textBitmapData2.width + margin * 2, textBitmapData2.height + margin * 2);
mouseEventLayer.graphics.endFill();
addChild(mouseEventLayer);
textBitmapData2.dispose();
}
// canvas 生成
private function setupCanvas():void {
addChild(new Bitmap(canvasBitmapData));
//addChild(new Bitmap(noiseBitmapData));
}
// フィルター生成
private function setFilter():void {
// DisplacementMapFilter
dmf = new DisplacementMapFilter(
noiseBitmapData,
ZERO_POINT,
BitmapDataChannel.RED,
BitmapDataChannel.GREEN,
0,
0,
DisplacementMapFilterMode.COLOR
);
// BlurFilter
blur = new BlurFilter(
2,
2,
BitmapFilterQuality.LOW
);
}
// 案内文生成
private function setExplain():void{
var signField:TextField = new TextField();
signField.text = "文字上でマウスをドラッグしてください。\n効果の大きさと持続時間はドラッグ時間の長さに比例します。";
signField.autoSize = TextFieldAutoSize.LEFT;
signField.selectable = false;
signField.blendMode = BlendMode.INVERT;
addChild(signField);
}
// ENTER_FRAME 中の処理
// perlinNoise の更新
private function updatePerlinNoise():void {
var point:Point = offset[0];
point.x += mouseDownCnt / 4;
point.y += mouseDownCnt / 4;
noiseBitmapData.perlinNoise(STAGE_WIDTH / 5, STAGE_HEIGHT / 5, 1, 10, false, true, 1, true, offset);
}
// DisplacementMapFilter 更新および canvasBitmapData への適用
private function updateDisplacementMapFilter():void {
dmf.scaleX = mouseDownCnt;
dmf.scaleY = mouseDownCnt;
canvasBitmapData.applyFilter(canvasBitmapData, RECT, ZERO_POINT, dmf);
}
// フェードアウト
private function updateFade():void{
var c:Object = hsvToRgb(colorCnt++);
canvasBitmapData.colorTransform(RECT, new ColorTransform(c.r, c.g, c.b, 0.93, 1, 1, 1, 0));
canvasBitmapData.applyFilter(canvasBitmapData, RECT, ZERO_POINT, blur);
}
private static function hsvToRgb(h:Number = 0.0, s:Number = 1.0, v:Number = 1.0):Object {
// h : 0.0 - 360.0
// s : 0.0 - 1.0
// v : 0.0 - 1.0
var r:uint = 0;
var g:uint = 0;
var b:uint = 0;
// 各引数を許可範囲に収める
h %= 360;
if (h < 0)
h += 360;
h /= 60;
s = Math.max(0, Math.min(s, 1.0));
v = Math.max(0, Math.min(v, 1.0));
v *= 0xFF;
if (s == 0) {
r = g = b = v;
} else {
var hi:uint = Math.floor(h % 6);
var f:Number = h - hi;
var p:Number = v * (1 - s);
var q:Number = v * (1 - s * f);
var t:Number = v * (1 - s * (1 - f));
switch(hi) {
case 0: {
r = v;
g = t;
b = p;
break;
}
case 1: {
r = q;
g = v;
b = p;
break;
}
case 2: {
r = p;
g = v;
b = t;
break;
}
case 3: {
r = p;
g = q;
b = v;
break;
}
case 4: {
r = t;
g = p;
b = v;
break;
}
case 5: {
r = v;
g = p;
b = q;
break;
}
}
}
return { r:r / 255, g:g / 255, b:b / 255 };
}
}
}