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

ミツバチを歩かせたくなった(Short ver.)

<ミツバチを歩かせたくなった ShortVer>
説明用コードを削除して短くしてみました。 びっくりするほど短くならなかった;;;
虫好きには可愛く、虫嫌いの方には気持ち悪くみえれば成功
行数を減らすため、ミツバチグラフィックを微調整
いつ完成するか不明ですが、ミツバチ集団バージョンも作成中。現在高速化方法模索中
/**
 * Copyright zendenmushi ( http://wonderfl.net/user/zendenmushi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/sqUC
 */

// forked from zendenmushi's ミツバチを歩かせたくなった
//
// <ミツバチを歩かせたくなった ShortVer>
// 説明用コードを削除して短くしてみました。 びっくりするほど短くならなかった;;;
//
// 虫好きには可愛く、虫嫌いの方には気持ち悪くみえれば成功
//
//
// 行数を減らすため、ミツバチグラフィックを微調整
//
// いつ完成するか不明ですが、ミツバチ集団バージョンも作成中。現在高速化方法模索中
package 
{
	import com.bit101.components.CheckBox;
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.display.StageDisplayState;
	import flash.events.Event;
	import flash.events.FullScreenEvent;
	import flash.events.MouseEvent;
	import flash.filters.BlurFilter;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.utils.getTimer;
	import frocessing.core.F5BitmapData2D;
	import frocessing.core.F5Graphics2D;
	
	/**
	 * ...
	 * @author TMaeda
	 */
    [SWF(width=465,height=465,backgroundColor=0xcccccc,frameRate=60)]
	public class HoneyBeeWalk extends Sprite 
	{
		private var step : int = 0;
		private var txt  : TextField = new TextField();
		private var legs : Vector.<Leg> = new Vector.<Leg>;
		private var canvas: F5BitmapData2D;
		
		private var autoCheckbox : CheckBox;
		private var fullscreenCheckbox : CheckBox;
		
		private var abdomenState : int = 0;
		private var honey : Point = new Point;
		private var lastHoney : Point = new Point;
		
		private var temppos1 : Point = new Point();
		private var temppos2 : Point = new Point();
		
		private var mouseIsDown : Boolean = false;
		
		private var blur : BlurFilter = new BlurFilter(4, 4, 1);
		private var zeroPoint : Point = new Point(0, 0);
		
		private var bodyAngle : Number;
		private var appear : int = 0;
		private var after_fly : int = 0;
		private var dice_count : int = 0;
		private var dice_pos : Point = new Point();
		
		private var walk : WalkMotion;
		private var fly : FlyingMotion;
		
		public function HoneyBeeWalk()
		{
            Wonderfl.capture_delay( 30 );
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}

		public function init( e : Event = null) : void
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			addEventListener(Event.ENTER_FRAME, enterFrame);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
			stage.addEventListener(FullScreenEvent.FULL_SCREEN, changeFullscreen);
		
			canvas = new F5BitmapData2D(stage.stageWidth, stage.stageHeight, true, 0xff808080);
			addChild(new Bitmap(canvas.bitmapData) );
			
			autoCheckbox = new CheckBox(this, 0, 0, "AUTO");
			autoCheckbox.enabled = false;
			fullscreenCheckbox = new CheckBox(this, 0, 0, "FULLSCREEN", fullscreenChecked);
			fullscreenCheckbox.y = stage.stageHeight-fullscreenCheckbox.height;
			autoCheckbox.y = stage.stageHeight-fullscreenCheckbox.height-autoCheckbox.height;
			
			txt.autoSize = TextFieldAutoSize.LEFT;
			addChild(txt);
			
			// 脚構造をセットアップ ここで指定しているrotate angleはあまり意味なし
			// front 
			legs[0] = new Leg([ { x:8, y: -8, len:16, rotate: -30 } , { len:16, rotate:45 }, { len:24, rotate: -90 } ]);
			legs[1] = new Leg([ { x: -8, y: -8, len:16, rotate: -150 } , { len:16, rotate:-45 }, { len:24, rotate:90 } ]);
			
			// middle
			legs[2] = new Leg([ { x:8, y: 0, len:32, rotate: 15 } , { len:16, rotate: -45 }, { len:16, rotate: -20 } ]);
			legs[3] = new Leg([ { x: -8, y: 0, len:32, rotate: 165 } , { len:16, rotate:45 }, { len:16, rotate:20 } ]);
			//
			// last
			legs[4] = new Leg([ { x:8, y: 8, len:16, rotate: 45 } , { len:24, rotate: -30 }, { len:48, rotate: 45 } ]);
			legs[5] = new Leg([ { x:-8, y: 8, len:16, rotate: 135 } , { len:24, rotate:30 }, { len:48, rotate:-45 } ]);

			txt.text = "Apis cerana japonica";
			txt.x = (stage.stageWidth - txt.width) / 2;
			txt.y = stage.stageHeight - 50;
			honey.x = 0;
			honey.y = stage.stageHeight;
			appear = 360;
			dice_count = 0;
			
			autoCheckbox.enabled = true;
			autoCheckbox.selected = true;
			
			walk = new WalkMotion(legs);
			fly = new FlyingMotion(legs);
		}
		
		private function changeFullscreen(e:Event):void 
		{
			if (stage.displayState == StageDisplayState.FULL_SCREEN) {
				fullscreenCheckbox.selected = true;
			} else {
				fullscreenCheckbox.selected = false;
			}
		}
		
		private function fullscreenChecked(e:Event) : void
		{
			if (!fullscreenCheckbox.selected) {
				stage.fullScreenSourceRect = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
				stage.displayState = StageDisplayState.NORMAL;
			} else {
				stage.fullScreenSourceRect = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
				stage.displayState = StageDisplayState.FULL_SCREEN;
			}
		}
		

		private function mouseUp(e:MouseEvent):void 
		{
			mouseIsDown = false;
		}
		
		private function mouseDown(e:MouseEvent):void 
		{
			mouseIsDown = true;
		}
		private function enterFrame(e:Event):void 
		{
			var i : int, j : int, thi : Number, a : Number;
			var flying : Boolean = false;

			canvas.bitmapData.fillRect(canvas.bitmapData.rect, 0xff808080);
			//state++;
			
			if (appear > 0) {
				// 登場
				bodyAngle = ((appear*appear)/180) * Math.PI / 180;
				honey.x = Math.cos(bodyAngle) * (appear+20);
				honey.y = Math.sin(bodyAngle) * (appear+20);
				flying = ((appear * appear) / 180) > 30;
				if (!flying) walk.stepState();
				appear--;
				after_fly = 30;
				dice_count = 1;
				dice_pos.x = 0;
				dice_pos.y = 0;
			} else if (mouseIsDown || autoCheckbox.selected) {
				// 自動移動、or マウスドラッグ
				if (autoCheckbox.selected) {
					if (dice_count == 0) {
						if (Math.random() * 100 > 90) {
							dice_pos.x = (Math.round(Math.random()*2)-1)*100;
							dice_pos.y = ((Math.random()*2)-1)*100;
						} else {
							dice_pos.x = Math.random() * 48 - 24;
							dice_pos.y = Math.random() * 48 - 24;
						}
						
					}
					dice_count = (dice_count + 1) & 0x1f;
					temppos1.x = honey.x + dice_pos.x + Math.random()*16-8;
					temppos1.y = honey.y + dice_pos.y + Math.random()*16-8;
					if (temppos1.x > stage.stageWidth / 2-32) temppos1.x = stage.stageWidth / 2 - 32;
					if (temppos1.x < -stage.stageWidth / 2+32) temppos1.x = -stage.stageWidth / 2 + 32;
					if (temppos1.y > stage.stageHeight / 2-32) temppos1.y = stage.stageHeight / 2 - 32;
					if (temppos1.y < -stage.stageHeight / 2+32) temppos1.y = -stage.stageHeight / 2 + 32;
				} else {
					temppos1.x = stage.mouseX - stage.stageWidth / 2;
					temppos1.y = stage.mouseY - stage.stageHeight / 2;
				}
				temppos2.x = honey.x;
				temppos2.y = honey.y;
				var ba : Number = Math.atan2( temppos1.y - honey.y, temppos1.x - honey.x);
				var dx : Number = (temppos1.x - honey.x);
				var dy : Number = (temppos1.y - honey.y);
				
				honey.x += dx / 8;
				honey.y += dy / 8;
				if ((honey.x != lastHoney.x) || (honey.y != lastHoney.y)) walk.stepState();
				
				flying = Math.sqrt(dx * dx + dy * dy) > 64;
				after_fly |= flying ? 30 : 0;
				if (dist(temppos1, temppos2) > 32){					
					bodyAngle = interpolateAngle(bodyAngle,  ba + Math.PI / 2, flying ? 1/4 : 1 / 32);
				} else if (mouseIsDown) {
					autoCheckbox.selected = false;
				}
			} else {
				if (after_fly > 0) { // 飛行後に脚の角度を着地形態にするために数ステップ進める
					after_fly--;
					walk.stepState();
				}
				flying = false;
			}
			lastHoney.x = honey.x;
			lastHoney.y = honey.y;
			
			abdomenState++;
			
			if (flying) {
				fly.stepFrame(stage.stageWidth / 2 + honey.x, stage.stageHeight / 2 + honey.y, bodyAngle);
			} else {
				walk.stepFrame(stage.stageWidth / 2 + honey.x, stage.stageHeight / 2 + honey.y, bodyAngle);
			}
			
			canvas.beginDraw();
			drawBodyShadow(honey.x, honey.y, bodyAngle, 0, abdomenState, flying);
			canvas.endDraw();
			// 影ぼかし
			canvas.bitmapData.applyFilter(canvas.bitmapData, canvas.bitmapData.rect, zeroPoint, blur);
			
			canvas.beginDraw();
			drawBody(honey.x, honey.y, bodyAngle, abdomenState, flying);
			canvas.endDraw();
		}
	
		private var offsetrec : int;
		private function drawBodyShadow(dx : int,  dy : int, angle : Number, scroll : int, state : int, flying : Boolean) : void
		{
			//if (!flying) offsetrec = 8;
			
			var offset : int = flying ? offsetrec + (32 - offsetrec) / 4: offsetrec + (8 - offsetrec) / 4;
			offsetrec = offset;
			
			canvas.fill(0.5,0.5,0.5,0.2);
			canvas.pushMatrix();
			canvas.strokeAlpha = 0;
			canvas.translate(stage.stageWidth / 2 + dx+offset, stage.stageHeight / 2 + dy +offset + scroll);
			canvas.rotate(angle);
			canvas.ellipse( -0, -32, 48, 32);
			canvas.ellipse( 0, 64 + (state % 15) / 2, 70, 96 + (state % 15));
			canvas.ellipse(0, 0, 56,48);

			canvas.stroke(0x00);
			canvas.strokeAlpha = 0.2;
			canvas.moveTo( -4, -48);
			canvas.lineTo( -8, -52);
			canvas.lineTo( -12, -64);
			canvas.moveTo( 4, -48);
			canvas.lineTo( 8, -52);
			canvas.lineTo( 12, -64);
			
			canvas.popMatrix();
			if (!flying) {
				var legcnt : int = legs.length;
				for (var i : int = 0; i < legcnt; i++) {
				var segcnt : int = legs[i].items.length;
					canvas.stroke(0x00);
					canvas.moveTo(legs[i].root.x + 8, legs[i].root.y + 8);
					for (var j : int = 0; j < segcnt; j++) {
						if (legs[i].items[j].IK && (j == segcnt-1)) {
							canvas.strokeAlpha = 0.5;
							canvas.lineTo(legs[i].items[j].IKPoint.x, legs[i].items[j].IKPoint.y);
						} else {
							canvas.strokeAlpha = 0.2;
							canvas.lineTo(legs[i].items[j].IKPoint.x + 8-(j*4)/segcnt, legs[i].items[j].IKPoint.y + 8-(j*4)/segcnt);
						}
					}
				}
			}
		}
		
		private function drawBody(dx : int,  dy : int, angle : Number, state : int, fly : Boolean) : void
		{
			var i : int, j : int;
			var sign : int = 1;
			
			canvas.strokeAlpha = 1;
			// leg 
			var legcnt : int = legs.length;
			for (i = 0; i < legcnt; i++) {
				var segcnt : int = legs[i].items.length;
				for (j  = 0; j < segcnt; j++) {
					canvas.pushMatrix();
					var m : Matrix = legs[i].items[j].matrix;
					canvas.resetMatrix();
					canvas.applyMatrix(m.a, m.b, m.c, m.d, m.tx, m.ty);
					canvas.stroke(0x806020);

					canvas.beginFill(0xff001020);
					canvas.ellipse( legs[i].items[j].len/2, 0, legs[i].items[j].len, 4+j+( (i>=2) && (j==2) ? 4:0));
					canvas.endFill();
					canvas.stroke(0xffffd040);
					canvas.moveTo(legs[i].items[j].len-2, -2);
					canvas.lineTo(legs[i].items[j].len-2, 2);
					
					if (j == 2) {
						if (i & 4) { // 後脚に花粉
							canvas.strokeAlpha = 0;
							canvas.beginFill(0xffffd040);
							canvas.ellipse(legs[i].items[j].len / 3, 0, 24, 16);
							canvas.endFill();
							canvas.strokeAlpha = 1;
						}
						canvas.stroke(0xff001020);
						if (legs[i].items[j].IK) {
							canvas.moveTo(legs[i].items[j].len, 0);
							canvas.lineTo(legs[i].items[j].len , (i & 1) ? 4 : -4);
						} else {
							canvas.moveTo(legs[i].items[j].len, 0);
							canvas.lineTo(legs[i].items[j].len + 4, (i & 1) ? 3 : -3);
						}
					}
					canvas.popMatrix();
				}
			}
			
			// head
			canvas.fill(0xff, 0xff, 0xff, 1);
			canvas.pushMatrix();
			canvas.stroke(0x806020);
			canvas.translate(stage.stageWidth / 2 + dx, stage.stageHeight / 2 + dy);
			canvas.rotate(angle);

			canvas.beginFill(0xa07000);
			canvas.ellipse( -0, -32, 48, 32);
			canvas.endFill();

			sign = 1;
			for (i = 0; i < 2; i++) {
				canvas.stroke(0x806020);
				canvas.beginFill(0x201000);
				canvas.ellipse( -16*sign, -32, 16, 24);
				canvas.pushMatrix();
				canvas.translate( -16*sign, -32);
				canvas.rotate( -angle);
				canvas.beginFill(0xffffff, 0.8);
				canvas.circle( -4, -4, 2);
				canvas.endFill();
				canvas.popMatrix();
				canvas.endFill();
				// 触角
				canvas.stroke(0x201000);
				canvas.strokeWeight(2);
				canvas.moveTo( -4*sign, -48);
				canvas.lineTo( -8*sign, -52);
				canvas.strokeWeight(3);
				canvas.lineTo( -12*sign, -64);
				canvas.strokeWeight(1);
				
				sign *= -1;
			}
			
			canvas.stroke(0x806020);
			// abdomen
			canvas.beginFill(0xa07000);
			canvas.ellipse( 0, 64 + (state % 15) / 2, 70, 96 + (state % 15));
			canvas.endFill();
			
			canvas.stroke(0xf0, 0x80, 0x00, 0x00);
			canvas.beginFill(0xf09000);
			canvas.ellipse( 0, 64 + (state % 15) / 2, 70, 86 + (state % 15));
			canvas.ellipse( 0, 64 + (state % 15) / 2, 70, 66 + (state % 15));
			canvas.endFill();
			canvas.beginFill(0xf08000);
			canvas.ellipse( 0, 64 + (state % 15) / 2, 70, 46 + (state % 15));
			canvas.ellipse( 0, 64 + (state % 15) / 2, 70, 26 + (state % 15));
			canvas.endFill();
			
			for (i = 0; i < 3; i++) {
				canvas.beginFill(0x201000);
				canvas.ellipse( 0, 64 + (state % 15) / 2, 70, 96 -i*40+ (state % 15));
				canvas.ellipse( 0, 64 -5+i+ (state % 15) / 2, 70, 76 -i*35+ (state % 15));
				canvas.endFill();
			}

			// chest
			canvas.beginFill(0x402010);
			canvas.ellipse(0, 0, 56,48);
			canvas.endFill();
			canvas.beginFill(0x201000);
			canvas.ellipse(0, -5, 46,38);
			canvas.endFill();

			// chest fur
			canvas.fill(0xff, 0xff, 0xff, 0xff);
			for (i = 0; i < 360; i+=4) {
				var ra1 : Number = i * Math.PI / 180;
				var x0 : Number = Math.sin(ra1) * 54/2;
				var y0 : Number = Math.cos(ra1) * 44/2;
				var x1 : Number = Math.sin(ra1) * 59/2;
				var y1 : Number = Math.cos(ra1) * 52/2+2;
				var x2 : Number = Math.sin(ra1) * 64/2;
				var y2 : Number = Math.cos(ra1) * 56/2+4;
				canvas.stroke(0xa0, 0x70, 0x00, 0x80);
				canvas.moveTo(x0, y0);
				canvas.lineTo(x1, y1);
				canvas.stroke(0xf0, 0x80, 0x00, 0x10);
				canvas.lineTo(x2, y2);
			}
			// wing
			var flystate : int = (state*2) % 10;
			if (fly) flystate = flystate*2 + 90;

			sign = 1;
			for (i = 0; i < 2; i++) {
				canvas.stroke(0x00, 0xff, 0xff, 0x40);
				canvas.strokeAlpha = 0.5;
				canvas.pushMatrix();
				canvas.translate( -8*sign, 8);
				canvas.rotate(sign*flystate*Math.PI / 180);
				canvas.beginFill(0x00ffff,0.2);
				canvas.moveTo( -8*sign, 0);
				canvas.lineTo( -24*sign, 48);
				canvas.arcCurveTo( -24*sign,48, -12*sign, 56,2, 8, false, sign == -1);
				canvas.strokeAlpha = 0;
				canvas.arcCurveTo( -12*sign, 56, 4*sign, 32, 2, 4, false, sign == -1);
				canvas.lineTo( 0, 8);
				canvas.endFill();
				canvas.popMatrix();
				
				sign *= -1;
			}

			canvas.fill(0xff, 0xff, 0xff, 0xff);
			
			canvas.popMatrix();
			
		}
	}
	
}

