forked from: Pixels

by ikekou forked from Pixels (diff: 135)
♥0 | Line 172 | Modified 2010-08-02 13:23:07 | MIT License
play

ActionScript3 source code

/**
 * Copyright ikekou ( http://wonderfl.net/user/ikekou )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/d8hL
 */

// forked from Saqoosha's Pixels
package {
    import frocessing.color.ColorHSV;

    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.events.MouseEvent;
    import flash.geom.PerspectiveProjection;
    import flash.utils.getTimer;

    [SWF(backgroundColor="#000000", frameRate="60", width="475", height="475")]
    
    
    public class Pixels extends Sprite {

        
        private var _canvas:Canvas;

        private var _color:ColorHSV;
        
        //前回描画分の座標?
        private var _px:int;
        private var _py:int;

        
        public function Pixels() {
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            //qualityはLow
            stage.quality = StageQuality.LOW;
            
            //rootのperspectiveProjection取得
            var pp:PerspectiveProjection = root.transform.perspectiveProjection;
            
            //視点または視点の原点(0,0,0)と z 軸上に位置する表示オブジェクトとの距離
            pp.focalLength = 2000;
            
            //取得したperspectiveProjectionを戻す
            //直接書き換えはできない仕様ということか?
            root.transform.perspectiveProjection = pp;
            
            //Canvas
            _canvas = addChild(new Canvas()) as Canvas;
            _color = new ColorHSV();
            
            //座標初期化
            _px = _py = -1;

            //マウスダウンとマウスアップにハンドラ設置
            addEventListener(MouseEvent.MOUSE_DOWN, _onMouseDown);
            addEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
        }


        //マウスが押されたら
        private function _onMouseDown(event:MouseEvent):void {
            //マウスムーブ監視
            addEventListener(MouseEvent.MOUSE_MOVE, _onMouseMove);
            
            //初回描画?
            //でもマウス押下時はピクセル落ちてこない
            //動かすと落ちてくるけど
            _draw();
        }
    
        
        private function _onMouseMove(event:MouseEvent):void {
            //マウス動かすと描画
            _draw();
        }
    
        
        private function _onMouseUp(event:MouseEvent):void {
            //描画中止のためマウスムーブのリスナー外す
            removeEventListener(MouseEvent.MOUSE_MOVE, _onMouseMove);
            
             //再度座標を初期化
            _px = _py = -1;
        }
        
        
        private function _draw():void {
            //HSVのH(色相)変更
            //getTime() / 50で時間とともに滑らかに色相を変更しつつ
            //Math.random() * 30でさらに色を微妙にぶれさせる
            _color.h = getTimer() / 50 + Math.random() * 30;
            
            //currentX,currentYかな
            //この5の意味がまだわからず
            var cx:int = mouseX / 5;
            var cy:int = mouseY / 5;
            
            //描画
            //drawLineを二回呼んでる?意味はまだわからず
            //引数は前回のx、前回のy、今回のx、今回のy、ピクセルの色かな
            if (_px >= 0) _canvas.drawLine(_px, _py, cx, cy, _color.value);
            if (_px >= 0) _canvas.drawLine(_px, _py, cx, cy, _color.value);            
            
            //今回描画分記録
            _px = cx;
            _py = cy;
        }
    }
}

import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.Circ;
import org.libspark.betweenas3.tweens.ITween;

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.PixelSnapping;
import flash.display.Shape;
import flash.display.Sprite;


class Canvas extends Sprite {

    
    //描画結果表示用
    private var _image:Bitmap;
    
    //グリッドの線用
    private var _grid:Bitmap;
    
    //前回描画したxとyでpastX、pastY、かな?
    private var _px:int;
    private var _py:int;

    //コンストラクタ
    public function Canvas() {
        //子をマウスに反応させない
        mouseChildren = false;
        
        //描画結果用初期化
        var b:BitmapData = new BitmapData(95 + 1, 95, false, 0x0);
        _image = addChild(new Bitmap(b, PixelSnapping.ALWAYS, false)) as Bitmap;
        
        //ピクセル5倍
        _image.scaleX = _image.scaleY = 5;
        
        //グリッド一こま分の見た目をシェイプで作る
        var s:Shape = new Shape();
        s.graphics.beginFill(0x101010);
        //グリッドの線をdrawRectで描く
        //縦
        s.graphics.drawRect(4, 0, 1, 5);
        //横
        s.graphics.drawRect(0, 4, 4, 1);
        s.graphics.endFill();
        
        //グリッドひとこまをdraw
        //ひとこま分の大きさ
        var p:BitmapData = new BitmapData(5, 5, true, 0x0);
        //draw
        p.draw(s);
        s.graphics.clear();
        //今度はさっきdrawしたひとこま分のbitmapDataで塗る
        s.graphics.beginBitmapFill(p);
        //大きさはステージの分全部
        s.graphics.drawRect(0, 0, 475 + 5, 475);
        s.graphics.endFill();
        
        //さらにそれを転写するためのbitmapData作成
        b = new BitmapData(475 + 5, 475, true, 0x0);
        //転写
        b.draw(s);
        //表示オブジェクトに追加
        _grid = addChild(new Bitmap(b, PixelSnapping.ALWAYS, false)) as Bitmap;
        
        //多分、初期描画したあとに、"前回と同じ座標なら描画しない"のを回避するために
        //ない座標で初期化
        _px = _py = -1;
    }

