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

pre-rendering ver. forked from: forked from: Shining Text

前回のがあまりに重かったのでプリレンダ版です。
画面サイズ約1/4。アウトライン抽出の前に2値化処理を追加したので光線も細身。
ソースコードかなりいじったのでもうほぼ別物です…
/**
 * Copyright matacat ( http://wonderfl.net/user/matacat )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/yGc2
 */

// forked from matacat's forked from: Shining Text
// forked from Kay's Shining Text

// 前回のがあまりに重かったのでプリレンダ版です。
// 画面サイズ約1/4。アウトライン抽出の前に2値化処理を追加したので光線も細身。
// ソースコードかなりいじったのでもうほぼ別物です…

package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Graphics;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.filters.BlurFilter;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.text.TextField;
    import flash.text.TextFormat;
    
    [SWF(width="230", height="230", frameRate="30", backgroundColor="0xCFCFCF")]
    
    public class Main extends Sprite
    {
        // 調整用
        private var text:String = "wonderfl";
        private var textSize:Number = 32;
        private var textColor:uint = 0xFFFF9F;
        private var backColor:uint = 0x000000;
        
        // 光線の広がる倍率(X方向を増やすと総フレーム数が増える)
        private var multiX:Number = 12;
        private var multiY:Number = 10;
        // 1フレームあたりの光線の移動量(減らすと総フレーム数が増える)
        private var delta:Number = 20;
        private var lightColor:uint = 0xFFFFBF;
        // 光線の太さ
        private var thickness:Number = 3;
        private var filter:BlurFilter = new BlurFilter(12, 10, 2);
        
        private var textOnly:Boolean = false;
        
        
        // 内部処理用
        private var screen:Bitmap = new Bitmap();
        private var frames:Vector.<BitmapData> = new Vector.<BitmapData>();
        private var totalFrames:int = 0;
        private var currentFrame:int = 0;
        private var message:TextField = new TextField();
        
        private const SW:Number = stage.stageWidth;
        private const SH:Number = stage.stageHeight;
        private const CX:Number = SW >> 1;
        private const CY:Number = SH >> 1;
        
        
        public function Main()
        {
            Wonderfl.capture_delay(30);
            
            var fm:TextFormat = new TextFormat(null, null, 0);
            message.autoSize = fm.align = "center";
            message.defaultTextFormat = fm;
            message.selectable = false;
            message.text = "Click to start";
            message.x = SW - message.width >> 1;
            message.y = SH - message.height >> 1;
            addChild(message);
            
            stage.addEventListener(MouseEvent.CLICK, init);
        }
        
        
        private function init(e:MouseEvent):void
        {
            stage.removeEventListener(MouseEvent.CLICK, init);
            
            message.text = "Rendering now.\nPlease wait a minute...";
            message.y = SH - message.height >> 1;
            e.updateAfterEvent();
            
            stage.addEventListener(Event.ENTER_FRAME, render);
        }
        
        
        private function render(e:Event):void
        {
            stage.removeEventListener(Event.ENTER_FRAME, render);
            
            // initialize text
            var tf:TextField = new TextField();
            tf.defaultTextFormat = new TextFormat("Arial", textSize, textColor);
            tf.autoSize = "left";
            tf.selectable = false;
            tf.text = this.text;
            
            var tw:Number = tf.width;
            var th:Number = tf.height;
            tf.x = SW - tw >> 1;
            tf.y = SH - th >> 1;
            
            
            // binarize text picture
            var bmp:BitmapData = new BitmapData(tw, th, false, 0);
            bmp.draw(tf);
            
            var binPic:Vector.<Vector.<Boolean>> = new Vector.<Vector.<Boolean>>();
            
            var textLum:uint = ((textColor >> 16 & 0xFF) + (textColor >> 8 & 0xFF) + (textColor & 0xFF)) / 3;
            var backLum:uint = ((backColor >> 16 & 0xFF) + (backColor >> 8 & 0xFF) + (backColor & 0xFF)) / 3;
            var avg:uint = textLum + backLum >> 1;
            var dir:Boolean  = textLum > avg ? true : false;
            
            for (var i:int = 0; i < tw ; i++) {
                binPic[i] = new Vector.<Boolean>();
                for (var j:int = 0; j < th; j++) {
                    var c:uint = bmp.getPixel(i, j);
                    c = ((c >> 16 & 0xFF) + (c >> 8 & 0xFF) + (c & 0xFF)) / 3;
                    binPic[i][j] = (dir && (c > avg)) || (!dir && (c < avg));
                }
            }
            
            
            // get outline
            var backOL:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
            var frontOL:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
            var nx:Number;
            var ny:Number;
            var len:int = 0;
            for (i = 0; i < tw; i++) {
                for (j = 0; j < th; j++) {
                    // 注目画素が背景色ならスルー
                    if (!binPic[i][j]) continue;
                    
                    // 注目画素が端っこでないときで
                    if (!(i == 0 || i == th - 1 || j == 0 || j == tw - 1)) {
                        // 4-近傍(上下左右のピクセル)が文字色で埋まっているときスルー
                        if (binPic[i + 1][j] && binPic[i - 1][j] && binPic[i][j + 1] && binPic[i][j - 1]) continue;
                    }
                    
                    // 以上の条件でスルーされなかったものをアウトラインとして抽出
                    backOL[len] = Vector.<Number>([nx = i - (tw >> 1), ny = j - (th >> 1)]);
                    frontOL[len] = Vector.<Number>([nx * multiX, ny * multiY]);
                    backOL[len][0] += CX;
                    backOL[len][1] += CY;
                    frontOL[len][0] += CX;
                    frontOL[len][1] += CY;
                    len++;
                }
            }
            
            
            // rendering
            var canvas:Sprite = new Sprite();
            var g:Graphics = canvas.graphics;
            canvas.addChild(tf);
            
            var max:Number = SW + tw * multiX;
            var min:Number = -max;
            
            var temp:BitmapData = new BitmapData(SW, SH , false, backColor);
            var rect:Rectangle = new Rectangle(0, 0, SW, SH);
            var point:Point = new Point(0, 0);
            
            for (var dx:Number = max; dx >= min; dx -= delta) {
                var aAvg:Number = 0;
                
                for (i = 0; i < len; i++) {
                    var xx:Number = backOL[i][0] - (frontOL[i][0] + dx);
                    if (xx < 0) xx = -xx;
                    if (xx <= delta) xx = delta;
                    xx = delta / xx;
                    aAvg += xx;
                    
                    if (!textOnly) {
                        g.lineStyle(thickness, lightColor, xx);
                        g.moveTo(backOL[i][0], backOL[i][1]);
                        g.lineTo(frontOL[i][0] + dx , frontOL[i][1]);
                    }
                }
                
                tf.alpha = aAvg / len * 2;
                temp.draw(canvas);
                
                frames[totalFrames] = new BitmapData(SW, SH, false, backColor);
                frames[totalFrames].applyFilter(temp, rect, point, filter);
                temp.fillRect(rect, backColor);
                
                g.clear();
                frames[totalFrames].draw(canvas, null, null, "add");
                
                totalFrames++;
            }
            
            
            // start
            removeChild(message);
            addChild(screen);
            stage.addEventListener(Event.ENTER_FRAME, xAnimation);
        }
        
        
        private function xAnimation(e:Event):void
        {
            screen.bitmapData = frames[currentFrame];
            currentFrame = currentFrame < totalFrames - 1 ? currentFrame + 1 : 0;
        }
    }
}