function dist(p0 : Point, p1 : Point) : Number
{
	return Math.sqrt( (p0.x - p1.x) * (p0.x - p1.x) + (p0.y - p1.y) * (p0.y - p1.y) );
}

function unitVector(p0 : Point, p1 : Point, /*out*/ u : Point) : Boolean
{
	var len : Number = dist(p0, p1);
	if (len > 0) {
		u.x = (p0.x - p1.x) / len;
		u.y = (p0.y - p1.y) / len;
		return true;
	} else return false;
}

function dotProduct(p0 : Point, p1 : Point) : Number
{
	return p0.x * p1.x + p0.y * p1.y;
}

function crossProductZ(p0 : Point, p1 : Point) : Number
{
	return p0.x * p1.y - p0.y * p1.x;
}


function interpolateAngle(from : Number, to : Number, coef : Number/*, limit : Number = Math.PI/18*/ ) : Number
{
	var d1 : Number = Math.abs(to-from);
	var to2 : Number = to;
	var from2 : Number = from;
	
	if (to2 < 0) to2 += 2 * Math.PI;
	if (from2 < 0) from2 += 2 * Math.PI;
	var d2 : Number = Math.abs(to2 - from2);
	var d : Number = 0;
	if (d1 < d2) {
		d = (to-from) * coef;
	} else {
		d = (to2 - from2) * coef;
	}
	
	from += d;
	
	if (from > Math.PI) from -= 2 * Math.PI;
	if (from < -Math.PI) from += 2 * Math.PI;
	
	return from;
}

