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

お絵描きの4歩(金色のモコモコ)

Get Adobe Flash player
by nabe 02 Jan 2009
// forked from nabe's forked from: お絵描きの3歩(金色のミミズ)
// forked from nabe's お絵描きの3歩(金色のミミズ)
// forked from nabe's お絵描きの2歩(金色の弾丸)
// forked from nabe's お絵描きの初歩
// forked from nabe's ソースの雛形
package {

    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.text.*;

    [SWF(width="465", height="465", backgroundColor="0xAABBCC", frameRate="1")];
    public class Program_ extends Sprite {
    //全体の処理を受け持つクラス。

        private const radius_:Number = 15;
            //円の半径。

        private var cursor_:Sprite = new Sprite();
            //カーソル。

        private var drag_:Boolean = false;
            //「ドラッグ中」の管理フラグ。

        private var work_:Draw_;
            //描画処理を受け持つインスタンス。

        public function Program_ () {
        //コンストラクタ。ここから全体の処理が開始する。
        //1.初期化処理の呼び出しを仕込むに留める。
            addEventListener(Event.ADDED_TO_STAGE, init_);
        }

        private function init_ (event_:Event):void {
        //初期化処理。
        //1.用済みのリスナ登録を解除する。
            event_.target.removeEventListener(event_.type, arguments.callee);

        //2.ビットマップを配置する。
            var W_:uint = stage.stageWidth;
            var H_:uint = stage.stageHeight;
            var bmd_:BitmapData = new BitmapData(W_, H_, false);
            addChild(new Bitmap(bmd_));

        //4.カーソルを作成する。
            var graphics_:Graphics;
            graphics_ = cursor_.graphics;
            graphics_.lineStyle(0, 0xFF0000);
            graphics_.drawCircle(0, 0, radius_);
            addChild(cursor_);
            cursor_.startDrag(true);

        //5.描画処理の準備をする。
            work_ = new Draw_(bmd_, radius_);

        //6.コマンドを用意する。
            var text_:TextField = new TextField();
            text_.autoSize = TextFieldAutoSize.LEFT;
            text_.background = true;
            text_.text = "Clear!";
            addChild(text_);

        //7.イベント処理を登録する。
            stage.addEventListener(MouseEvent.MOUSE_DOWN, beginDrag_);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onDrag_);
            stage.addEventListener(MouseEvent.MOUSE_UP  , endDrag_);
            text_.addEventListener(MouseEvent.CLICK     , onClear_);
        }

        private function beginDrag_ (event_:MouseEvent):void {
            work_.moveTo_(mouseX, mouseY);
            drag_ = true;
        }

        private function onDrag_ (event_:MouseEvent):void {
            if (!drag_) return;
            work_.lineTo_(mouseX, mouseY);
        }

        private function endDrag_ (event_:MouseEvent):void {
            drag_ = false;
        }

        private function onClear_ (event_:MouseEvent):void {
            work_.clear_();
        }

    }

}

import flash.display.*;
import flash.geom.*;
import flash.filters.*;

class Draw_ extends Sprite {
//描画処理だけ受け持つクラス。

    private var radius_:Number;
        //円の半径。

    private var target_:BitmapData;
        //表示用データ。

    private var zBuffer_:BitmapData;
        //zバッファ用データ。

    private var matrix_:Matrix = new Matrix();
        //使い回しマトリクス。

    private var cmf_:ColorMatrixFilter = new ColorMatrixFilter([
        1, 0, 0, 0, 0,
        0, 1, 0, 0, 0,
        0, 0, 1, 0, 0,
        0xFF, 0, 0, 0, 0,
    ]);
        //αマスク作成用。

    private var lastPos_:Point = new Point();
        //前回のカーソル位置。

    private var v_stamp:Sprite = new Sprite();
        //新規描画用オブジェクト。
        private var v_circle:Shape = new Shape();
            //球。
        private var v_bmd:BitmapData;
            //描画補助データ。
        private var v_bm:Bitmap;
            //棒。

