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: Mandelbrot Set / forked from: Progressive Test

Legacy Mandelbrot Set
* コンテクストメニューからズームイン/アウト選択
Get Adobe Flash player
by raduweiss 04 Apr 2009

    Talk

    WLAD at 24 May 2016 00:10
    Center: 0.2722086683737748+0.59073667057176i / Scale: 5.684341886080802e-14

    Tags

    Embed
// forked from broken's Mandelbrot Set / forked from: Progressive Test
/**
 * Legacy Mandelbrot Set
 * コンテクストメニューからズームイン/アウト選択
 */
package {

    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Graphics;
    import flash.display.Sprite;
    import flash.events.ContextMenuEvent;
    import flash.events.Event;
    import flash.geom.Rectangle;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFieldType;
    import flash.ui.ContextMenu;
    import flash.ui.ContextMenuItem;
    import flash.utils.getTimer;
    
    [SWF(width="465", height="465", backgroundColor="0x000000", frameRate="30")]
    public class MandelbrotSet extends Sprite {

        private static const CALC_LIMIT : int = 1000;

        private var _bitmap : BitmapData;

        private var _infoText : TextField;

        private var _infoTextBg : Sprite;

        private var _renderer : ProgressiveRenderer;

        private var _mouseX : Number = 0;
        private var _mouseY : Number = 0;

/*
        private var _reC : Number = 0;
        private var _imC : Number = 0;
        private var _scale : Number = 4;
*/
        private var _reC : Number = 0.271171875;
        private var _imC : Number = 0.59072265625;
        private var _scale : Number = 0.00390625;

        public function MandelbrotSet() {

            setupContextMenu();

            _bitmap = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x000000);
            addChild(new Bitmap(_bitmap) );

            _infoTextBg = new Sprite();
            addChild(_infoTextBg);
            
            _infoText = new TextField();
            _infoText.textColor = 0xffffff;
            _infoText.type = TextFieldType.DYNAMIC;
            _infoText.autoSize = TextFieldAutoSize.LEFT;
            addChild(_infoText);

            addEventListener(Event.ENTER_FRAME, enterFrameHandler);

            start();
        }

        private function setupContextMenu() : void {

            var contextMenu : ContextMenu = new ContextMenu();
            contextMenu.hideBuiltInItems();
            contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, function (e : ContextMenuEvent) : void {
                _mouseX = mouseX;
                _mouseY = mouseY;
            } );

            var zoomInItem : ContextMenuItem = new ContextMenuItem("ZoomIn");
            zoomInItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, function (e : ContextMenuEvent) : void {
                zoom(false);
            } );
            contextMenu.customItems.push(zoomInItem);

            var zoomOutItem : ContextMenuItem = new ContextMenuItem("ZoomOut");
            zoomOutItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, function (e : ContextMenuEvent) : void {
                zoom(true);
            } );
            contextMenu.customItems.push(zoomOutItem);

            var resetItem : ContextMenuItem = new ContextMenuItem("Reset");
            resetItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, function (e : ContextMenuEvent) : void {
                reset();
            } );
            contextMenu.customItems.push(resetItem);

            this.contextMenu = contextMenu;        
        }

        private function reset() : void {

            _reC = 0;
            _imC = 0;
            _scale = 4;

            start();
        }        

        private function zoom(zoomOut : Boolean) : void {

            _reC = getRe(_mouseX);
            _imC = getIm(_mouseY);

            if (zoomOut) {
                _scale *= 2;
            } else {
                _scale /= 2;
            }

            start();
        }

        private function enterFrameHandler(event : Event) : void {

            if (_renderer == null) {
                return;
            }

            // 最大実行時間を決定
            var maxTime : int = 1000 / stage.frameRate;

            _bitmap.lock();

            var beginTime : Number = getTimer();

            // できる限りたくさん実行
            while (getTimer() - beginTime < maxTime) {

                if (!_renderer.next() ) {
                    // 処理完了
                    _renderer = null;
                    break;            
                }
            }

            _bitmap.unlock();
        }

        private function start() : void {

            showInfo();

            _renderer = new ProgressiveRenderer(_bitmap.width, _bitmap.height);
            _renderer.render = render;
        }

        /**
         * 情報表示
         */
        private function showInfo() : void {

            _infoText.text = "Center: " + _reC + (_imC < 0 ? "" : "+") + _imC + "i / Scale: " + _scale;
            
            // 背景
            var g : Graphics = _infoTextBg.graphics;
            g.clear();
            g.beginFill(0x000000, 0.5);
            g.drawRect(_infoText.x, _infoText.y, _infoText.width, _infoText.height);
            g.endFill();
        }

        private function getRe(x : int) : Number {
            return (x - _bitmap.width / 2) / _bitmap.height * _scale + _reC;
        }

        private function getIm(y : int) : Number {
            return (_bitmap.height / 2 - y) / _bitmap.height * _scale + _imC;
        }
        
        private function render(x : Number, y : Number, width : Number, height : Number) : void {

            var re0 : Number = getRe(x);
            var im0 : Number = getIm(y);

            var re : Number = re0;
            var im : Number = im0;
            var limit : int;
            var tmpRe : Number;

            for (limit = CALC_LIMIT; limit > 0 && (re * re + im * im < 4); limit--) {
                tmpRe = re;
                re = re * re - im * im + re0;
                im = 2 * tmpRe * im + im0;
            }

            var weight : Number = (limit % 2 == 1)? 0.8 : 1.0;
             var r : uint = tri(limit * 2.0) * 255 * weight;
             var g : uint = tri(limit * 2.1) * 255 * weight;
             var b : uint = tri(limit * 2.2) * 255 * weight;
            

            var color : uint = (limit == 0)? 0x000000 : 
                  ( (r << 16) | (g << 8) | b);
            
            _bitmap.fillRect(new Rectangle(x, y, width, height), color);
        }
    }
}

