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: Painting

画像を抽象絵画風に描画
Get Adobe Flash player
by gyo 12 Aug 2011
/**
 * Copyright gyo ( http://wonderfl.net/user/gyo )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/w3s3
 */

// forked from chutaicho's Painting
/**
画像を抽象絵画風に描画
*/
package 
{
    import __AS3__.vec.Vector;
    
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.TimerEvent;
    import flash.geom.ColorTransform;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;
    import flash.utils.Timer; 
    
    [SWF(backgroundColor="0x000000", frameRate="40")]
    public class AbstractPainting extends Sprite
    {
        private const IMAGE_URL:String = "http://farm6.static.flickr.com/5127/5348947610_96eabf3c9c_b.jpg";
        //-------------------------------------------------------
        //  const
        //-------------------------------------------------------
        private const DOTS_MAX:Number = 50; // 1モーションで保持する頂点数        
        private const FRICTION:Number = 0.98;         
        private const EDGE_COLOR:uint = 0x666666; // 太いラインのエッジカラー        
        
        //-------------------------------------------------------
        //  vars
        //-------------------------------------------------------
        private var _drawImage:BitmapData;
        private var _dotNumber:Number = 0;
        private var _dots:Vector.<Vertex>;
        private var _codeWidth:Number = 1;
        
        private var _startX:Number;
        private var _startY:Number;
        
        private var _layerA:Sprite; // 上のレイヤー(太いライン)
        private var _layerB:Sprite; // 下のレイヤー(細いライン)
        private var _drawTarget:Sprite; // ビットマップ描画するターゲット
        
        private var _canvas:BitmapData; // 描画先
        private var _holder:Sprite;     // 描画したビットマップのいれもの
        
        public function AbstractPainting()
        {
            init();
        }
        private function init():void
        {
            var req:URLRequest = new URLRequest(IMAGE_URL);
            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);    
            loader.load( req, new LoaderContext(true));
            
        }
        private function loadComplete(e:Event):void
        {
            e.target.removeEventListener(Event.COMPLETE, loadComplete);
                var sw:int = stage.stageWidth;
            var sh:int = stage.stageHeight;
            _startX = sw/2;
            _startY = sh/2;
            
            var source:Bitmap = e.target.loader.content as Bitmap;
            source.width  = sw;
            source.height = sh;
            
            _drawImage = new BitmapData(sw,sh, false, 0x000);
            _drawImage.draw(source);
      
            _layerA = new Sprite();// 上のレイヤー
            _layerB = new Sprite();// 下のレイヤー...ちょっとずらす
            _layerB.x = 10;
            _layerB.y = 10;
            
                // 上のレイヤーだけちょっと色かえる
              var colorTransform:ColorTransform = new ColorTransform(1,1,1,2,20,30,20,20);
            _layerB.transform.colorTransform = colorTransform;
            
            _drawTarget = new Sprite();
            _drawTarget.addChild(_layerA);
            _drawTarget.addChild(_layerB);
            
            _holder = new Sprite();
            _holder.x = sw/2;
            _holder.z = 300;
            addChild(_holder);
            
            _canvas = new BitmapData(sw,sh,false,0xEEEEEE);
            var canvasBitmap:Bitmap = new Bitmap(_canvas,"auto",true);
            canvasBitmap.x = -232;
            _holder.addChild(canvasBitmap);

            _dots = new Vector.<Vertex>();
            
            var timer:Timer = new Timer(30, 0);
            timer.addEventListener(TimerEvent.TIMER, createDot);
            timer.start();
            
            addEventListener(Event.ENTER_FRAME, enterFrameHandler);
        }
        private function randomRange( min:Number, max:Number ):Number
        {
            return min + Math.random() * (max + 1 - min);
        }
        //-------------------------------------------------------
        //  Private Event Handler
        //-------------------------------------------------------
        private function createDot(e:TimerEvent):void 
        {
            var dot:Vertex = new Vertex();            
            var px:Number = _startX + randomRange(-40,40);
            var py:Number = _startY + randomRange(-40,40);
            
            // ステージからはみ出たら適当な場所へ戻す
            if(px > stage.stageWidth || py > stage.stageHeight || px < 0 || py < 0)
            {
                px = Math.random() * stage.stageWidth;
                py = Math.random() * stage.stageHeight;
                
                dot.ajust = true; // 位置変更フラグ
            }
            
            _startX = px;
            _startY = py;

                        dot.x = _startX;
            dot.y = _startY;
            
            
            
            _dots.push(dot);    
                
            if (_dotNumber >= DOTS_MAX) 
            {
                var target:Vertex = _dots.shift();
                target = null;
            }    
            _dotNumber ++;    
        }
        private function enterFrameHandler(e:Event):void
        {        
            _layerA.graphics.clear();
            _layerB.graphics.clear();
            
            var codeWidth:Number = 1; // layerBの線の太さ
            var brushThickness:Number = 4; // 線の太さ
            var pressure:Number = 0;       // 筆圧っぽさ
            var l:int = _dots.length;            
            
            // 一回まわして角度を計算しておく
            for(var i:int = l-1; i > 0; i-- )
            {
                if( i != l-1 )
                {
                    var dot:Vertex = _dots[i];                    
                    var dotB:Vertex = _dots[i-1]; // 一つ前のポイント(基準値)
                    var disX:Number = dotB.x - dot.x;
                    var disY:Number = dotB.y - dot.y;
                    // X:Yの角度から垂直になるポイントへの角度
                    dot.angle = Math.atan2(disX, disY) + Math.PI / 2; 
                }
            }
            
            // 線の描画部分 
            for(var j:int = l-1; j > 0; j-- )
            {    
                dot = _dots[j];
                var color:uint = _drawImage.getPixel(dot.x, dot.y);                

                if (j>0)
                {
                    brushThickness += 0.1;
                    codeWidth += 0.01;
                    pressure += 0.02;
                }
                else
                {
                    brushThickness *= FRICTION;
                    codeWidth *= FRICTION;
                    pressure *= FRICTION;
                }
                
                if( j == l-1 )
                {
                    // はみ出たポイントを戻すタイミングで円を書く
                    if(dot.ajust)
                    drawCircle(dot,color);
                    
                    _layerA.graphics.moveTo(dot.x, dot.y);
                    _layerB.graphics.moveTo(dot.x, dot.y);
                }
                else
                {
                    dotB = _dots[j-1];
                    disX = dotB.x - dot.x;
                    disY = dotB.y - dot.y;
                    var mx:Number = dot.x + (disX)*0.4;
                    var my:Number = dot.y + (disY)*0.4;
                    var cosA:Number = brushThickness*Math.cos(dot.angle);
                    var cosB:Number = brushThickness*Math.cos(dotB.angle);
                    var sinA:Number = brushThickness*Math.sin(dot.angle);
                    var sinB:Number = brushThickness*Math.sin(dotB.angle);
                    
                    // 上のレイヤー
                    _layerB.graphics.lineStyle(codeWidth, color, pressure);
                    _layerB.graphics.curveTo(dotB.x, dotB.y, mx, my);
                    _layerB.graphics.lineTo(mx, my);

                    // 下のレイヤー
                    if(!dot.ajust)
                    {
                        _layerA.graphics.beginFill(color,0.4);
                        _layerA.graphics.moveTo(mx,my);                                            
                        _layerA.graphics.lineStyle(0.2, EDGE_COLOR, 0);
                        _layerA.graphics.moveTo(dot.x + cosA, dot.y + sinA);
                        _layerA.graphics.lineTo(dot.x - cosA, dot.y - sinA);
                        _layerA.graphics.lineStyle(0.2, EDGE_COLOR, 0.2);                    
                        _layerA.graphics.lineTo(dotB.x - cosB, dotB.y - sinB);
                        _layerA.graphics.lineStyle(0.2, EDGE_COLOR, 0);
                        _layerA.graphics.lineTo(dotB.x + cosB, dotB.y + sinB);
                        _layerA.graphics.lineStyle(0.2, EDGE_COLOR, 0.2);    
                        _layerA.graphics.lineTo(dot.x + cosA, dot.y + sinA);
                    
                        _layerA.graphics.moveTo(mx, my);
                    }
                }                
            }
            _canvas.draw(_drawTarget);
            
            var center:Number = stage.stageWidth/2;
            var p:Number = (center - mouseX)/center* -180;
                
            SimpleTween.addTween(_holder, {rotationY:p});                
        }
        private function drawCircle(target:Vertex, color:uint):void
        {
            for(var i:int = 0; i<8; i++)
            {
                var px:Number = target.x + randomRange( -100, 100 );
                var py:Number = target.y + randomRange( -100, 100 );
                var r:Number = Math.random()* 4;
                _layerA.graphics.beginFill(color,1);
                _layerA.graphics.drawCircle(px,py,r);
            }
        }
        
    }
}
import flash.display.DisplayObject;
    