import flash.geom.Matrix;
import flash.geom.Point;
import frocessing.core.F5BitmapData2D;
import frocessing.geom.FMatrix2D;

class LegSegment
{
	public var root : Point = new Point(); // 親jointからの相対値
	public var joint : Point = new Point(); // joint絶対値
	public var len : Number = 10;
	public var rotate : Number = 0; // 
	public var IKRotate : Number = 0; // 
	public var IKPoint : Point = new Point(); // 接地点の座標
	
	public var uselim : Boolean = false;
	public var limmax : Number = 0;
	public var limmin : Number = 0;

	private var _IK : Boolean = false;
	private var _matrix : FMatrix2D = new FMatrix2D();
	
	public function get IK():Boolean { return _IK; }
	
	public function set IK(value:Boolean):void 
	{
		if (!_IK && value) {
			IKPoint.x = joint.x;
			IKPoint.y = joint.y;
		}
		_IK = value;
	}
	
	public function get matrix():FMatrix2D { return _matrix; }
}

class Leg
{
	private var temppos : Point = new Point();
	private var temppos1 : Point = new Point();
	private var temppos2 : Point = new Point();

	public var items : Vector.<LegSegment> = new Vector.<LegSegment>;
	public var root : Point = new Point();

// 行数を減らすため、独自MatrixStackクラスを削除。 代わりに1x1のF5BitmapDataをMatrix Stackクラス代わりに使う
	private var f5matrix : F5BitmapData2D = new F5BitmapData2D(1,1);

