Beautifl - Flash Gallery

Thumbnail : IK実験
IK実験
Nao_u 2009-08-30 All rights reserved

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

// 
// 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();    
}