/**
頂点クラス
*/   
class Vertex
{
    private const GRAVITY:Number  = 0.5; // 重力
    private const FRICTION:Number = 0.98; // 減速抵抗
    
    public var x:Number;
    public var y:Number;
    public var rad:Number = 2;
    public var color:uint;
    public var randonNum:Number;
    public var angle:Number;
    public var ajust:Boolean = false;
    
    private var speedX:Number;
    private var speedY:Number;
        
    public function Vertex()
    {
        init();
    }
    private function init():void
    {
        var angle:Number = Math.random()*Math.PI*2;
        randonNum = Math.random() * 4;
        speedX = Math.cos(angle) * randonNum;
        speedY = Math.sin(angle) * randonNum;       
    }
    public function upDate():void
    {            
        speedX *= FRICTION;
        speedY *= FRICTION;
        
        x += speedX;
        y += speedY;
    }
}

/**
TWEEN用 あとで使うかも。いまのとこ一回しか使ってない。
*/
class SimpleTween
{
    private static const EASE_VALUE:Number = 0.2;
    
    public static function addTween( target:Object, obj:Object ):void
    {    
        for(var istr:String in obj)
        {
            var a:Number = target[istr];
            var b:Number = obj[istr];
            target[istr] = a + (b-a) * EASE_VALUE;
        }        
    }
    
}