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: IKhandle and Doll

Drag a red circles
/**
 * Copyright h_sakurai ( http://wonderfl.net/user/h_sakurai )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/hBda
 */

/*
やりたいこと
1。状態の保存 なんか、ボタンを押すと保存出来る
2。時間指定して、保存出来る
3。再生 再生出来る

そのために、各状態を保存出来るとうれしいのでした。
で、タイムラインみたいなのでアニメーションして遊びたいと。

○プロパティを保存すればよいかを調べる。
○強制的にプロパティを指定できるようにする。

*/
package {
    import flash.display.*;
    import flash.events.Event;
    import flash.events.MouseEvent;
    
    [SWF(width = 465, height = 465, frameRate = 30)]
    public class Main extends Sprite  {
        // 人形
        private var doll : Doll;
        private var save1Btn:Button = new Button("save1",48);
        private var save2Btn:Button = new Button("save2",48);
        private var move1Btn:Button = new Button("move1",48);
        private var move2Btn:Button = new Button("move2",48);
    /**
     * あああ
     */
        public function Main():void {
        // ステージあれば初期化
            if (stage) init();
            // ないときはイベント登録して待ち
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        /**
         * 
         */
        private function init(e:Event = null):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            tf.y=30;
            tf.width=465;
            tf.height=465;
            addChild(tf);
            doll = new Doll();
            addChild(doll);
            save1Btn.addEventListener(MouseEvent.CLICK, save1);
            save2Btn.addEventListener(MouseEvent.CLICK, save2);
            move1Btn.addEventListener(MouseEvent.CLICK, move1);
            move2Btn.addEventListener(MouseEvent.CLICK, move2);
            addChild(save1Btn);
            addChild(save2Btn);
            save2Btn.x = 50;
            move1Btn.x = 100;
            move2Btn.x = 150;
            addChild(move1Btn);
            addChild(move2Btn);
        }
        public var xml1:XML;
        public var xml2:XML;        
        private function save1(e:Event):void {
            xml1=obj2xml("doll",doll.toObject());
            dbg(xml1.toXMLString());
 //   g        tf.text = xml1.toXMLString();
        }
        private function save2(e:Event):void {
            xml2=obj2xml("doll",doll.toObject());        
            
        }
        private function move1(e:Event):void {
            doll.setXML(xml1)            
        }
        private function move2(e:Event):void {
            doll.setXML(xml2)            
        }

    }
}
import flash.text.TextField;
var tf:TextField = new TextField();

function obj2xml(name:String, obj:Object):XML {

    var xml:XML = new XML("<"+name+"/>");
    if (obj is String || obj is Number || obj is int) {
        xml.appendChild(obj);
        return xml;
    }
    var i:String;

    if (obj is Array) {
//        var x2:XML = new XML("<Array/>");
        var x2:XML = xml;
        for (i in obj) {
            x2.appendChild(obj2xml("v", obj[i]));
        }
//        xml.appendChild(x2);
        return xml;
    }

    for (i in obj) {
        xml.appendChild(obj2xml(i, obj[i]));
    }
    return xml;
}

import flash.display.*;
import flash.events.*;
import flash.geom.Point;
function dbg(s:String):void {
    tf.text = s+"\n"+tf.text;
}

internal class NodeObject extends Sprite {
    public var ikParent:DollParts;

    public function toObject():Object {
        var obj:Object = {
            "x":x,
            "y":y,
            "ikX":_ikX,
            "ikY":_ikY
        };
        if (ikParent != null) {
            obj["_parent"] = ikParent.toObject();
        }
        return obj;
    }
    
    public function setXML(x:XML):void {
        dbg("nodeobj setxml start");
        this.x = parseFloat(x.x)
        y = parseFloat(x.y)
        _ikX = parseFloat(x.ikX)
        _ikY = parseFloat(x.ikY)
        dbg("a")
        if (ikParent != null && x._parent != null ) {
            ikParent.setXML(x._parent[0]);
        }
        dbg("koko2");
    }
    private var _ikX:Number;
    public function get ikX():Number {
        positioning();
        return _ikX;
    }

