Beautifl - Flash Gallery

Thumbnail : forked from: ぷよんぷよんな栗様(drawTrianglesによる描画バージョン
forked from: ぷよんぷよんな栗様(drawTrianglesによる描画バージョン
fumix 2009-08-30 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

// forked from fumix's ぷよんぷよんな栗様(キレイなぷよんぷよんバージョン
/*

ぷよんぷよんな栗様

元ネタ

画像を行列で変形:てらこ23で発表したものの説明2
http://wonderfl.net/code/e56e31f395e7f7457464b00111a6dab5aadc3c7f

ぷよんぷよんな動き:Grid
http://wonderfl.net/code/b287f881a7e6e1f5c6f71d441134b7672dcc4884

どうしても、行列での画像変形がうまくいかずヒビが入ってしまいます涙
一回Bitmapに書き出さず、一気に変換かければうまくいくと思うのですが・・・

埒が明かないのでGraphics.drawTriangles()による描画にしてみる。
すっごいきれいになったが・・・負けた気がするorz
参考:http://www.adobe.com/jp/devnet/flash/articles/graphics_draw_triangles_part2.html

*/
package
{
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	
	//import net.hires.debug.Stats;
	
	[SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "0x000000")]
	public class puyon extends Sprite
	{
		private var _container:Sprite;
		private var _canvas:Sprite;
		private var _bmdCurrent:BitmapData;
		
		private var _stageW:Number = 465;
		private var _stageH:Number = 465;
		private var _w:Number;
		private var _cP0:CirclePoint;
		private var _cP1:CirclePoint;
		private var _cP2:CirclePoint;
		private var _cP3:CirclePoint;
		private var _matrixArrayCurrent:Array;
		private var _pointsArray:Array;
		//分割数。増やせば細かくなるが、画像変換がうまくいってないので、増やすとヒビが大きくなるだけ・・・
		private var Pice:int = 15;

        private var Reaction:uint = 100;//変化する範囲(半径) 
        private var spring:Number = 0.75;//びよーんってなる数(振動数??
        private var friction:Number = 0.85;//びよーんってなる大きさ

		
		
		private const IMAGE_URL:String = "http://www.planet-ape.net/wonderfl/kuri.jpg";			
		private var nextButton:Sprite;
		
		private var mouseSp:Sprite;
		
		public function puyon()
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
            removeEventListener(Event.ADDED_TO_STAGE, init);
            //画像の読み込み
            var req:URLRequest = new URLRequest(IMAGE_URL);
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);    
			loader.load( req, new LoaderContext(true));
			// take a capture after 10 sec
			//Wonderfl.capture_delay( 120 );
		}
		
		//画像読み込み後の処理
		private function loadComplete(e:Event):void 
		{
			e.target.removeEventListener(Event.COMPLETE, loadComplete);
		
			//取得した画像を切り取って_bmdCurrentに入れる
			_bmdCurrent = new BitmapData (465, 465, true, 0xFFFFFF);
			_bmdCurrent.draw (e.target.loader.content.bitmapData);
			
			//キャンバスを用意してコンテナに入れる(重要じゃないので無視無視)
			_canvas = new Sprite();
			_container = new Sprite();
			_container.addChild(_canvas);
			addChild(_container);
			_container.x = 0;//(_stageW - _bmdCurrent.width)/2;
			_container.y = 0;//(_stageH - _bmdCurrent.height)/2;

			//画像の大きさに合わせ、ポイントを7x7の格子に配置する(配列に入れる)
			//CirclePointのコンストラクタの中で初期状態のポイント位置を保持してます。(initPoint)
			//その初期ポイントと、マウスドラッグで移動したポイントを比較してるのが、_drawの中。
			_w = _bmdCurrent.width / Pice;

			_matrixArrayCurrent = new Array ();
			_pointsArray = new Array();
			//x軸とy軸の2重ループ(配列に入れる
			for (var j:int = 0; j <= _bmdCurrent.width; j += _w) {
				for (var i:int = 0; i <= _bmdCurrent.height; i += _w) {
					var cp1:CirclePoint = new CirclePoint (i, j);
					_matrixArrayCurrent.push (cp1);
					_container.addChild (cp1);

					var _points:Points = new Points(i,j);
					_pointsArray.push(_points);
					//cp1.addEventListener(MouseEvent.MOUSE_DOWN , _cPMouseDownHandler );
				}
			}
			
			//_draw ();
			addEventListener(Event.ENTER_FRAME,onEnterFrameHandler);
			
			//速度とかメモリとかチェック(重要じゃないので無視無視)
			//addChild(new Stats());
		}
		private function onEnterFrameHandler(e:Event):void{
			var mousePoint:Point = new Point(mouseX, mouseY);
			var i:int;
			for each (var _point:Points in _pointsArray) { 
				_point.update(mousePoint,  Reaction, spring, friction);
				_matrixArrayCurrent[i].x = _point.x;
				_matrixArrayCurrent[i].y = _point.y;
				i++;
			}
			_draw();
		}
		private function _draw():void {
			/**
			 * ポイントの番号は↓な感じ。
			 *   0--------1
			 *   ----------
			 *   ----------
			 *   2--------3
			 */			
			//マトリックスを適応
			_canvas.graphics.clear();

			//配列のループ
			for (var k:String in _matrixArrayCurrent) {
				//
				if (int(k) > _matrixArrayCurrent.length - (Pice+3)) break;
				if ((int (k) + 1) % (Pice+1) == 0) continue;
				//初期状態のポイント取得
				_cP0 = _matrixArrayCurrent[int (k)];
				_cP1 = _matrixArrayCurrent[int (k) + 1];
				_cP2 = _matrixArrayCurrent[int (k) + (Pice+1)];
				_cP3 = _matrixArrayCurrent[int (k) + (Pice+2)];
				
				var aP0:Point = _cP0.initPoint;
				var aP1:Point = _cP1.initPoint;
				var aP2:Point = _cP2.initPoint;
				var aP3:Point = _cP3.initPoint;

				//初期状態のポイントよりマトリックス取得
				//var initMatrix1:Matrix = _getTransformMatrix( aP0 , aP1 , aP2 );
				//var initMatrix2:Matrix = _getTransformMatrix( aP3 , aP2 , aP1 );
				//変更状態のポイント取得
				var bP0:Point = new Point(_cP0.x , _cP0.y );
				var bP1:Point = new Point(_cP1.x , _cP1.y );
				var bP2:Point = new Point(_cP2.x , _cP2.y );
				var bP3:Point = new Point (_cP3.x , _cP3.y );
				//変更状態のポイントよりマトリックス取得
				//var editMatrix1:Matrix = _getTransformMatrix( bP0 , bP1 , bP2);
				//var editMatrix2:Matrix = _getTransformMatrix( bP3 , bP2 , bP1 );
				//初期状態と変更状態のマトリックスを合体
				//var newMatrix1:Matrix = initMatrix1.clone();
				//newMatrix1.concat(editMatrix1);
				//var newMatrix2:Matrix = initMatrix2.clone();
				//newMatrix2.concat(editMatrix2);
				
				//Graphics.drawTriangles()による描画にしてみる
				var indices:Vector.<int> = new Vector.<int>();
				var uvtData:Vector.<Number> = new Vector.<Number>();				
				// 三角形の頂点番号の組合わせ(第2引数)
				indices.push(0,1,2);
				indices.push(1,3,2);
				// テクスチャマッピングのuv座標(第3引数)
				uvtData.push(aP0.x/_stageW,aP0.y/_stageH);
				uvtData.push(aP1.x/_stageW,aP1.y/_stageH);
				uvtData.push(aP2.x/_stageW,aP2.y/_stageH);
				uvtData.push(aP3.x/_stageW,aP3.y/_stageH);
				// 三角形の頂点座標(第1引数)
				var vertices:Vector.<Number> = new Vector.<Number>();
				vertices.push(bP0.x, bP0.y);
				vertices.push(bP1.x, bP1.y);
				vertices.push(bP2.x, bP2.y);
				vertices.push(bP3.x, bP3.y);

				_canvas.graphics.beginBitmapFill(_bmdCurrent,null,true,true);
				_canvas.graphics.drawTriangles( vertices, indices, uvtData);
				
				
				//(無理やり)分割した1個目の描写のロジック
				//2個目はわざわざ、別のbitmapDataを用意しなくても直接描画できる。
				//1個目は別のbitmapDataを用意ないと順番がめちゃくちゃになる。
				/*
				var matBmd:BitmapData = new BitmapData(465,465);
				var mat:Matrix = new Matrix ();
				mat.tx = - aP0.x;// +(aP0.x - aP2.x);
				mat.ty = - aP0.y;
				matBmd.draw (_bmdCurrent,mat);
				//分割した1個目を描画
				//_canvas.graphics.lineStyle(1 , 0x00FF00);
				_canvas.graphics.beginBitmapFill(matBmd , newMatrix1,true,true );
				_canvas.graphics.moveTo(bP1.x , bP1.y );
				_canvas.graphics.lineTo(bP2.x , bP2.y );
				_canvas.graphics.lineTo(bP0.x , bP0.y );
				_canvas.graphics.lineTo(bP1.x , bP1.y );
				_canvas.graphics.endFill ();

				//分割した2個目を描画
				//_canvas.graphics.lineStyle(0 , 0x00FF00);
				_canvas.graphics.beginBitmapFill(_bmdCurrent , newMatrix2,true,true );
				_canvas.graphics.moveTo(bP3.x , bP3.y );
				_canvas.graphics.lineTo(bP1.x , bP1.y );
				_canvas.graphics.lineTo(bP2.x , bP2.y );
				_canvas.graphics.lineTo(bP3.x , bP3.y );
				_canvas.graphics.endFill();
				*/
			}
		}
		
		
		private function _getTransformMatrix($pt0:Point, $pt1:Point, $pt2:Point):Matrix
		{
			/*
			http://www.adobe.com/jp/devnet/flash/articles/matrix_class.html
			a: 水平方向の伸縮率 = 変換後の幅/もとの幅
			b: 垂直方向の傾斜率 = 垂直方向の傾斜/もとの幅
			c: 水平方向の傾斜率 = 水平方向の傾斜/もとの高さ
			d: 垂直方向の伸縮率 = 変換後の高さ/もとの高さ
			tx: 水平方向の移動ピクセル数
			ty: 垂直方向の移動ピクセル数
			*/
			var w:Number = _w;
			var h:Number = _w;
			var mat:Matrix = new Matrix();
			mat.a = ($pt1.x - $pt0.x) / w;
			mat.b = ($pt1.y - $pt0.y) / w;
			mat.c = ($pt2.x - $pt0.x) / h;
			mat.d = ($pt2.y - $pt0.y) / h;
			mat.tx = $pt0.x;
			mat.ty = $pt0.y;
			return mat;
		}
		
		//こっからマウスのドラッグとかの設定(無視無視)
		private function _cPMouseDownHandler(e:MouseEvent):void {
			CirclePoint(e.target).startDrag();
			CirclePoint(e.target).addEventListener(MouseEvent.MOUSE_MOVE , _cPMouseMoveHandler );
			stage.addEventListener(MouseEvent.MOUSE_UP , _cPMouseUpHandler );
		}
		
		private function _cPMouseUpHandler(e:MouseEvent):void {
			CirclePoint(e.target).stopDrag();
			CirclePoint(e.target).removeEventListener(MouseEvent.MOUSE_MOVE , _cPMouseMoveHandler );
			stage.removeEventListener(MouseEvent.MOUSE_UP , _cPMouseUpHandler );
		}
		
		private function _cPMouseMoveHandler(e:MouseEvent):void {
			_draw();
		}
		
		

	}
}


import flash.display.Bitmap;
import flash.display.Shape;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.geom.Point;

/**
 * 赤い点を書いてる。
 * それと初期状態のポイントをinitPointに保持してる。
 */
class CirclePoint extends Sprite {
	public var initPoint:Point;
	
	public function CirclePoint($x:Number , $y:Number) {
		x = $x;
		y = $y;
		this.initPoint = new Point( $x , $y );
		//this.graphics.beginFill(0xFF0000,1);
		//this.graphics.drawCircle(0,0,5);
		//this.graphics.endFill();
		//this.buttonMode = true;
	}	
}
import flash.geom.Point;
class Points { 
     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; 
    public function Points(x:Number, y:Number) { 
        _x = localX = x; 
        _y = localY = y; 
    } 
    public function update(mousePoint:Point, Reaction:uint, spring:Number, friction:Number):void { 
        var dx:Number; 
       var dy:Number; 
        var distance:Number = Point.distance(mousePoint, new Point(localX, localY)); 
        if (distance < Reaction) { 
            var diff:Number     = distance * -1 * (Reaction - distance) / Reaction; 
            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; } 
}