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

ff: [betweenAS3]BubbleSort And SelectionSort

---- Original comment by applicott --------------------
*  クリックするたびに動きます。
*  上手く可視化出来なかった。。。
*  シャッフル > BubbleSort > Shuffle > SelectionSort >>>....
* 
* ---- Additional comment by matacat --------------------
*  Click the stage to toggle motions.
*  shuffle -> selection sort ->
*    shuffule -> bubble sort ->
*      shuffle -> selection sort -> ...
* 
*  大体こんな感じでしょうか?ソートの解釈間違えてるかもです...
*  今回初めて BetweenAS3 を使わせていただきましたが、
*  たのしいですねこれ!調整しては眺めるのを繰り返していたら
*  いつの間にか一日が終わってました。
Get Adobe Flash player
by matacat 18 Apr 2010
/**
 * Copyright matacat ( http://wonderfl.net/user/matacat )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/pswp
 */

// forked from applicott's [betweenAS3]BubbleSort And SelectionSort

/*
 * ---- Original comment by applicott --------------------
 *  クリックするたびに動きます。
 *  上手く可視化出来なかった。。。
 *  シャッフル > BubbleSort > Shuffle > SelectionSort >>>....
 * 
 * ---- Additional comment by matacat --------------------
 *  Click the stage to toggle motions.
 *  shuffle -> selection sort ->
 *    shuffule -> bubble sort ->
 *      shuffle -> selection sort -> ...
 * 
 *  大体こんな感じでしょうか?ソートの解釈間違えてるかもです...
 *  今回初めて BetweenAS3 を使わせていただきましたが、
 *  たのしいですねこれ!調整しては眺めるのを繰り返していたら
 *  いつの間にか一日が終わってました。
 */