    private var _ikY:Number;
    public function get ikY():Number {
        positioning();
        return _ikY;
    }

    public function NodeObject(_x:int, _y:int):void {
        this.x = _x;
        this.y = _y;
    }

    private function positioning():void {
        var p:Point = parent.localToGlobal(new Point(x, y));
        _ikX = ikParent.globalToLocal(p).x;
        _ikY = ikParent.globalToLocal(p).y;
    }
}


internal class IkTarget extends NodeObject {

    public function IkTarget( _x:int, _y:int ):void {
        super( _x, _y );
        graphics.beginFill( 0xFF0000, 0.2 );
        graphics.drawCircle( 0, 0, 15 );
        graphics.endFill();
        addEventListener( MouseEvent.MOUSE_DOWN, mouseDownHandler );
    }

    private function mouseDownHandler(e:MouseEvent):void {
        removeEventListener( MouseEvent.MOUSE_DOWN, mouseDownHandler );
        startDrag();
        addEventListener( MouseEvent.MOUSE_UP, mouseUpHandler );
    }

    private function mouseUpHandler(e:MouseEvent):void {
        removeEventListener( MouseEvent.MOUSE_UP, mouseUpHandler );
        stopDrag();
        addEventListener( MouseEvent.MOUSE_DOWN, mouseDownHandler );
    }
}

internal class Doll extends NodeObject {
    private var _rootTarget : IkTarget;    // ○ルート移動用

    private var _headTarget : IkTarget;        // 頭のIK目標点
    private var _bodyTarget : IkTarget;        // 体のIK目標点
    private var _leftArmTarget : IkTarget;    // 左手のIK目標点
    private var _rightArmTarget : IkTarget;    // 右手のIK目標点
    private var _leftLegTarget : IkTarget;    // 左足のIK目標点
    private var _rightLegTarget : IkTarget;    // 右足のIK目標点

    private var _head : DollParts;        // 頭
    private var _body : DollParts;        // 体
    private var _leftArm : DollParts;    // 左手
    private var _rightArm : DollParts;    // 右手
    private var _leftLeg : DollParts;    // 左足
    private var _rightLeg : DollParts;    // 右足

    private function getTargets():Object {
        return {
            "root":_rootTarget,
            "head":_headTarget,
            "body":_bodyTarget,
            "leftArm":_leftArmTarget,
            "rightArm":_rightArmTarget,
            "leftLeg":_leftLegTarget,
            "rightLeg":_rightLegTarget
        };
    }
    public function getParts():Object {
        return {
            "head":_head,
            "body":_body,
            "leftArm":_leftArm,
            "rightArm":_rightArm,
            "leftLeg":_leftLeg,
            "rightLeg":_rightLeg
        };
    }

    override public function toObject():Object {
        var obj:Object = getParts();
        var rcs:Object = super.toObject();
        rcs["targets"] = {};
        rcs["parts"] = {};
        for(var i:String in obj) {
           rcs["parts"][i] = obj[i].toObject();
        }
        obj = getTargets();
        for (i in obj) {
           rcs["targets"]["_" + i] = obj[i].toObject();
        }
        rcs["x"] = x;
        rcs["y"] = y;
        return rcs;
    }
    override public function setXML(x:XML):void {
       super.setXML(x)
        var obj:Object =getParts()
        for(var i:String in obj) {
           obj[i].setXML(x.parts[i][0])
        }
        dbg("parts ok")
        obj = getTargets();
        for (i in obj) {
            dbg("i"+i)
            dbg(""+(x.targets["_"+i][0] is XML))
           obj[i].setXML(x.targets["_"+i][0])
        }
        dbg("ok")
        this.x = parseFloat(x.x)
        y = parseFloat(x.y)
    }

    public function Doll():void {
        super( 230, 300 );
        init();
    }

