IK実験
IK実験
クリックで追加。
あまり綺麗に曲がってくれない・・・・。
//
// IK実験
//
// クリックで追加。
// あまり綺麗に曲がってくれない・・・・。
//
//
package {
import flash.display.Sprite;
import flash.events.*;
[SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="60")]
public class FlashTest extends Sprite {
public function FlashTest() {
Main = this;
initialize();
stage.addEventListener(Event.ENTER_FRAME,update);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onClick);
}
}
}
import flash.display.Sprite;
import flash.text.*;
import flash.events.*;
import flash.geom.*;
var SCREEN_W:Number = 465, SCREEN_H:Number = 465;
var Main:Sprite;
var Text:TextField
var IkAry:Array = new Array;
function initialize():void{
Text = new TextField();
Text.text = "";
Text.autoSize = "left";
Main.addChild(Text);
IkAry.push( new IkBase(100, 150, 10 ) );
IkAry.push( new IkBase(400, 20, 13 ) );
// IkAry.push( new IkBase(400, 420, 7 ) );
}
function onClick(event:MouseEvent):void{
IkAry.push( new IkBase(Main.stage.mouseX, Main.stage.mouseY, 6+Math.random()*7 ) );
if( IkAry.length > 6 ){
IkAry.splice( 0, 1 );
}
}
function update(e :Event):void{
graphicClear();
var ik:IkBase;
for( var i:int=0; i<50; i++ ) {
for each( ik in IkAry ) ik.update();
}
for each( ik in IkAry ) ik.draw();
}
class Node{
public var x:Number;
public var y:Number;
public var Rot:Number = 0;
public function Node( ){
}
}
class IkBase{
public var Length:Number = 25.0;
public var Base:Point = new Point(0,0);
public var Target:Point = new Point(0,0);
public var Nodes:Vector.<Node> = new Vector.<Node>;
public function IkBase( x:Number, y:Number, num:int ){
Base.x = x;
Base.y = y;
for( var i:int=0; i<num; i++ ) Nodes[i] = new Node();
}
// 内積
public function dot( p0:Point, p1:Point ):Number{
return p0.x*p1.x + p0.y*p1.y
}
public function update():void{
Target.x = Main.stage.mouseX;
Target.y = Main.stage.mouseY;
var rotMax:Number = 0.001;
// 先端ノード
var sn:Node = Nodes[Nodes.length-1]
for( var i:int=Nodes.length-2; i>=0; i-- ){
n = Nodes[i]
var tv:Point = new Point();
var sv:Point = new Point();
var rv:Point = new Point();
var lv:Point = new Point();
// 間接から目標に向いたベクトル
tv.x = Target.x - n.x;
tv.y = Target.y - n.y;
// 間接から先端に向いたベクトル
sv.x = sn.x - n.x;
sv.y = sn.y - n.y;
// 右回りのベクトル
rv.x = sv.x * Math.cos( rotMax ) + sv.y * Math.sin( rotMax );
rv.y =-sv.x * Math.sin( rotMax ) + sv.y * Math.cos( rotMax );
// 左回りのベクトル
lv.x = sv.x * Math.cos(-rotMax ) + sv.y * Math.sin(-rotMax );
lv.y =-sv.x * Math.sin(-rotMax ) + sv.y * Math.cos(-rotMax );
var ds:Number = dot( tv, sv );
var dr:Number = dot( tv, rv );
var dl:Number = dot( tv, lv );
if( ds < dr && ds < dl ){
// 回らない
}else if( dr > dl ){
n.Rot += rotMax;
}else{
n.Rot -= rotMax;
}
}
Nodes[0].x = Base.x;
Nodes[0].y = Base.y;
var pn:Node = Nodes[0];
var n:Node;
for( i=1; i<Nodes.length; i++ ){
n = Nodes[i];
n.x = Length * Math.sin( pn.Rot );
n.y = Length * Math.cos( pn.Rot );
n.x += pn.x;
n.y += pn.y;
pn = n;
}
}
public function draw():void{
var pn:Node = Nodes[0];
for( var i:int=1; i<Nodes.length; i++ ){
var n:Node = Nodes[i];
drawLine( pn.x, pn.y, n.x, n.y, 7.5, 0x808020 );
pn = n;
}
drawCircle( Target.x, Target.y, 12, 0xe04000 );
for each( n in Nodes ) drawCircle( n.x, n.y, 8, 0xe0d000 );
drawCircle( Base.x, Base.y, 12, 0xb0a000 );
}
}
function graphicClear():void{
Main.graphics.clear();
Main.graphics.lineStyle(1.2,0xb0b040);
Main.graphics.moveTo( SCREEN_W/2, 0 );
Main.graphics.lineTo( SCREEN_W/2, SCREEN_H );
Main.graphics.moveTo( 0, SCREEN_H/2 );
Main.graphics.lineTo( SCREEN_W, SCREEN_H/2 );
}
function drawLine( sx:Number, sy:Number, ex:Number, ey:Number, size:Number, col:int ):void{
Main.graphics.lineStyle(size,col);
Main.graphics.moveTo( sx, sy );
Main.graphics.lineTo( ex, ey );
}
function drawCircle( x:Number, y:Number, size:Number, col:int ):void{
Main.graphics.lineStyle(1.4,0x000000);
Main.graphics.beginFill(col,1);
Main.graphics.drawCircle(x,y,size);
Main.graphics.endFill();
}