    //外から呼ばれる描画メイン処理
    public function drawLine(
        x0:int, 
        y0:int, 
        x1:int, 
        y1:int, 
        color:int
    ):void {
        //前回のy座標と今回のy座標の差、前回のx座標の差と今回のx座標の差を比較
        //y座標のほうが大きく動いていればtrue
        var steep:Boolean = Math.abs(y1 - y0) > Math.abs(x1 - x0);
        
        //何かの一時変数
        var tmp:int;
        
        //y座標のほうが大きく動いている場合
        if (steep) {
            //前回のxをとっておく
            tmp = x0;
            //前回のxを前回のyと同じ値にする
            x0 = y0;
            //前回のyを前回のxに
            y0 = tmp;
            //今回のxをとっておく
            tmp = x1;
            //今回のxを今回のyに書き換え
            x1 = y1;
            //今回のyを今回のxに書き換え
            y1 = tmp;
            
            //今回分と前回分の座標をそれぞれxとyを入れ替え
            //なんのためかはまだわからない
        }
        
        //前回のx座標より今回のx座標が大きい場合、つまり
        //右方向に動いた場合
        if (x0 > x1) {
            //今回と前回のx座標を入れ替え
            tmp = x0;
            x0 = x1;
            x1 = tmp;
            //今回と前回のy座標を入れ替え
            tmp = y0;
            y0 = y1;
            y1 = tmp;
            
            //何のためかはまだわからない
        }
        
        //前回分のxとの距離
        var deltax:int = x1 - x0;
        //前回分のyとの距離の絶対値
        var deltay:int = Math.abs(y1 - y0);
        //エラー?
        //前回分のxとの距離 /2
        //意味はまだわからん
        var error:int = deltax / 2;
        //
        var ystep:int;
        var y:int = y0;
        if (y0 < y1) {
            ystep = 1;
        } else {
            ystep = -1;
        }
        for (var x:int = x0; x <= x1; x++) {
            if (steep) {
                setPixel(y, x, color);
            } else {
                setPixel(x, y, color);
            }
            error = error - deltay;
            if (error < 0) {
                y = y + ystep;
                error = error + deltax;
            }
        }
    }

    //publicだけど、外から呼ばれてるわけではないようだ
    public function setPixel(
        x:int, //x座標
        y:int, //y座標
        color:uint //塗りの色
    ):void {
        //もし前回描画したのと同じ座標だった場合は処理なし
        if (x == _px && y == _py) return;
        
        //今回描画ポイント記憶
        _px = x;
        _py = y;
        
        //ピクセルにグレーの色塗る
        _image.bitmapData.setPixel32(x, y, 0x333333);
        
        //シェイプ生成
        var s:Shape = new Shape();
        //引数に指定された色の矩形作成
        s.graphics.beginFill(color);
        s.graphics.drawRect(-2, -2, 3, 3);
        s.graphics.endFill();
        
        //この計算の意味はまだよくわからず
        s.x = x * 5 + 2 + Math.random() * 200 - 100;
        s.y = y * 5 + 2 + Math.random() * 200 - 100;
        
        //z位置を手前に配置
        s.z = -2000;
        
        //ランダムで回転させる
        s.rotationX = Math.random() * 360 - 180;
        s.rotationY = Math.random() * 360 - 180;
        s.rotationZ = Math.random() * 360 - 180;
        
        //スケール10倍
        s.scaleX = s.scaleY = 10;
        //透明に
        s.alpha = 0;
        //表示オブジェクトに追加
        addChild(s);
        
        //BetweenAS3でトゥイーン作成
        var t:ITween = BetweenAS3.to(s, {
            //ここの計算が・・・
            x: x * 5 + 2,
            y: y * 5 + 2,
            //奥行き0に
            z: 0,
            //回転も元に戻す
            rotationX: 0,
            rotationY: 0,
            rotationZ: 0,
            //スケールも戻す
            scaleX: 1,
            scaleY: 1,
            //アルファも戻す
            alpha: 1.0
        //1秒かけてイージングはCircのイーズアウト
        }, 1.0, Circ.easeOut);
        
        //トゥイーンが完了したら
        t.onComplete = function ():void {
            //シェイプを表示オブジェクトから削除
            s.parent.removeChild(s);
            //同時に、同じ位置にビットマップに色を塗る
            //これで見た目には到達したシェイプはそのままの位置に
            _image.bitmapData.setPixel32(x, y, color);
        };
        //トゥイーン開始
        t.play();
    }
}