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

文字をパスにして落とす

詳しくはFork元を見てください。
Get Adobe Flash player
by paq 16 Jan 2011
  • Forked from shohei909's 文字のShape化
  • Diff: 371
  • Related works: 1
  • Talk

    paq at 16 Jan 2011 16:04
    よく考えればShapeにしてないw Fork元はテキストフィールド→BitmapData(2値化)→頂点取得→Shapeに描画 このコードはテキストフィールド→BitmapData(2値化)→頂点取得→Box2D あと、なぜか「左」は使えるよ! http://gyazo.com/5bfd3068bc370bd9949ceedd1d92a179.png
    makc3d at 16 Jan 2011 22:17
    characters with holes fail
    paq at 17 Jan 2011 10:02
    Thanks, I think about the solution.

    Tags

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

// forked from shohei909's 文字のShape化
package
{
    import com.actionsnippet.qbox.QuickBox2D;
    import com.actionsnippet.qbox.QuickObject;
    import flash.display.Graphics;
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.FocusEvent;
    import flash.events.KeyboardEvent;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFieldType;
    import flash.text.TextFormat;
    import flash.ui.Keyboard;
    
    /**
     * 一部の文字が使えないのはなんでなんだろ。
     * @author paq89
     */
    [SWF(width="465",height="465",backgroundColor="0xFFFFFF",frameRate="60")]
    
    public class TypeBox2D extends MovieClip
    {
        private var _inputText:InputTextField;
        private var _box2d:QuickBox2D;
        private var _tts:TextToShape;
        private var _polies:Vector.<QuickObject>;
        
        public function TypeBox2D()
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(event:Event = null):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            _tts = new TextToShape();
            _polies = new Vector.<QuickObject>();
            
            _box2d = new QuickBox2D(this);
            _box2d.setDefault({lineColor:0xFFFFFF, fillColor:0x0D0D0D});
            _box2d.mouseDrag();
            _box2d.start();
            
            var sw:Number = _box2d.main.stage.stageWidth / 30;
            var sh:Number = _box2d.main.stage.stageHeight / 30;
            _box2d.addBox( { x:sw / 2, y: -0.5, width:sw, height:1, lineAlpha: 0, fillAlpha: 0, density:0.0 } );
            _box2d.addBox( { x:sw / 2, y:sh + 0.5, width:sw, height:1, lineAlpha: 0, fillAlpha: 0, density:0.0 } );
            _box2d.addBox( { x: -0.5, y:sh / 2, width:1, height:sh, lineAlpha: 0, fillAlpha: 0, density:0.0 } );
            _box2d.addBox( { x:sw + 0.5, y:sh / 2, width:1, height:sh, lineAlpha: 0, fillAlpha: 0, density:0.0 } );
            
            _inputText = new InputTextField(send, "Input here");
            _inputText.width = stage.stageWidth-1;
            addChild(_inputText);
        }
        
        private function send():void
        {
            var count:int = 0;
            for each (var s:String in _inputText.text.split(""))
            {
                var path:Vector.<Vector.<Anchor>> = _tts.convert(s);
                var points:Array = [];
                var r:Number = Math.random()*7;
                for each (var v:Vector.<Anchor> in path)
                {
                    for each (var a:Anchor in v)
                    {
                        points.push(a.x / (20.0-r), a.y / (20.0-r));
                    }
                }
                
                if (points.length > 1)
                {
                    var avgX:Number = 0;
                    var avgY:Number = 0;
                    
                    var len:uint = points.length;
                    for (var i:uint = 0; i < len; i += 2)
                    {
                        avgX += points[i];
                        avgY += points[i + 1];
                    }
                    
                    avgX /= points.length / 2;
                    avgY /= points.length / 2;
                    
                    for (i = 0; i < len; i += 2)
                    {
                        var yp:int = i + 1;
                        points[i] -= avgX;
                        points[yp] -= avgY;
                        points[i] = Number(points[i].toFixed(2));
                        points[yp] = Number(points[yp].toFixed(2));
                    }
                    
                    try
                    { 
                        _polies.push(_box2d.addPoly( { x:1 + count * 2,
                                                       y:2,
                                                       points:points } ));
                    }
                    catch (e:*)
                    {
                        trace(e)
                    }
                    
                    if (_polies.length > 15)
                    {
                        var p:QuickObject = _polies.shift();
                        p.fullDestroy();
                    }
                    count++;
                }
            }
        }
    }

}

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Shape;
import flash.events.FocusEvent;
import flash.events.KeyboardEvent;
import flash.geom.Matrix;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.ui.Keyboard;
import flash.utils.getTimer;

internal class TextToShape
{
    private const W:int = 100;
    private const H:int = 80;
    
    private var _map:Vector.<Vector.<Anchor>>;
    private var _vec:Vector.<Anchor>;
    private var _paths:Vector.<Vector.<Anchor>>;
    
    private var _bitmapData:BitmapData = new BitmapData(W, H);
    private var _textField:TextField;
    private var _matrix:Matrix;
    
    public function TextToShape()
    {
        _textField = new TextField()
        _textField.defaultTextFormat = new TextFormat("", 50);
        _textField.width = W;
        _textField.height = H;
    }
    
    public function convert(text:String):Vector.<Vector.<Anchor>>
    {
        _map = new Vector.<Vector.<Anchor>>();
        _vec = new Vector.<Anchor>();
        _paths = new Vector.<Vector.<Anchor>>();
        
        for (var i:int = 0; i < W + 1; i++)
        {
            _map[i] = new Vector.<Anchor>();
            for (var j:int = 0; j < H + 1; j++)
            {
                _map[i][j] = null;
            }
        }
        
        _bitmapData.fillRect(_bitmapData.rect, 0xFFFFFFFF);
        _textField.text = text;
        _bitmapData.draw(_textField);
        progress();
        
        return _paths;
    }
    