	public function Leg( assemble : Array )
	{
		var cnt : int = assemble.length;
		for (var i : int = 0; i < cnt; i++) {
			items[i] = new LegSegment();
			items[i].root.x = 0;
			items[i].root.y = 0;
			if (assemble[i].x != undefined) {
				items[i].root.x = assemble[i].x;
				items[i].root.y = assemble[i].y;
			} else {
			}
			items[i].len = assemble[i].len;
			items[i].rotate = assemble[i].rotate * Math.PI / 180;
			
			if ((assemble[i].limmax != undefined) && (assemble[i].limmin != undefined)) {
				items[i].uselim = true;
				items[i].limmax = assemble[i].limmax;
				items[i].limmin = assemble[i].limmin;
			}
		}
		if (cnt > 0) computeFK(0,0,0);
	}
	
	public function computeFK(x : Number, y : Number, angle : Number) : void
	{
		var cnt : int = items.length;
		if (cnt == 0) return;
		
		
		f5matrix.pushMatrix();
		f5matrix.translate(x, y);
		f5matrix.rotate(angle);
		
		for (var i : int = 0; i < cnt; i++) {
			temppos.x = items[i].root.x;
			temppos.y = items[i].root.y;
			
			if (i == 0) {
				root = f5matrix.matrix.transformPoint(temppos);
			}
			f5matrix.translate(temppos.x, temppos.y);
			f5matrix.rotate(items[i].rotate);
			
			temppos.x = items[i].len;
			temppos.y = 0;
			items[i].joint = f5matrix.matrix.transformPoint(temppos);
			
			items[i].matrix.identity();
			items[i].matrix.concat(f5matrix.matrix);

			f5matrix.translate(items[i].len, 0);
		}
		f5matrix.popMatrix();
	}
	
