ミツバチを歩かせたくなった(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クラス代わりに使う