スポンサーサイト

-------- | --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[ActionScript 3.0]渋滞シミュレーション

2007-08-05 | 17:06

ひとつの出口に向かう車の渋滞シミュレーション。
緑のボタンを押すと開始されます。

ランダムに配置された30個の矢印が、互いにぶつからないように一つの出口に向かっていきます。
アルゴリズムが単純なので、行儀がいいんだが頭悪いんだがよくわからない動きをしているものが見受けられます。
全ての他車を走査して距離計算を行っている部分のアルゴリズムは改良の余地あり。

package {
    import flash.display.*;
    import flash.events.*;
    import flash.text.*;

    [SWF(width="400", height="400", backgroundColor="#ffffff")]
        public class Traffic extends Sprite {
            private var _cars:Array = new Array();
            private static var COLLISION_THRESHOLD:Number = 30;

            public function Traffic() {
                var button:SimpleButton = new SimpleButton( );
                button.x = 360;
                button.y = 20;
                button.upState = createCircle( 0x00FF00, 10 );
                button.overState = createCircle( 0xFFFFFF, 12 );
                button.downState = createCircle( 0xCCCCCC, 10 );
                button.hitTestState = button.upState;
                button.addEventListener( MouseEvent.CLICK, function():void{init();} );
                addChild( button );

                addEventListener(Event.ENTER_FRAME, onEnterFrame);
            }

            private function init():void{
                for each(var c:Car in _cars){
                    removeChild(c);
                }
                _cars = new Array();

                for(var i:int = 0 ; i < 50 ; i++){
                    var car:Car = new Car();
                    car.x = Math.random()*400;
                    car.y = Math.random()*350 + 50;
                    if(i > 0){
                        while(minimumDistance(car) < COLLISION_THRESHOLD){
                            car.x = Math.random()*400;
                            car.y = Math.random()*350 + 50;
                        }
                    }
                    var vx:Number = 200 - car.x;
                    var vy:Number = 0 - car.y;
                    car.vx = Math.sqrt(Math.pow(vx,2) / (Math.pow(vx,2) + Math.pow(vy,2)));
                    car.vy = Math.sqrt(Math.pow(vy,2) / (Math.pow(vx,2) + Math.pow(vy,2))) * (-1);
                    if(car.x > 200)
                        car.vx *= (-1);
                    var degree:Number = Math.atan(car.vy/car.vx)*180/Math.PI;
                    if(car.vx < 0)
                        degree += 180;
                    car.rotation = degree;

                    addChild(car);
                    _cars.push(car);
                }
            }

            private function minimumDistance(car:Car):Number{
                var min:Number = 1000;
                for each(var c:Car in _cars){
                    var distance:Number = 
                        Math.sqrt(Math.pow(c.x - car.x,2) + Math.pow(c.y - car.y,2));
                    if(distance < min)
                        min = distance;
                }
                return min;
            }

            public function onEnterFrame(event:Event):void {
                var i:int = 0;
                for(i = 0 ; i < _cars.length ; i++){
                    var car:Car = _cars[i];
                    var stop:Boolean = false;
                    if(car.y > 0){
                        for(var j:int = 0 ; j < _cars.length; j++){
                            if(i != j){
                                var otherCar:Car = _cars[j];
                                var distance:Number = 
                                    Math.sqrt(Math.pow(otherCar.x - car.x,2) + 
                                            Math.pow(otherCar.y - car.y,2));
                                if(distance < COLLISION_THRESHOLD && otherCar.y < car.y){
                                    stop = true;
                                    break;
                                }
                            }
                        }
                    }
                    if(!stop){
                        car.x += car.vx;
                        car.y += car.vy;
                        if(car.y < 0){
                            _cars.splice(i,1);
                            removeChild(car);
                        }
                    }
                }
            }
            private function createCircle( color:uint, radius:Number ):Shape {
                var circle:Shape = new Shape( );
                circle.graphics.lineStyle( 1, 0x000000 );
                circle.graphics.beginFill( color );
                circle.graphics.drawCircle( 0, 0, radius );
                circle.graphics.endFill( );
                return circle;
            }

        }
}  
package {
    import flash.display.Sprite;

    public class Car extends Sprite {

        private var _vx:Number;
        private var _vy:Number;

        public function Car() {
            graphics.lineStyle(1, 0, 1);
            graphics.beginFill(0xff0000);
            graphics.moveTo(-10, -5);
            graphics.lineTo(0, -5);
            graphics.lineTo(0, -10);
            graphics.lineTo(10, 0);
            graphics.lineTo(0, 10);
            graphics.lineTo(0, 5);
            graphics.lineTo(-10, 5);
            graphics.lineTo(-10, -5);
            graphics.endFill();
        }

        public function get vx():Number{
            return _vx;
        }

        public function set vx(v:Number):void{
            _vx = v;
        }

        public function get vy():Number{
            return _vy;
        }

        public function set vy(v:Number):void{
            _vy = v;
        }
    }
} 
スポンサーサイト

Comment

Post a comment

Secret

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。