	public function setIK(useIK : Boolean, startIndex : int, endIndex : int) : void
	{
		if (endIndex >= items.length - 1) endIndex = items.length - 1;
		
		for (var i : int = startIndex; i <= endIndex; i++) {
			items[i].IK = useIK;
		}
		
	}
	
	public function computeIK(x : Number, y : Number, angle : Number, interpolateCoeff : Number) : void
	{
		var i : int, j : int;
		var cnt : int = items.length;
		if (cnt == 0) return;
		
		computeFK(x, y, angle);
		
		for (i = cnt - 1; i > 0; i--) {
			if (items[i].IK) adjustIK(i);
		}
		for (j = 0; j < items.length; j++) {
			if (j == 0) {
				temppos2.x = Math.cos( angle );
				temppos2.y = Math.sin( angle );
				unitVector( items[j].IKPoint,  root, temppos1);
			} else {
				unitVector( items[j].IKPoint,  items[j - 1].IKPoint, temppos1);
			}
			var ca : Number = Math.max(-1,Math.min(1, dotProduct(temppos1, temppos2))); // 単位ベクトル同士の内積だが、たま~に1を微妙に超えることがあるみたい
			var sa : Number = crossProductZ(temppos1, temppos2);
			var r : Number = Math.acos(ca);
			if (sa > 0) r = -r;
			items[j].IKRotate = r;
			
			temppos2.x = temppos1.x;
			temppos2.y = temppos1.y;
		}
		
		f5matrix.pushMatrix();
		f5matrix.translate(x, y);
		f5matrix.rotate(angle);
		
		for (i = 0; i < cnt; i++) {
			temppos.x = items[i].root.x;
			temppos.y = items[i].root.y;
			
			if (i == 0) {
				root = f5matrix.matrix.transformPoint(temppos);
			}
			
			if (!items[i].IK) {
				items[i].IKRotate = interpolateAngle(items[i].IKRotate, items[i].rotate, interpolateCoeff);
			}

			if (items[i].uselim) {
				if (items[i].IKRotate > items[i].limmax) {
					items[i].IKRotate = items[i].limmax;
				} else if (items[i].IKRotate < items[i].limmin) {
					items[i].IKRotate = items[i].limmin;
				}
			}
			
			f5matrix.translate(temppos.x, temppos.y);
			f5matrix.rotate(items[i].IKRotate);
		
			temppos.x = items[i].len;
			temppos.y = 0;
			// transformPoint()がnew して値を返すのがどうしても馴染めない・・・・
			items[i].IKPoint = f5matrix.matrix.transformPoint(temppos);
			items[i].matrix.identity();
			items[i].matrix.concat(f5matrix.matrix);

			f5matrix.translate(items[i].len, 0);
		}
		f5matrix.popMatrix();
	}
	
