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

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;
}