/**
 * @return 0~1 triangle wave
 */
function tri(t : Number) : Number {
    t = ( (t < 0)? -t : t) % 256;
    return (t < 128)? t / 128 : 2 - t / 128;
}

class ProgressiveRenderer {

    private static var DEFAULT_RENDER : Function = function(
            x : Number, y : Number, width : Number, height: Number) : void {
        trace(x, y, width, height);
    }

    private var _width : Number;
    private var _height : Number;

    private var _depth : uint;

    private var _funcs : Array;
    private var _labelIndex : Object;
    private var _index : int;
    private var _defualtCellSize : int;
    
    // function(x : Number, y : Number, width : Number, height: Number) : void 
    public var render : Function = DEFAULT_RENDER;
        
    public function ProgressiveRenderer(width : Number, height : Number, depth : uint = 2) {

        _width = width;
        _height = height;
                
        _depth = depth;
        
        init();
    }
    
    public function get width() : Number {
        return _width;
    }
    
    public function get height() : Number {
        return _height;
    }

    public function next() : Boolean {
        
        if (_index >= _funcs.length) {
            return false;
        }
        
        var func : Function = _funcs[_index] as Function;
                
        if (func != null) {
            
            var label : String = func() as String;

            if (label != null) {

                // jump to label.
                _index = _labelIndex[label];
                return true;
              }
        }

        _index++;

        return _index < _funcs.length;
    }

    private function init() : void {

        var x : int;
        var y : int;

        var size1 : int = 2 << _depth;
        var size2 : int = size1 << 1;

        _funcs = [

            function() : * { y = 0; },
            "y_loop1",
                function() : * { x = 0; },
                "x_loop1",
                    function() : * { render(x, y, size2, size2); },
                function() : * { x += size2; return x < _width? "x_loop1" : null; },
            function() : * { y += size2; return y < _height? "y_loop1" : null; },

            "size_loop",

                function() : * { y = 0; },
                "y_loop2",
                    function() : * { x = size1; },
                    "x_loop2",
                        function() : * { render(x, y, size1, size2); },
                    function() : * { x += size2; return x < _width? "x_loop2" : null; },
                function() : * { y += size2; return y < _height? "y_loop2" : null; },

                function() : * { y = size1; },
                "y_loop3",
                    function() : * { x = 0; },
                    "x_loop3",
                        function() : * { render(x, y, size1, size1); },
                    function() : * { x += size1; return x < _width? "x_loop3" : null; },
                function() : * { y += size2; return y < _height? "y_loop3" : null; },

            function() : * { size1 >>= 1; size2 >>= 1; return size1 >= 1? "size_loop" : null; }
        ];

        _index = 0;

        _labelIndex = new Object();
        for (var i : int = 0; i < _funcs.length; i++) {
            if (_funcs[i] is String) {
                _labelIndex[_funcs[i]] = i;
            }
        }
    }
}