	public function adjustIK(index : int) : void
	{
		if (index < 1) return;
		
		var item_2 : Point;
		if (index >= 2) {
			item_2 = items[index - 2].joint;
		} else {
			item_2 = root;
		}
		
		var len : Number = dist(items[index].IKPoint, item_2);
		
		if ((len <= items[index].len + items[index-1].len) && (len >= Math.abs(items[index].len - items[index - 1].len))) { // 交点がある可能性あり
			var thi : Number = Math.atan2(item_2.y - items[index].IKPoint.y, item_2.x - items[index].IKPoint.x);
			// 余弦定理で2つの交点を求める cosa = (b*b+c*c-a*a)/(2bc)
			var cf : Number = (items[index].len * items[index].len + len * len - items[index - 1].len * items[index - 1].len) / (2 * items[index].len * len);
			var a : Number = Math.acos(cf);

			temppos1.x = items[index].IKPoint.x + Math.cos(thi + a) * items[index].len;
			temppos1.y = items[index].IKPoint.y + Math.sin(thi + a) * items[index].len;
			temppos2.x = items[index].IKPoint.x + Math.cos(thi - a) * items[index].len;
			temppos2.y = items[index].IKPoint.y + Math.sin(thi - a) * items[index].len;
			// 求まった2つの交点から元の間接に近い点を求め、それを新しい間接位置にする
			var l1 : Number = dist(temppos1, items[index-1].IKPoint);
			var l2 : Number = dist(temppos2, items[index-1].IKPoint);
			if (l1 < l2) {
				items[index-1].IKPoint.x = temppos1.x;
				items[index-1].IKPoint.y = temppos1.y;
			} else {
				items[index-1].IKPoint.x = temppos2.x;
				items[index-1].IKPoint.y = temppos2.y;
			}
		} else {
			thi = Math.atan2(item_2.y - items[index].IKPoint.y, item_2.x - items[index].IKPoint.x);
			// 2つの円の中心を結ぶ直線と先端の円の交点を求め、それを新しい間接位置にする
			temppos1.x = items[index].IKPoint.x + Math.cos(thi) * items[index].len;
			temppos1.y = items[index].IKPoint.y + Math.sin(thi) * items[index].len;
			items[index-1].IKPoint.x += (temppos1.x - items[index-1].IKPoint.x) / 4;
			items[index-1].IKPoint.y += (temppos1.y - items[index-1].IKPoint.y) / 4;
			
		}
		
	}
	
}

