Newtype
左下に数値入力後、右下の●をクリックでファンネル生成
生成後は画面の上半分あたりクリックで射出
Σ (1/{|速度の各Bitとの相対位置と垂直な成分|*|相対位置|^0.5})
を最小化するように頑張ってます!
レーザーの当たり判定とかは一切取ってない。Bitからみて当てにくい動きをする。
/**
* Copyright uwi ( http://wonderfl.net/user/uwi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/9StF
*/
// forked from umroom's ファンネル(ビット)wonderfl移植
/*
左下に数値入力後、右下の●をクリックでファンネル生成
生成後は画面の上半分あたりクリックで射出
*/
// Σ (1/{|速度の各Bitとの相対位置と垂直な成分|*|相対位置|^0.5})
// を最小化するように頑張ってます!
// レーザーの当たり判定とかは一切取ってない。Bitからみて当てにくい動きをする。
package
{
import flash.display.*;
import flash.events.*;
import flash.text.*;
[SWF(width="300", height="300", backgroundColor="0x000000", frameRate="30")]
public class Main extends MovieClip
{
private var _bt_mc:MovieClip = new MovieClip();
private var _txt:TextField = new TextField();
public var _bitNum:uint=0;
public var _av : Avoider;
public var _tf : TextField;
public function Main():void
{
_txt.height=30;
_txt.x = 30;
_txt.y = 270;
_txt.background=true;
_txt.backgroundColor=0xFFFFFF;
_txt.type = TextFieldType.INPUT;
_txt.text = "6";
_txt.restrict="0-9";
addChild(_txt);
_bt_mc.graphics.beginFill(0xFF00FF);
_bt_mc.graphics.drawCircle(0,0,20);
_bt_mc.graphics.endFill();
_bt_mc.x = 260;
_bt_mc.y = 280;
_bt_mc.buttonMode=true;
_bt_mc.addEventListener(MouseEvent.CLICK, init);
addChild(_bt_mc);
_av = new Avoider(this, 0, 0, 300, 300, 4, 1.5, 6, 0, 0);
_av.x = 300 / 2;
_av.y = 300 / 2;
addChild(_av);
_tf = new TextField();
addChild(_tf);
_tf.width = 200;
_tf.height = 200;
_tf.textColor = 0xffffff;
}
private function init(me:MouseEvent):void
{
stage.addEventListener(MouseEvent.MOUSE_UP, startMv);
for(var i:uint=1; i<=_bitNum; i++){ removeChild( getChildByName("bit_"+i) ); }
stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
_bitNum = uint(_txt.text);
for(i=1; i<=_bitNum; i++){
var bit:Bit=new Bit();
bit.name="bit_"+i;
bit.rotation = 360*(i-1)/_bitNum;
bit.x = 150 + 30*Math.sin(bit.rotation * Math.PI/180);
bit.y = 150 + -30*Math.cos(bit.rotation * Math.PI/180);
addChild(bit);
}
_av.x = 300/2;
_av.y = 300/2;
}
private function startMv(me:MouseEvent):void
{
if(mouseY<250){
stage.removeEventListener(MouseEvent.MOUSE_UP, startMv);
for(var i:uint=1; i<=_bitNum; i++){ Bit(getChildByName("bit_"+i)).init( i%3*0.2 ); }
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
}
private function onEnterFrame(e : Event) : void
{
_av.step(1);
}
}
}
import flash.display.*;
import flash.events.*;
import gs.*;
import gs.easing.*;
class Bit extends MovieClip
{
private var _laser_mc:MovieClip = new MovieClip();
public var tx : Number = x;
public var ty : Number = y;
public function Bit():void
{
addEventListener(Event.REMOVED_FROM_STAGE, remove);
graphics.beginFill(0xF0F0F0);
graphics.moveTo( 0, 0 );
graphics.lineTo( -5, 24 );
graphics.lineTo( 5, 24 );
graphics.endFill();
_laser_mc.graphics.lineStyle(2, 0xFFFFCC);
_laser_mc.graphics.moveTo(0, 0);
_laser_mc.graphics.lineTo(0, -600);
_laser_mc.scaleY=0;
addChild( _laser_mc );
}
private function remove(e:Event):void
{
removeEventListener(Event.ENTER_FRAME, rot);
removeEventListener(Event.REMOVED_FROM_STAGE, remove);
TweenMax.killTweensOf(this);
TweenMax.killTweensOf(_laser_mc);
}
public function init(delayTime:Number):void
{
var startX:int = 150+300*Math.sin(rotation * Math.PI/180);
var startY:int = 150-300*Math.cos(rotation * Math.PI/180);
TweenMax.to( this, 0.2+Math.random()*0.2, { delay:delayTime, x:startX, y:startY, ease:Cubic.easeIn, onComplete:startMv});
}
public function startMv():void
{
addEventListener(Event.ENTER_FRAME, rot);
var scaleVal:Number = 0.3+Math.random()*0.7;
var bezierData:Array = [
{x:Math.random()*300, y:Math.random()*300},
{x:Math.random()*300, y:Math.random()*300}
];
tx = bezierData[1].x;
ty = bezierData[1].y;
TweenMax.to( this, 0.4+Math.random()*0.4, { delay:0.3+Math.random()*0.2, bezier:bezierData, scaleX:scaleVal, scaleY:scaleVal,
ease:Cubic.easeInOut, onComplete:shot});
}
private function shot():void
{
removeEventListener(Event.ENTER_FRAME, rot);
_laser_mc.scaleY=0;
_laser_mc.alpha=1;
_laser_mc.visible=true;
TweenMax.to(_laser_mc, 0.5, {scaleY:1, ease:Cubic.easeOut} );
TweenMax.to(_laser_mc, 0.3, {delay:0.2, autoAlpha:0, ease:Linear.easeNone, onComplete:startMv} );
}
private function rot(e:Event):void
{
// rotation = 180*Math.atan2(MovieClip(parent).mouseY-y, MovieClip(parent).mouseX-x)/Math.PI+90;
var av : Avoider = Main(parent)._av;
rotation = 180*Math.atan2(av.y-y, av.x-x)/Math.PI+90;
}
}
class Avoider extends Shape
{
private var _main : Main;
private var MAXXX : Number;
private var MINXX : Number;
private var MAXXY : Number;
private var MINXY : Number;
private var MYR : Number;
private var LIMA : Number;
private var STEPTHETA : Number;
public var _val : Number;
private var _vx : Number;
private var _vy : Number;
public function Avoider(
main : Main,
minxx : Number, minxy : Number,
maxxx : Number, maxxy : Number,
myr : Number,
lima : Number, steptheta : Number,
vx0 : Number, vy0 : Number
) : void
{
_main = main;
MINXX = minxx; MINXY = minxy;
MAXXX = maxxx; MAXXY = maxxy;
MYR = myr;
LIMA = lima;
STEPTHETA = steptheta;
_vx = vx0;
_vy = vy0;
graphics.beginFill(0xff0000);
graphics.drawCircle(0, 0, 4);
graphics.endFill();
}
private var _ans : Array = [0, 0];
public function step(depth : uint) : void
{
if(depth > 0){
_ans = algo(depth);
_vx += _ans[0];
_vy += _ans[1];
}
x += _vx;
y += _vy;
// 逃がしはしない
if(x > 300){x = 299; _vx = 0;}
if(y > 300){y = 299; _vy = 0;}
if(x < 0){x = 1; _vx = 0;}
if(y < 0){y = 1; _vy = 0;}
}
// もっとも長い時間生き残れる加速度の組を返す
public function algo(depth : int) : Array
{
var ret : Array = [0.0, 0.0];
var maxt : Number = algoCore(x, y, _vx, _vy, 0, 0, 0, depth);
for(var theta : Number = 0;theta < 360;theta += STEPTHETA){
var ax : Number = Math.cos(theta * Math.PI / 180) * LIMA;
var ay : Number = Math.sin(theta * Math.PI / 180) * LIMA;
var t : Number = algoCore(x, y, _vx, _vy, ax, ay, 0, depth);
if(maxt < t){
maxt = t;
ret[0] = ax;
ret[1] = ay;
}
}
_val = maxt;
return ret;
}
private function algoCore(xx : Number, xy : Number, vx : Number, vy : Number, ax : Number, ay : Number, dt : int, depth : int) : Number
{
var mint : Number = 100;
// wall
var t : Number;
// bullet
/*
for each(var b : Bullet in _bullets){
var mybr2 : Number = (MYR + b.r) * (MYR + b.r);
var rxx : Number = xx - (b.x.x + b.v.x * dt);
var rxy : Number = xy - (b.x.y + b.v.y * dt);
var rvx : Number = vx - b.v.x;
var rvy : Number = vy - b.v.y;
for(t = 0;t < mint;t++){
if(rxx * rxx + rxy * rxy <= mybr2)break;
rvx += ax;
rvy += ay;
rxx += rvx;
rxy += rvy;
}
mint = t;
}
*/
var tsum : Number = 0;
var minv : Number = Number.MAX_VALUE;
for(var i : uint = 1;i <= _main._bitNum;i++){
var b : Bit = Bit(_main.getChildByName("bit_"+i));
// if(!b.hasEventListener(Event.ENTER_FRAME))continue;
var d2 : Number = (xx - b.tx) * (xx - b.tx) + (xy - b.ty) * (xy - b.ty);
if(d2 < 1)continue;
var u : Number = ((vx + ax) * (xx - b.tx) + (vy + ay) * (xy - b.ty)) / d2;
var vhx : Number = vx + ax - u * (xx - b.tx);
var vhy : Number = vy + ay - u * (xy - b.ty);
var vh : Number = (vhx * vhx + vhy * vhy); // * Math.sqrt(d2);
// tsum += 1/Math.sqrt(vh + 100);
if(vh < minv)minv = vh;
}
// _main._tf.text = "";
// mint -= tsum * 1500 / _main._bitNum;
mint -= 1 / Math.sqrt(minv + 10) * 300;
// _main._tf.appendText("" + mint + "\n");
/*
t = solveQPositive(ax/2, vx, xx - (MAXXX - MYR)); if(!isNaN(t) && t < mint)mint = t;
t = solveQPositive(ax/2, vx, xx - (MINXX + MYR)); if(!isNaN(t) && t < mint)mint = t;
t = solveQPositive(ay/2, vy, xy - (MAXXY - MYR)); if(!isNaN(t) && t < mint)mint = t;
t = solveQPositive(ay/2, vy, xy - (MINXY + MYR)); if(!isNaN(t) && t < mint)mint = t;
*/
if(vx + ax > 0){t = ((MAXXX - MYR) - xx) / (vx + ax); if(t < mint)mint = t;}
if(vx + ax < 0){t = ((MINXX + MYR) - xx) / (vx + ax); if(t < mint)mint = t;}
if(vy + ay > 0){t = ((MAXXY - MYR) - xy) / (vy + ay); if(t < mint)mint = t;}
if(vy + ay < 0){t = ((MINXY + MYR) - xy) / (vy + ay); if(t < mint)mint = t;}
// _main._tf.text = "";
// _main._tf.appendText("" + mint + "\n");
return mint;
}
// 0以上の最小解を求める
private static function solveQPositive(a : Number, b : Number, c : Number) : Number
{
if(a > -0.0001 && a < 0.0001){
return -c / b;
}else{
var D : Number = b * b - 4 * a * c;
if(D < 0)return Number.NaN;
var sqd : Number = Math.sqrt(D);
var a1 : Number = (-b - sqd) / (2 * a);
var a2 : Number = (-b + sqd) / (2 * a);
if(a < 0){
var d : Number = a1; a1 = a2; a2 = d;
}
if(a1 >= 0)return a1;
if(a2 >= 0)return a2;
return Number.NaN;
}
}
}