    private var z_stamp:Sprite = new Sprite();
        //zバッファ更新用オブジェクト。
        private var z_circle:Shape = new Shape();
            //球。
        private var z_rect:Shape = new Shape();
            //棒。

    public function Draw_ (target_:BitmapData, radius_:Number) {
    //コンストラクタ。
        this.target_ = target_;
        this.radius_ = radius_;
        build_();
        clear_();
    }

    public function build_ ():void {
    //各種オブジェクトを構築する。

        var g_:Graphics;

        var rect_:Rectangle = new Rectangle(
            -radius_, -radius_, 2 * radius_, 2 * radius_
        );

    //zバッファ用データ。
//内容を書き換える。
        zBuffer_ = target_.clone();

    //新規描画用オブジェクト。
        matrix_.createGradientBox(
            rect_.width, rect_.height, Math.PI/4, rect_.x, rect_.y
        );
        g_ = v_circle.graphics;
        g_.clear();
        g_.beginGradientFill(
            GradientType.RADIAL,
            [0xFFFFF7,0xFFFB8C,0xF7D75A,0xA57100,0x432700],
            [1,1,1,1,1],
            [0x30,0x60,0x90,0xE0,0xFF],
            matrix_,
            SpreadMethod.PAD,
            InterpolationMethod.RGB,
            -0.65
        );
        g_.drawEllipse(rect_.x, rect_.y, rect_.width, rect_.height);
        g_.endFill();
        v_stamp.addChild(v_circle);

        v_bmd = new BitmapData(1, 2 * radius_, false);

        v_bm = new Bitmap(v_bmd);
        v_bm.y = -radius_;
        v_stamp.addChild(v_bm);

        this.addChild(v_stamp);
            //getBounds呼び出し用に親の座標系にaddしておく。

    //zバッファ更新用オブジェクト。
        var color_:Array = [];
        var alpha_:Array = [];
        var ratio_:Array = [];
        var max_:uint = Math.ceil(radius_);
        for (var x_:uint = 0; x_ <= max_; x_ += 1) {
            color_.push(Math.floor((Math.sqrt(max_ * max_ - x_ * x_)) * 0x7F / max_) * 0x010101 + 0x808080);
            alpha_.push(1);
            ratio_.push(Math.floor(x_ * 0xFF / max_));
        }

        matrix_.createGradientBox(
            rect_.width, rect_.height, 0, rect_.x, rect_.y
        );
        g_ = z_circle.graphics;
        g_.clear();
        g_.beginGradientFill(
            GradientType.RADIAL,
            color_, alpha_, ratio_,
            matrix_,
            SpreadMethod.PAD,
            InterpolationMethod.RGB,
            0
        );
        g_.drawEllipse(rect_.x, rect_.y, rect_.width, rect_.height);
        g_.endFill();
        z_stamp.addChild(z_circle);

        matrix_.createGradientBox(
            1, radius_, Math.PI/2, 0, 0
        );
        g_ = z_rect.graphics;
        g_.clear();
        g_.beginGradientFill(
            GradientType.LINEAR,
            color_, alpha_, ratio_,
            matrix_,
            SpreadMethod.REFLECT,
            InterpolationMethod.RGB,
            0
        );
        g_.drawRect(0, -radius_, 1, 2 * radius_);
        g_.endFill();
        z_stamp.addChild(z_rect);

    }

    public function clear_ ():void {
        var rect_:Rectangle = new Rectangle(
            0, 0, zBuffer_.width, zBuffer_.height
        );

        zBuffer_.fillRect(rect_, 0);
        target_.fillRect(rect_, 0);
    }

    private function savePos_ (x_:Number, y_:Number):void {
    //カーソル位置を記憶する。
        lastPos_.x = x_;
        lastPos_.y = y_;
    }

