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;
}
}