    private function progress():void
    {
        var time:int = getTimer();
        var c:int = 0;
        monoColor();
        setVec();
        setLink();
        setPaths();
        cutAnchors();
    }
    
    private function monoColor():void
    {
        var b:BitmapData = this._bitmapData;
        b.lock();
        for (var x:int = 0; x < W; x++)
        {
            for (var y:int = 0; y < H; y++)
            {
                if (b.getPixel(x, y) != 0xFFFFFF)
                {
                    b.setPixel(x, y, 0)
                }
            }
        }
        b.unlock();
    }
    
    private function setVec():void
    {
        var b:BitmapData = this._bitmapData;
        for (var x2:int = 0; x2 < W; x2++)
        {
            for (var y2:int = 0; y2 < H; y2++)
            {
                var d:Array = [];
                var dl:int = 0;
                for (var dx:int = -1; dx < 1; dx++)
                {
                    for (var dy:int = -1; dy < 1; dy++)
                    {
                        var x:int = x2 + dx;
                        var y:int = y2 + dy;
                        if (x < 0 || W + 1 < x || y < 0 || H + 1 < y || b.getPixel(x, y) != 0)
                        {
                            d.push("0")
                        }
                        else
                        {
                            d.push("1");
                            dl++
                        }
                    }
                }
                if (dl == 1 || dl == 3)
                {
                    var dir:Array;
                    if (dl == 1)
                    {
                        dir = [[0, -1], [-1, 0], [1, 0], [0, 1]][d.indexOf("1")]
                    }
                    else
                    {
                        dir = [[-1, 0], [0, 1], [0, -1], [1, 0]][d.indexOf("0")]
                    }
                    var anc:Anchor = new Anchor(x2, y2, dir);
                    _vec.push(anc);
                    _map[x2][y2] = anc;
                }
            }
        }
    }
    
    private function setLink():void
    {
        for each (var a:Anchor in _vec)
        {
            var dx:int = a.dir[0];
            var dy:int = a.dir[1];
            var x:int = a.x;
            var y:int = a.y;
            while (true)
            {
                x += dx;
                y += dy;
                if (x < 0 || W < x || y < 0 || H < y)
                {
                    break
                }
                if (_map[x][y] != null)
                {
                    a.next = _map[x][y];
                    break;
                }
            }
        }
    }
    
    private function setPaths():void
    {
        while (_vec.length > 0)
        {
            var first:Anchor = _vec[0];
            var a:Anchor = first;
            var v:Vector.<Anchor> = new Vector.<Anchor>;
            var c:int = 0;
            do
            {
                v.push(a)
                _vec.splice(_vec.indexOf(a), 1);
                a = a.next;
                c++;
            } while (first != a && c < 100)
            _paths.push(v);
        }
    }
    
    private function cutAnchors(size:Number = 10):void
    {
        for each (var v:Vector.<Anchor>in _paths)
        {
            while (v.length > 2)
            {
                var l:int = v.length
                var a1:Anchor = v[l - 2];
                var a2:Anchor = v[l - 1];
                var a3:Anchor = v[0];
                var min:Number = getTriangleSize(a1, a2, a3);
                var mp:int = l - 1;
                for (var i:int = 1; i < l; i++)
                {
                    a1 = a2;
                    a2 = a3;
                    a3 = v[i];
                    var s:Number = getTriangleSize(a1, a2, a3);
                    if (s < min)
                    {
                        min = s;
                        mp = i - 1;
                    }
                }
                if (min <= size)
                {
                    v.splice(mp, 1);
                }
                else
                {
                    break;
                }
            }
        }
    }
    
    private function getTriangleSize(a1:Anchor, a2:Anchor, a3:Anchor):Number
    {
        var s:Number = (a2.x - a1.x) * (a3.y - a1.y) - (a2.y - a1.y) * (a3.x - a1.x);
        return (s > 0 ? s : -s) / 2;
    }

}

internal class Anchor
{
    public var x:Number;
    public var y:Number;
    public var dir:Array;
    public var next:Anchor;
    
    public var bf_size:Number;
    public var size:Number;
    public var af_size:Number;
    
    function Anchor(x:Number, y:Number, dir:Array)
    {
        this.x = x;
        this.y = y;
        this.dir = dir
    }
}

internal class InputTextField extends TextField
{
    public var handler:Function;
    
    private var _currentKey:uint;
    private var _isFocus:Boolean;
    private var _isMessageShowing:Boolean;
    
    public function InputTextField(handler:Function, message:String = "")
    {
        super();
        
        this.handler = handler;
        
        _isFocus = false;
        
        defaultTextFormat = new TextFormat("", 30);
        height = 40;
        text = message;
        type = TextFieldType.INPUT;
        border = true;
        
        addEventListener(FocusEvent.FOCUS_IN, onFocusIn);
        addEventListener(FocusEvent.FOCUS_OUT, onFocusOut);
        addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
        addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
    }
    
    private function onFocusIn(event:FocusEvent):void 
    {
        if (!_isMessageShowing)
        {
            text = "";
            _isMessageShowing = false;
        }
        _isFocus = true;
    }

    private function onFocusOut(event:FocusEvent):void 
    {
        _isFocus = false;
    }

    private function onKeyDown(event:KeyboardEvent):void 
    {
        if (!_isFocus) return;
        _currentKey = event.charCode;
    }

    private function onKeyUp(event:KeyboardEvent):void 
    {
        if (!_isFocus) return;
        if (event.charCode == Keyboard.ENTER && event.charCode == _currentKey)
        {
            handler();
            text = "";
        }
    }
}