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

forked from: シューティングっぽい動きで避ける

マウスカーソルでuwiさんのプログラムと勝負!
マウスカーソルは赤円で表示されます
勝敗判定とかはないので各自心の中で行ってください
/**
 * Copyright Nicolas ( http://wonderfl.net/user/Nicolas )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/25aZ
 */

// forked from uwi's シューティングっぽい動きで避ける
// forked from uwi's forked from: avoidance function
// forked from uwi's avoidance function

//マウスカーソルでuwiさんのプログラムと勝負!
//マウスカーソルは赤円で表示されます
//勝敗判定とかはないので各自心の中で行ってください
package {
    import com.flashdynamix.utils.SWFProfiler;
    import flash.display.*;
    import flash.geom.*;
    import flash.events.*;
    import flash.filters.*;
    import flash.text.TextField;
    import flash.ui.Mouse;
    
    // frameRate="60"は本気モード
    // TODO アルゴリズムの抜けを修正
    [SWF(frameRate="30", backgroundColor="#660000")]
    public class FlashTest extends Sprite {
        private var _bullets : Array;
        private var _ct : int;
        private var _myx : Point;
        private var _nhit : int;
        private var _myx2 : Point;
	private var _nhit2 : int;
        
        private const R_BULLET : Number = 30.0;
        private const R_SELF : Number = 5.0;
        private const INFD : Number = Math.pow((R_BULLET + R_SELF), 2);
        
        private var _space : BitmapData;
        private var _bmdbullet : BitmapData;
        private var _bmdself : BitmapData;
        private var _bmdself2 : BitmapData;
        
        private var _tf : TextField;
        private var _tf2 : TextField;
        private const P0 : Point = new Point(0, 0);
        private const WEAKBLUR : BitmapFilter = new BlurFilter(3.0, 3.0);
       
        public function FlashTest() {
            Wonderfl.capture_delay(5);
            SWFProfiler.init(this);
            
            // 宇宙
            _space = new BitmapData(400, 465, false, 0x000000);
            var bmpspace : Bitmap = new Bitmap(_space);
            addChild(bmpspace);
            
            // 弾描画
            var shBullet : Shape = new Shape();
            var gb : Graphics = shBullet.graphics;
            gb.lineStyle(0.0, 0x999999);
            var mat : Matrix = new Matrix();
            mat.createGradientBox(R_BULLET * 2, R_BULLET * 2, 0, 0, 0);
            gb.beginGradientFill("radial", [0xffffff, 0xaaaaaa], [1, 1], [0x00, 0xff], mat);
            gb.drawCircle(R_BULLET, R_BULLET, R_BULLET);
            gb.endFill();
            _bmdbullet = new BitmapData(R_BULLET * 2, R_BULLET * 2, true, 0x00000000);
            _bmdbullet.draw(shBullet);
            _bmdbullet.applyFilter(_bmdbullet, _bmdbullet.rect, P0, WEAKBLUR);
            
            // 自機描画(COM)
            var shSelf : Shape = new Shape();
            var gs : Graphics = shSelf.graphics;
            gs.lineStyle(1.0, 0x0000ff);
            gs.beginFill(0x3333ff);
            gs.drawCircle(R_SELF, R_SELF, R_SELF);
            gs.endFill();
            _bmdself = new BitmapData(R_SELF * 2, R_SELF * 2, true, 0x00000000);
            _bmdself.draw(shSelf);
            
            //自機描画(マウスカーソル)
            var shSelf2 : Shape = new Shape();
            var gs2 : Graphics = shSelf2.graphics;
            gs2.lineStyle(1.0, 0xff0000);
            gs2.beginFill(0xff3333);
            gs2.drawCircle(R_SELF, R_SELF, R_SELF);
            gs2.endFill();
            _bmdself2 = new BitmapData(R_SELF * 2, R_SELF * 2, true, 0x00000000);
            _bmdself2.draw(shSelf2);
            
            
            _myx = new Point(200, 400);
            _myx2 = new Point(200, 400);
            _bullets = [];
            _ct = 0;
            _nhit = 0;
            //addEventListener(Event.ENTER_FRAME, onEnterFrame);
            
            _tf = new TextField();
            _tf.autoSize = "left";
            _tf.textColor = 0xffffff;
            _tf.borderColor = 0xffffff;
            _tf.border = true;
            _tf.x = 400;
            addChild(_tf);
            
            _tf2 = new TextField();
            _tf2.text = "Click to start"
            _tf2.textColor = 0xffffff;
            _tf2.x = 200;
	    _tf2.y = 200;
            addChild(_tf2);
			
	    stage.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void {
		_tf2.visible = false;
		Mouse.hide();
		addEventListener(Event.ENTER_FRAME, onEnterFrame);
	    });
            
        }
        
        private var _gct : int = 0; // デバッグ用
        
        private var _ans : int = 0;
        
        private function onEnterFrame(e : Event) : void
        {
            //画面内にマウスカーソルがあるときのみ位置を更新
            if (mouseX >= 0 && mouseX < 400 && mouseY >= 0 && mouseY < 465) {
		_myx2.x = mouseX;
                _myx2.y = mouseY;
	    }

            draw();
            judge();
            
            _ct++;
            if(_ct % 3 == 0){
                addBullet();
//                addBullet();
//                addBullet();
            }
            
            if(_ct % 3 == 0){
                _ans = calcAvoidanceAtRoot(_myx, 1);
            }
            
            // step
            _myx.x += PTN_MOVE[_ans][0];
            _myx.y += PTN_MOVE[_ans][1];
            if(_myx.x < 0 || _myx.x >= 400 || _myx.y < 0 || _myx.y >= 465){
                _myx.x -= PTN_MOVE[_ans][0];
                _myx.y -= PTN_MOVE[_ans][1];
            }
            
            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)
                    < INFD){
                        _nhit++;
                        removeBullet(i);
                        continue;
                }
                if (
		    (b.x.x - _myx2.x) * (b.x.x - _myx2.x) + 
                    (b.x.y - _myx2.y) * (b.x.y - _myx2.y)
	            < INFD) {
			_nhit2++;
                        removeBullet(i);
                        continue;
		}
                if(b.x.x < 0 - R_BULLET || b.x.x > 400 + R_BULLET || b.x.y < 0 - R_BULLET || b.x.y > 465 + R_BULLET){
                    removeBullet(i);
                }
            }
        }
        
        private function draw() : void
        {
            _space.lock();
            _space.fillRect(_space.rect, 0x000000);

            // self
            _space.copyPixels(_bmdself, _bmdself.rect,
                new Point(_myx.x - R_SELF, _myx.y - R_SELF));
            
            _space.copyPixels(_bmdself2, _bmdself2.rect,
                new Point(_myx2.x - R_SELF, _myx2.y - R_SELF));
            
            // bullets
            for each(var b : Bullet in _bullets){
                _space.copyPixels(_bmdbullet, _bmdbullet.rect,
                    new Point(b.x.x - R_BULLET, b.x.y - R_BULLET));
            }
            _space.unlock();
            
            _tf.text = "time : \n" + _ct + "\n\nhit(Red) : \n" + _nhit2 + "\n\nhit(blue) : \n" + _nhit;
        }
        
        private function addBullet() : void
        {
            var x : Point = new Point(Math.random() * 400, 0);
            var v : Point = new Point(Math.random() * 8 - 4, Math.random() * 5 + 5);
            var b : Bullet = new Bullet();
            b.x = x;
            b.v = v;
            _bullets.push(b);
        }
        
        /*
        // 低速移動・高速移動
        public static const PTN_MOVE : Array = [
            [0, 0], 
            [3, 0], [6, 0],
            [0, 3], [0, 6],
            [-3, 0], [-6, 0],
            [0, -3], [0, -6],
            [2, 2], [4, 4],
            [-2, 2], [-4, 4],
            [-2, -2], [-4, -4],
            [2, -2], [4, -4]
            ];
            */
        // 高速移動オンリー
        public static const PTN_MOVE : Array = [
            [0, 0], 
            [6, 0],
            [0, 6],
            [-6, 0],
            [0, -6],
            [4, 4],
            [-4, 4],
            [-4, -4],
            [4, -4]
            ];
        
        // 回避アルゴリズム
        // @param x 回避者位置
        // @param depth 読むパスの深さ
        public function calcAvoidanceAtRoot(x : Point, depth : int) : int
        {
            var i : int;
            var t : Number;
            var mincs : Array = new Array(PTN_MOVE.length);
            // 壁への衝突
            for(i = 0;i < PTN_MOVE.length;i++){
                var minc : Number = Number.MAX_VALUE;
                if(PTN_MOVE[i][0] > 0){
                    t = (400 - x.x) / PTN_MOVE[i][0];
                    if(t < minc)minc = t;
                }else if(PTN_MOVE[i][0] < 0){
                    t = (x.x) / -PTN_MOVE[i][0];
                    if(t < minc)minc = t;
                }
                if(PTN_MOVE[i][1] > 0){
                    t = (465 - x.y) / PTN_MOVE[i][1];
                    if(t < minc)minc = t;
                }else if(PTN_MOVE[i][1] < 0){
                    t = (x.y) / -PTN_MOVE[i][1];
                    if(t < minc)minc = t;
                }
                mincs[i] = minc;
            }
            
            // 弾への衝突
            for each(var b : Bullet in _bullets){
                var rx : Point = b.x.subtract(x);
                for(i = 0;i < PTN_MOVE.length;i++){
                    var rv : Point = new Point(
                        b.v.x - PTN_MOVE[i][0],
                        b.v.y - PTN_MOVE[i][1]
                        ); // rvはメモ化できそう
                    t = mint(rx, rv);
                    if(t > 0){
                        var d2 : Number = mind2(rx, rv, t);
                        if(d2 < INFD){
                            t -= Math.sqrt((INFD - d2) / rv.length);
                            _gct++;
                            if(t < mincs[i])mincs[i] = t;
                        }
                    }
                }
            }
            
            var mc : Number;
            var maxminc : Number = 0.0;
            var maxmini : int = 0; // 詰みの防止
//            var maxmini : int = Math.random() * PTN_MOVE.length; // 詰みの防止
            for(i = 0;i < PTN_MOVE.length;i++){
                var maxt : int = i == 0 ? 0 : int(mincs[i]) - 1;
                if(maxt <= 0)continue;
                if(depth == 0){
                    mc = mincs[i] + calcAvoidanceAtLeaf(
                        new Point(x.x + PTN_MOVE[i][0] * maxt, x.y + PTN_MOVE[i][1] * maxt),
                        maxt
                        );
                }else{
                    mc = mincs[i] + calcAvoidanceAtNode(
                        new Point(x.x + PTN_MOVE[i][0] * maxt, x.y + PTN_MOVE[i][1] * maxt),
                        maxt,
                        depth - 1
                        );
                }
                if(mc > maxminc){
                    maxminc = mc;
                    maxmini = i;
                }
            }
            return maxmini;
        }
        
        private function calcAvoidanceAtNode(x : Point, delay : int, depth : int) : Number
        {
            var i : int;
            var t : Number;
            var mincs : Array = new Array(PTN_MOVE.length);
            // 壁への衝突
            for(i = 0;i < PTN_MOVE.length;i++){
                var minc : Number = Number.MAX_VALUE;
                if(PTN_MOVE[i][0] > 0){
                    t = (400 - x.x) / PTN_MOVE[i][0];
                    if(t < minc)minc = t;
                }else if(PTN_MOVE[i][0] < 0){
                    t = (x.x) / -PTN_MOVE[i][0];
                    if(t < minc)minc = t;
                }
                if(PTN_MOVE[i][1] > 0){
                    t = (465 - x.y) / PTN_MOVE[i][1];
                    if(t < minc)minc = t;
                }else if(PTN_MOVE[i][1] < 0){
                    t = (x.y) / -PTN_MOVE[i][1];
                    if(t < minc)minc = t;
                }
                mincs[i] = minc;
            }
            
            // 弾への衝突
            for each(var b : Bullet in _bullets){
                var rx : Point = b.x.subtract(x);
                rx.x += b.v.x * delay;
                rx.y += b.v.y * delay;
                for(i = 0;i < PTN_MOVE.length;i++){
                    var rv : Point = new Point(
                        b.v.x - PTN_MOVE[i][0],
                        b.v.y - PTN_MOVE[i][1]
                        );
                    t = mint(rx, rv);
                    if(t > 0){
                        var d2 : Number = mind2(rx, rv, t);
                        if(d2 < INFD){
                            t -= Math.sqrt((INFD - d2) / rv.length);
                            _gct++;
                            if(t < mincs[i])mincs[i] = t;
                        }
                    }
                }
            }
            
            var mc : Number;
            var maxminc : Number = 0.0;
            for(i = 0;i < PTN_MOVE.length;i++){
                var maxt : int = i == 0 ? 0 : int(mincs[i]) - 1;
                if(maxt <= 0)continue;
                if(depth == 0){
                    mc = mincs[i] + calcAvoidanceAtLeaf(
                        new Point(x.x + PTN_MOVE[i][0] * maxt, x.y + PTN_MOVE[i][1] * maxt),
                        delay + maxt
                        );
                }else{
                    mc = mincs[i] + calcAvoidanceAtNode(
                        new Point(x.x + PTN_MOVE[i][0] * maxt, x.y + PTN_MOVE[i][1] * maxt),
                        delay + maxt,
                        depth - 1
                        );
                }
                if(mc > maxminc)maxminc = mc;
            }
            return maxminc;
        }
        
        private function calcAvoidanceAtLeaf(x : Point, delay : int) : Number
        {
            var i : int;
            var t : Number;
            var minc : Number = Number.MAX_VALUE;
            // 壁への衝突
            for(i = 0;i < PTN_MOVE.length;i++){
                if(PTN_MOVE[i][0] > 0){
                    t = (400 - x.x) / PTN_MOVE[i][0];
                    if(t < minc)minc = t;
                }else if(PTN_MOVE[i][0] < 0){
                    t = (x.x) / -PTN_MOVE[i][0];
                    if(t < minc)minc = t;
                }
                if(PTN_MOVE[i][1] > 0){
                    t = (465 - x.y) / PTN_MOVE[i][1];
                    if(t < minc)minc = t;
                }else if(PTN_MOVE[i][1] < 0){
                    t = (x.y) / -PTN_MOVE[i][1];
                    if(t < minc)minc = t;
                }
            }
            // 弾への衝突
            for each(var b : Bullet in _bullets){
                var rx : Point = b.x.subtract(x);
                rx.x += b.v.x * delay;
                rx.y += b.v.y * delay;
                for(i = 0;i < PTN_MOVE.length;i++){
                    var rv : Point = new Point(
                        b.v.x - PTN_MOVE[i][0],
                        b.v.y - PTN_MOVE[i][1]
                        );
                    t = mint(rx, rv);
                    if(t > 0){
                        var d2 : Number = mind2(rx, rv, t);
                        if(d2 < INFD){
                            t -= Math.sqrt((INFD - d2) / rv.length);
                            _gct++;
                            if(t < minc)minc = t;
                        }
                    }
                }
            }
            return minc;
        }
        
        private function mint(x : Point, v : Point) : Number
        {
            if(v.x * v.x + v.y * v.y < 0.01){
                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;
        }
    }
}

import flash.geom.Point;

class Bullet
{
    public var x : Point;
    public var v : Point;
}