In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

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