    public function init():void {
        var param/*SegmentParam*/:Array;

        // 体
        param = new Array();
        param.push( new SegmentParam( 20, 20 ) );
        param.push( new SegmentParam( 20, 20 ) );
        param.push( new SegmentParam( 20, 20 ) );
        param.push( new SegmentParam( 20, 20 ) );
        _body = setDollParts( this, param, 0, 0 );
        _bodyTarget = setTarget( _body, _body, 0, -80 );

        // 頭
        param = new Array();
        param.push( new SegmentParam( 50, 20 ) );
        _head = setDollParts( _body.getSegmentAt(0), param, 50, 0 );
        _headTarget = setTarget( _body.getSegmentAt(0), _head, 100, 0 );

        // 左手
        param = new Array();
        param.push( new SegmentParam( 50, 20 ) );
        param.push( new SegmentParam( 50, 20 ) );
        _leftArm = setDollParts( _body.getSegmentAt(0), param, 40, -40 );
        _leftArmTarget = setTarget( _body.getSegmentAt(0), _leftArm, -50, -100 );

        // 右手
        param = new Array();
        param.push( new SegmentParam( 50, 20 ) );
        param.push( new SegmentParam( 50, 20 ) );
        _rightArm = setDollParts( _body.getSegmentAt(0), param, 40, 40 );
        _rightArmTarget = setTarget( _body.getSegmentAt(0), _rightArm, -50, 100 );

        // 左足
        param = new Array();
        param.push( new SegmentParam( 60, 20 ) );
        param.push( new SegmentParam( 70, 20 ) );
        _leftLeg = setDollParts( _body, param, -30, 0 );
        _leftLegTarget = setTarget( this, _leftLeg, -30, 130 );

        // 右足
        param = new Array();
        param.push( new SegmentParam( 60, 20 ) );
        param.push( new SegmentParam( 70, 20 ) );
        _rightLeg = setDollParts( _body, param, 30, 0 );
        _rightLegTarget = setTarget( this, _rightLeg, 30, 130 );

        _rootTarget = new IkTarget( 0, 0 );
        addChild( _rootTarget );

        addEventListener( Event.ENTER_FRAME, loop );
    }

    private function setDollParts( _parent:DisplayObjectContainer, _param:Array, _x:int, _y:int ):DollParts
    {
        var parts : DollParts = new DollParts( _param );
        parts.x = _x;
        parts.y = _y;
        _parent.addChild( parts );

        return parts;
    }

    private function setTarget( _parent:DisplayObjectContainer, _ikParent:DollParts, _x:int, _y:int ):IkTarget
    {
        var target:IkTarget = new IkTarget( _x, _y );
        target.ikParent = _ikParent;
        _parent.addChild( target );

        return target
    }

    private function loop( event:Event ):void
    {
        _body.x = _rootTarget.x;
        _body.y = _rootTarget.y;
        _body.upDate( _bodyTarget.ikX, _bodyTarget.ikY );
        _head.upDate( _headTarget.ikX, _headTarget.ikY );
        _leftArm.upDate( _leftArmTarget.ikX, _leftArmTarget.ikY );
        _rightArm.upDate( _rightArmTarget.ikX, _rightArmTarget.ikY );
        _leftLeg.upDate( _leftLegTarget.ikX, _leftLegTarget.ikY );
        _rightLeg.upDate( _rightLegTarget.ikX, _rightLegTarget.ikY );
//        tf.text = obj2xml("doll",this.toObject());
        
    }

}    

internal class DollParts extends Sprite
{
    private var segments /*Segment*/:Array;
    public function toObject():Object {
        var obj:Object = {
            "x":x,
            "y":y,
            "rotation":rotation
        };
        var segobjs:Array = [];
        for(var i:int=0;i < segments.length; i++) {
            segobjs[i] = segments[i].toObject();
        }
        obj["segments"] = segobjs;
        return obj;
    }

    public function setXML(x:XML):void {
        dbg("dollparts")
        this.x = parseFloat(x.x)
        y = parseFloat(x.y)
        rotation = parseFloat(x.rotation);
        for(var i:int=0;i < segments.length; i++) {
            segments[i].setXML(x.segments.v[i][0]);
        }
    }
    
    public function getSegmentAt( num:int ):Segment {
        return segments[ num ];
    }