class FlyingMotion
{
	private var legs : Vector.<Leg> = null;
	private var state : int = 0;
	private var temppos1 : Point = new Point();
	private var temppos2 : Point = new Point();

	public function FlyingMotion(legs : Vector.<Leg>)
	{
		this.legs = legs;
	}
	public function stepState() : void
	{
		state++;
	}
	public function stepFrame(x : Number, y : Number, angle : Number) : void
	{
		var legcnt : int = legs.length;
		for (var i : int = 0; i < legcnt; i++) {
			legs[i].setIK( false, 0, legs[i].items.length-1);
			switch (i) {
				case 0:
				case 1:// 飛行時の前足角度
				{
					legs[i].items[0].rotate = (-90+(i==1?-40:40))* Math.PI / 180;
					legs[i].items[1].rotate = (i==1?-50:50)* Math.PI / 180;
					legs[i].items[2].rotate = (i==1?160:-160)* Math.PI / 180;
					break;
				}
				case 2:
				case 3:// 飛行時の中足角度
				{
					legs[i].items[0].rotate = (90+(i==3?55:-55))* Math.PI / 180;
					legs[i].items[1].rotate = (i == 3? -70:70) * Math.PI / 180;
					legs[i].items[2].rotate = (i == 3? 20:-20) * Math.PI / 180;
					break;
				}
				case 4:
				case 5:// 飛行時の後足角度
				{
					legs[i].items[0].rotate = (90+(i==5?55:-55))* Math.PI / 180;
					legs[i].items[1].rotate = (i == 5? -20:20) * Math.PI / 180;
					legs[i].items[2].rotate = (i == 5? -40:40) * Math.PI / 180;
					break;
				}
			}
			legs[i].computeIK(x, y, angle, 1/4);
		}
	}
}

