avoidance function 軌跡の可視化
TODO 端だと当たる問題
/**
* Copyright keno42 ( http://wonderfl.net/user/keno42 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/kjXZ
*/
// forked from uwi's forked from: avoidance function
// forked from uwi's avoidance function
package {
import flash.display.*;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.events.*;
import flash.geom.Rectangle;
import flash.text.TextField;
// TODO 端だと当たる問題
[SWF(frameRate="30", backgroundColor="#000000")]
public class FlashTest extends Sprite {
private var _bullets : Array;
private var _ct : int;
private var _myx : Point;
private var _myv : Point;
private var _nhit : int;
private const LIMXY : Number = 3.0;
private const LIMVY : Number = 0.2;
private const LIMT : Number = 1.0;
private const NSAMPLE : int = 100;
private var _tf : TextField;
private var _bmpData : BitmapData = new BitmapData(232, 465, true, 0x0);
public function FlashTest() {
_myx = new Point(0, 0);
_myv = new Point(0, 0);
_bullets = [];
_ct = 0;
_nhit = 0;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
_tf = new TextField();
_tf.autoSize = "left";
_tf.text = "hit : " + _nhit;
_tf.textColor = 0xFFFFFF;
_tf.borderColor = 0xFFFFFF;
_tf.border = true;
var bmp:Bitmap = new Bitmap(_bmpData);
addChild(bmp);
bmp.x = 233;
addChild(_tf);
}
private function onEnterFrame(e : Event) : void
{
draw();
bmpDraw();
judge();
_ct++;
if(_ct % 2 == 0){
addBullet();
addBullet();
}
if(_ct % 1 == 0){
// TODO verbose
var maxdv : Number = LIMVY;
var mindv : Number = -LIMVY;
if(_myv.y > 0){
maxdv = Math.min((LIMXY - _myx.y) / LIMT, LIMVY);
}else{
mindv = Math.max((-LIMXY - _myx.y) / LIMT, -LIMVY);
}
// quasi-MC
var minav : Number = Number.MAX_VALUE;
var mina : Number = 0;
for(var j : int = 0;j < NSAMPLE;j++){
var a : Number = mindv + j * (maxdv - mindv) / NSAMPLE;
var av : Number = calcAvoidance(a);
if(av < minav){
minav = av;
mina = a;
}
}
_myv.y += mina;
}
// step
_myx.x += _myv.x;
_myx.y += _myv.y;
for each(var b : Bullet in _bullets){
b.x.x += b.v.x;
b.x.y += b.v.y;
}
}
private function removeBullet(i : int) : void
{
if(i < _bullets.length - 1){
_bullets[i] = _bullets.pop();
i--;
}else{
_bullets.pop();
}
}
private function judge() : void
{
for(var i : int = 0;i < _bullets.length;i++){
var b : Bullet = _bullets[i];
if(
(b.x.x - _myx.x) * (b.x.x - _myx.x) +
(b.x.y - _myx.y) * (b.x.y - _myx.y)
< 0.04){
_nhit++;
removeBullet(i);
continue;
}
if(b.x.x < -5.0 || b.x.x > 5.0 || b.x.y < -5.0 || b.x.y > 5.0){
removeBullet(i);
}
}
}
private function draw() : void
{
var g : Graphics = graphics;
g.clear();
// self
g.lineStyle(1.0);
g.beginFill(0x3333ff);
g.drawCircle(_myx.x * 50 + 465 / 2, _myx.y * 50 + 465 / 2, 5);
g.endFill();
// bullets
g.lineStyle(1.0);
g.beginFill(0xeeeeee);
for each(var b : Bullet in _bullets){
g.drawCircle(b.x.x * 50 + 465 / 2, b.x.y * 50 + 465 / 2, 5);
}
g.endFill();
_tf.text = "time : " + _ct + "\nhit : " + _nhit;
}
private function bmpDraw() : void
{
_bmpData.scroll(2, 0);
_bmpData.fillRect(new Rectangle(0, 0, 2, 465), 0x0);
_bmpData.draw(this, new Matrix(1, 0, 0, 1, -233, 0), null, null, new Rectangle(0, 0, 2, 465));
}
private function addBullet() : void
{
var x : Point = new Point(Math.random() * 1 - 5, Math.random() * 10 - 5);
var v : Point = new Point(Math.random() * 0.1 + 0.1, Math.random() * 0.3 - 0.15);
var b : Bullet = new Bullet();
b.x = x;
b.v = v;
_bullets.push(b);
}
private function calcAvoidance(dvy : Number) : Number
{
var vy : Point = new Point(0, _myv.y + dvy);
var ret : Number = 0.0;
for each(var b : Bullet in _bullets){
var vv : Point = b.v.subtract(vy);
var xx : Point = b.x.subtract(_myx);
var t : Number = mint(xx, vv);
if(t >= 0){
ret += f(mind2(xx, vv, t)) * 100 / (t + 10.0);
}
}
ret += dvy * dvy * 0.1 + vy.y * vy.y * 0.1;
return ret;
}
private function mint(x : Point, v : Point) : Number
{
if(v.x * v.x + v.y * v.y < 0.0001){
return 0.0;
}
return -(x.x * v.x + x.y * v.y) / (v.x * v.x + v.y * v.y);
}
private function mind2(x : Point, v : Point, t : Number) : Number
{
var xx : Number = x.x + v.x * t;
var yy : Number = x.y + v.y * t;
return xx * xx + yy * yy;
}
private function f(d2 : Number) : Number
{
// return d2 < 5 ? 1 : (d2 < 7 ? -0.1 : 0); // artistic
return d2 < 0.05 ? 1 : 0; // simplest
// return 1 / (1 + Math.exp(-(d2 - 5))); // sigmoid
// return Math.exp(-d2 / 2); // normal-distributed
}
}
}
import flash.geom.Point;
class Bullet
{
public var x : Point;
public var v : Point;
}