package
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    
    [SWF(backgroundColor = 0x000000, frameRate = 60)]
    
    public class Main extends Sprite
    {
        // 配列に関する定数・変数
        private const NUM:uint = 30;    // 配列の要素数
        private var list:Vector.<Bar>;  // 棒の配列
        private var curId:int;          // ソートに用いる。現在注目している要素など
        private var selId:int;          // ソートに用いる。比較対象の要素など
        
        // モーションに関する変数
        private var standby:Boolean;  // モーションが完了したかどうかのフラグ
        private var curMotion:int;    // 現在のモーション
        
        // 背景
        private var shuffleName:MotionName;
        private var ssortName:MotionName;
        private var bsortName:MotionName;
        
        
        public function Main()
        {
            var wz:int = stage.stageWidth;
            var hi:int = stage.stageHeight;
            
            graphics.beginFill(0);
            graphics.drawRect(0, 0, wz, hi);
            
            MotionName.centerY = hi / 2;
            shuffleName = addChild(new MotionName("Shuffle"))        as MotionName;
            ssortName   = addChild(new MotionName("Selection Sort")) as MotionName;
            bsortName   = addChild(new MotionName("Bubble Sort"))    as MotionName;
            
            // Bar クラスの初期設定
            Bar.centerY   = hi / 2;               // ステージ中央の Y 座標で棒の高さをそろえる
            Bar.interval  = wz / NUM;             // 棒の間隔はステージの幅を棒の総数で割った数
            Bar.lengthMin = 25;                   // 棒の長さの最小値
            Bar.lengthInc = (hi / 2 - 25) / NUM;  // 棒の長さの増分
            
            // リスト初期設定
            list = new Vector.<Bar>(NUM, true);
            for (var i:int = 0; i < NUM; i++) {
                list[i] = new Bar(i, hue2rgb(i / NUM * 360));
                addChild(list[i]);
            }
            
            getReady();
            curMotion = 0;
            
            stage.addEventListener(MouseEvent.CLICK, click);
        }
        
        
        private function click(e:MouseEvent):void
        {
            if (standby) {
                // モーション実行中に別のモーションを実行しないように
                standby = false;
                
                // モーション切り替え。名前を表示し、ソート(シャッフル)を実行する
                switch (curMotion) {
                    case 0: shuffleName.appear(); shuffle(); break;
                    case 1: ssortName.appear();   ssort();   break;
                    case 2: shuffleName.appear(); shuffle(); break;
                    case 3: bsortName.appear();   bsort();   break;
                }
                if (++curMotion > 3) curMotion = 0;
            }
        }
        
        
        private function getReady():void
        {
            // ソート(シャッフル)を実行する前の準備
            curId   = 0;
            selId   = 0;
            standby = true;
        }
        
        
        private function shuffle():void
        {
            // リストのシャッフル
            //   curId: 現在注目している要素。リストを前方から後方へ走査する
            //   selId: curId と交換する要素。 curId より前方の要素からランダムに選ぶ
            
            while (++curId < NUM) {
                selId = Math.random() * curId >> 0;
                if (curId == selId) continue;
                
                var b:Bar   = list[curId];
                list[curId] = list[selId];
                list[selId] = b;
            }
            
            // シャッフルモーションを徐々に開始させる
            curId = -1;
            selId = -1;
            addEventListener(Event.ENTER_FRAME, sMotion);
            
            // 一斉に動かすならこの一行だけ
            //for (curId = 0; curId < NUM; curId++) list[curId].goto(curId);
        }
        
        
        private function sMotion(e:Event):void
        {
            if (++selId % 5 != 0) return;
            
            // 位置はそのままで配列だけをシャッフルしたので、
            // インデックスに対応した位置に移動させれば良い
            if (++curId < NUM - 1) {
                list[curId].goto(curId);
            } else if (curId == NUM - 1) {
                list[curId].goto(curId, getReady);
            } else {
                removeEventListener(Event.ENTER_FRAME, sMotion);
                shuffleName.disappear();
            }
        }
        
        
        private function ssort():void
        {
            // リストの選択ソート(一回ずつモーションさせる)
            //   curId: 現在の注目インデックス。リストを前方から後方へ走査する
            //   selId: curId に収まるべき要素の候補。 i の長さの方が短い場合 i に置き換わる
            //   i:     curId より後方を走査し、一番短い棒を探す
            
            if (curId >= NUM - 1) {  // 終了条件
                getReady();
                ssortName.disappear();
                return;
            }
            
            selId = curId;
            for (var i:int = curId + 1; i < NUM; i++) {
                if (list[selId].length > list[i].length) selId = i;
            }
            
            var b:Bar   = list[curId];
            list[curId] = list[selId];
            list[selId] = b;
            
            // ソートモーション。完了する度このメソッド自身を呼び出させる
            list[curId].goto(curId);
            list[selId].goto(selId, ssort);
            
            curId++;
        }
        
        
        private function bsort():void
        {
            // リストのバブルソート(一回ずつモーションさせる)
            //   curId: selId の上限インデックス。リストを前方から後方へ走査する
            //   selId: リストの後ろから curId まで走査する。ひとつ前の棒と長さを比較し、短い場合入れ替える
            
            if (selId <= curId) {
                if (++curId > NUM - 1) {  // 終了条件
                    getReady();
                    bsortName.disappear();
                    return;
                }
                selId = NUM;
            }
            selId--;
            
            if (list[selId - 1].length > list[selId].length) {
                var b:Bar       = list[selId];
                list[selId]     = list[selId - 1];
                list[selId - 1] = b;
                
                // ソートモーション。完了する度このメソッド自身を呼び出させる
                list[selId].goto(selId);
                list[selId - 1].goto(selId - 1, bsort);
                
            } else {
                bsort();
            }
        }
        
        
        private function hue2rgb(hue:Number):uint
        {
            // 色相(単位: 度)から RGB を返すユーティリティ。輝度・彩度は常に最大
            
            hue = hue >= 360 ? hue % 360 : (hue < 0 ? hue % 360 + 360 : hue);
            
            var i:int    = hue / 60 >> 0;
            var j:Number = hue / 60 - i;
            var k:Number = 1 - j;
            
            var rgb:uint = 0;
            
            switch (i) {
                case 0: rgb = 0xFF0000       | 0xFF * j << 8 | 0;             break;
                case 1: rgb = 0xFF * k << 16 | 0x00FF00      | 0;             break;
                case 2: rgb = 0              | 0x00FF00      | 0xFF * j << 0; break;
                case 3: rgb = 0              | 0xFF * k << 8 | 0x0000FF;      break;
                case 4: rgb = 0xFF * j << 16 |             0 | 0x0000FF;      break;
                case 5: rgb = 0xFF0000       |             0 | 0xFF * k << 0; break;
            }
            
            return rgb;
        }
    }
}