class WalkMotion
{
	private var legs : Vector.<Leg> = null;
	private var state : int = 0;
	private var temppos1 : Point = new Point();
	private var temppos2 : Point = new Point();

	
	public function WalkMotion(legs : Vector.<Leg>)
	{
		this.legs = legs;
	}
	
	public function stepState() : void
	{
		state++;
	}
	
	public function stepFrame(x : Number, y : Number, angle : Number) : void
	{
		var legcnt : int = legs.length;
		var nr : Number = 0;
		var rad : Number = 0;
		for (var i : int = 0; i < legcnt; i++) {
			legs[i].computeIK(x, y, angle, 1/8);
			switch (i) {
				case 0:
				case 1:// 前足
				{
					nr = (((state * 10) % 360) / 360) + 0.25;
					// 接地タイミングでsetIK (true, ) を呼び出し、legsegmentをIK操作にする
					if (i == 0) {
						legs[i].setIK( (nr > 0.75) || (nr < 0.25), 0, legs[i].items.length-1);
					} else {
						legs[i].setIK( (nr < 0.75) && (nr > 0.25), 0, legs[i].items.length-1);
					}

					rad = nr * Math.PI * 2;
					legs[i].items[0].rotate = (-90+(i==1?-60:60)+Math.sin(rad)*20)* Math.PI / 180;

					nr = nr+0.5;
					rad = nr * Math.PI * 2;
					legs[i].items[1].rotate = ((i==1?-45:45)-Math.sin(rad)*20)* Math.PI / 180;
					legs[i].items[2].rotate = ((i==1?90:-90)+Math.sin(rad)*20)* Math.PI / 180;
					break;
				}
				case 2:
				case 3:// 中足
				{
					nr = (((state * 10) % 360) / 360) + 0.5;
					if (i == 2) {
						legs[i].setIK( (nr < 1.3) && (nr > 0.8), 0, legs[i].items.length-1);
					} else {
						legs[i].setIK( (nr > 1.3) || (nr < 0.8), 0, legs[i].items.length-1);
					}

					rad = nr * Math.PI * 2;
					legs[i].items[0].rotate = (90+(i==3?95:-95)+Math.sin(rad)*20)* Math.PI / 180;
					nr = nr + 0.75;
					rad = nr * Math.PI * 2;
					legs[i].items[1].rotate = ((i==3?-60:60)-Math.sin(rad)*40)* Math.PI / 180;
					legs[i].items[2].rotate = (i==3?20:-20)* Math.PI / 180;// (10 + Math.sin(state / 10) * 10) * Math.PI / 180;
					break;
				}
				case 4:
				case 5:// 後足
				{
					nr = (((state * 10) % 360) / 360);
					if (i == 4) {
						legs[i].setIK( (nr < 0.3) || (nr > 0.8), 0, legs[i].items.length-1);
					} else {
						legs[i].setIK( (nr > 0.3) && (nr < 0.8), 0, legs[i].items.length-1);
					}
					rad = nr * Math.PI * 2;
					legs[i].items[0].rotate = (90+(i==5?55:-55)-Math.sin(rad)*20)* Math.PI / 180;
					nr = nr + 0.5;// 75;
					rad = nr * Math.PI * 2;
					legs[i].items[1].rotate = ((i==5?30:-30)-Math.sin(rad)*40)* Math.PI / 180;
					legs[i].items[2].rotate = ((i==5?-90:90)+Math.sin(rad)*20)* Math.PI / 180;
					break;
				}
			}
		}
		
	}
	
}
// 行数を減らすため、独自MatrixStackクラスを削除。 代わりに1x1のF5BitmapDataをMatrix Stackクラス代わりに使う