    public function DollParts( params/*SegmentParam*/:Array ):void {
        segments = new Array();

        for each( var seg:SegmentParam in params )
        {
            var segment : Segment = new Segment( seg );
            addChild( segment );
            segments.push( segment );
        }            
    }

    public function upDate( targetX:int, targetY:int ):void
    {
        var target : Point = new Point( targetX, targetY );
        var leng : int = segments.length;
        for ( var i : int = 0; i < leng; i++ )
        {
            target = reach( segments[i], target.x, target.y );
            if ( i >= 1 )
            {
                var pin : Point = segments[i].getPin();
                segments[i-1].x = pin.x;
                segments[i-1].y = pin.y;
            }
        }
    }

    private function reach( segment:Segment, px:Number, py:Number ):Point
    {
        var dx:Number = px - segment.x;
        var dy:Number = py - segment.y;
        var angle:Number = Math.atan2(dy, dx);
        segment.rotation = angle * 180 / Math.PI;

        var pin : Point = segment.getPin();
        var w : Number = pin.x - segment.x;
        var h : Number = pin.y - segment.y;
        var tx : Number = px - w;
        var ty : Number = py - h;
        return new Point(tx, ty);
    }
}

internal class Segment extends Sprite
{
    public function toObject():Object {
        var obj:Object = {};
        obj["_length"]=_length;
        obj["width"]=_width;
        obj["x"]=x;
        obj["y"]=y;
        obj["count"]=count;
        obj["rotation"]=rotation;
        return obj;
    }
    public function setXML(x:XML):void {
        _length = parseInt(x._length)
        _width =parseInt(x.width)
        this.x = parseFloat(x.x)
        y = parseFloat(x.y)
        count =parseInt(x.count)
        rotation =parseFloat(x.rotation)
    }
    private var _length : int;
    private var _width : int;

    private static var colors:Array = [ 0xff0000, 0x00ff00, 0x0000ff ];
    private static var count:int = 0;

    public function Segment( segmentParam:SegmentParam )
    {
        this._length = segmentParam.length;
        this._width  = segmentParam.width;

        graphics.beginFill( colors[count%3], 0.2 );
        graphics.drawRect( -_width / 2, -_width / 2, _width + _length, _width );
        count++;

        graphics.drawCircle(0, 0, 4 );
        graphics.drawCircle( _length, 0, 2);
        graphics.endFill();

        mouseEnabled = false;
    }

    public function getPin():Point
    {
        var angle:Number = rotation * Math.PI / 180;
        var px:Number = x + Math.cos(angle) * _length;
        var py:Number = y + Math.sin(angle) * _length;
        return new Point( px, py );
    }
}

internal class SegmentParam
{
    public var length:int;
    public var width : int;

    public function SegmentParam( length:int, width:int ):void
    {
        this.length = length;
        this.width = width;
    }
}




import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.display.InteractiveObject;
import flash.display.Loader;
import flash.display.Shape;
import flash.display.SimpleButton;
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;

class Button extends SimpleButton {
    
    public function Button(label:String, width:int = 0):void {
        var up:Sprite = _buildImage(label, 0x0, width);
        var over:Sprite = _buildImage(label, 0x333333, width);
        var down:Sprite = _buildImage(label, 0x333333, width);
        down.y = 1;
        super(up, over, down, up);
    }
    
    private static function _buildImage(label:String, color:int, width:int = 0):Sprite {
        var text:TextField = new TextField();
        text.defaultTextFormat = new TextFormat('Verdana', 10, 0xffffff, true, null, null, null, null, TextFormatAlign.CENTER);
        text.autoSize = TextFieldAutoSize.LEFT
        text.selectable = false;
        text.text = label;
        text.x = (width - text.width) >> 1;
        text.y = 5;
        var base:Shape = new Shape();
        var g:Graphics = base.graphics;
        g.beginFill(color);
        g.drawRect(0, 0, width, text.height + 10);
        g.endFill();
        var sp:Sprite = new Sprite();
        sp.addChild(base);
        sp.addChild(text);
        return sp;
    }
}