import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Shape;
import flash.events.Event;
import flash.filters.BlurFilter;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFormat;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.Bounce;
import org.libspark.betweenas3.easing.Elastic;
import org.libspark.betweenas3.easing.Quad;
import org.libspark.betweenas3.easing.Sine;
import org.libspark.betweenas3.tweens.ITween;

class Bar extends Bitmap
{
    private static const THICKNESS:int = 2;
    private static const EDGE:int      = 2;
    
    public static var centerY:Number;
    public static var interval:Number;
    public static var lengthMin:Number;
    public static var lengthInc:Number;
    public var length:Number;
    
    private var upT:ITween;
    private var downT:ITween;
    
    
    public function Bar(index:int, color:uint)
    {
        length = lengthMin + lengthInc * index;
        
        var totalThick:int = THICKNESS + EDGE * 2;
        var ofsX:Number    = interval / 2;
        var line:Shape     = new Shape();
        var g:Graphics     = line.graphics;
        
        g.lineStyle(totalThick, 0, 0.5, true);
        g.moveTo(ofsX, totalThick / 2);
        g.lineTo(ofsX, length);
        
        g.lineStyle(THICKNESS, color, 1, true);
        g.moveTo(ofsX, totalThick / 2);
        g.lineTo(ofsX, length);
        
        bitmapData = new BitmapData(interval, length + totalThick, true, 0);
        bitmapData.draw(line);
        
        x = index * interval;
        y = centerY - totalThick / 2;
        
        upT   = BetweenAS3.tween(this, { y: centerY - totalThick / 2 - length }, null, 0.4, Elastic.easeOut);
        downT = BetweenAS3.tween(this, { y: centerY - totalThick / 2 },          null, 0.8, Bounce.easeOut);
    }
    
    
    public function goto(index:Number, onComplete:Function = null):void
    {
        var slideT:ITween = BetweenAS3.tween(this, { x: index * interval }, null, 0.4, Quad.easeInOut);
        if (onComplete != null) slideT.onComplete = onComplete;
        
        BetweenAS3.serial(
            BetweenAS3.parallel(
                upT,
                BetweenAS3.delay(slideT, 0.2)
            ),
            downT
        ).play();
    }
}


class MotionName extends Bitmap
{
    public static var centerY:Number;
    
    private var fadeIn:ITween;
    private var fadeOut:ITween;
    private var blink:ITween;
    
    
    public function MotionName(name:String)
    {
        var mx:Matrix = new Matrix();
        
        var tf:TextField     = new TextField();
        tf.defaultTextFormat = new TextFormat("_serif", 72, 0xFFFFFF);
        tf.autoSize          = "left";
        tf.text              = name;
        
        var wz:int = tf.width;
        var hi:int = tf.height * 0.9;
        
        mx.createGradientBox(wz, hi, Math.PI / 2);
        
        var gd:Shape = new Shape();
        gd.graphics.beginGradientFill("linear", [0, 0], [0, 0.8], [63, 255], mx);
        gd.graphics.drawRect(0, 0, wz, hi);
        
        var temp:BitmapData = new BitmapData(wz, hi, true, 0);
        temp.draw(tf);
        temp.draw(gd);
        temp.applyFilter(temp, temp.rect, new Point(), new BlurFilter(4, 4, 3));
        
        super(new BitmapData(wz, hi * 1.75, false, 0));
        bitmapData.draw(temp);
        mx.createBox(1, -0.75, 0, 0, hi * 1.75);
        bitmapData.draw(temp, mx, new ColorTransform(0.3, 0.3, 0.3));
        
        y     = centerY - hi;
        alpha = 0;
        
        temp.dispose();
        
        fadeIn  = BetweenAS3.tween(this, { alpha: 1.0 }, null, 1, Sine.easeInOut);
        fadeOut = BetweenAS3.tween(this, { alpha: 0.0 }, null, 1, Sine.easeInOut);
        blink   = BetweenAS3.serial(
            BetweenAS3.tween(this, { alpha: 0.6 }, null, 1, Sine.easeInOut),
            BetweenAS3.tween(this, { alpha: 1.0 }, null, 1, Sine.easeInOut)
        );
        
        fadeIn.onComplete = blink.play;
    }
    
    
    public function appear():void
    {
        blink.stopOnComplete = false;
        blink.onComplete     = null;
        fadeIn.play();
    }
    
    
    public function disappear():void
    {
        blink.stopOnComplete = true;
        blink.onComplete     = fadeOut.play;
    }
}