    public function moveTo_ (x_:Number, y_:Number):void {
    //開始点に球を配置する。
        var bounds_:Rectangle = new Rectangle(
            x_ - radius_, y_ - radius_,
            2 * radius_, 2 * radius_
        );

    //描画処理を呼び出す。
        const rot_:Number = 0;
        copy_(x_, y_, rot_, bounds_, v_circle, z_circle);
        savePos_(x_, y_);
    }

    public function lineTo_ (x_:Number, y_:Number):void {
    //現在地点まで線を引く。

        var dir_:Point = new Point(x_ - lastPos_.x, y_ - lastPos_.y);

        var len_:Number = dir_.length;
        var rot_:Number = Math.atan2(dir_.y, dir_.x);

        const k_:Number = 180 / Math.PI;

    //新規描画用オブジェクト。
        v_circle.rotation = -rot_ * k_;
        v_circle.x = len_;

        matrix_.createBox(1, 1, -rot_, 0, radius_);
        v_bmd.draw(v_circle, matrix_);
        v_bm.scaleX = len_;

    //zバッファ更新用オブジェクト。
        z_circle.x = len_;
        z_rect.scaleX = len_;

    //描画領域を求める。
        v_stamp.x = lastPos_.x;
        v_stamp.y = lastPos_.y;
        v_stamp.rotation = rot_ * k_;
        var bounds_:Rectangle = v_stamp.getBounds(this);

    //描画処理を呼び出す。
        copy_(lastPos_.x, lastPos_.y, rot_, bounds_, v_stamp, z_stamp);
        savePos_(x_, y_);
    }

    public function copy_ (
        x_:Number, y_:Number, rot_:Number, bounds_:Rectangle,
        v_shape:DisplayObject, z_shape:DisplayObject
    ):void {
    //描画領域の端数を丸める。
        bounds_.x = Math.floor(bounds_.x);
        bounds_.y = Math.floor(bounds_.y);
        bounds_.width  = Math.ceil(bounds_.width  + 2 * radius_);
        bounds_.height = Math.ceil(bounds_.height + 2 * radius_);

    //描画領域の左上の座標を求める。
        var leftTop_:Point = new Point(
            bounds_.x, bounds_.y
        );

    //作業領域を求める。
        var zeroBounds_:Rectangle = new Rectangle(
            0, 0, bounds_.x, bounds_.y
        );

    //作業領域の左上の座標を求める。
        var zero_:Point = new Point(0, 0);

    //新規描画用の位置・角度を設定する。
        matrix_.createBox(1, 1, rot_, x_ - bounds_.x, y_ - bounds_.y);

    //作業領域を用意する。
        var workBuf_:BitmapData = new BitmapData(
            bounds_.width, bounds_.height, false, 0
        );

    //zバッファの更新内容を用意する。
        workBuf_.draw(z_shape, matrix_, null, BlendMode.NORMAL);

    //αマスクを用意する。ただし他の作業にも流用する。
        var alphaBuf_:BitmapData = new BitmapData(
            bounds_.width, bounds_.height, true
        );

    //現在のzバッファの内容をコピーする。
        alphaBuf_.copyPixels(zBuffer_, bounds_, zero_);

    //zバッファの更新内容から現在の値を差し引く。
        workBuf_.draw(new Bitmap(alphaBuf_), null, null, BlendMode.SUBTRACT);

    //αチャンネルを求める。
        alphaBuf_.applyFilter(workBuf_, zeroBounds_, zero_, cmf_);

    //zバッファを更新する。
        workBuf_.draw(z_shape, matrix_, null, BlendMode.NORMAL);
        zBuffer_.copyPixels(
            workBuf_, zeroBounds_, leftTop_,
            alphaBuf_, zero_, false
        );

    //表示用データを更新する。
        workBuf_.draw(v_shape, matrix_, null, BlendMode.NORMAL);
        target_.copyPixels(
            workBuf_, zeroBounds_, leftTop_,
            alphaBuf_, zero_, false
        );

    }

}