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

flash on 2011-10-30

Get Adobe Flash player
by kihon 30 Oct 2011
    Embed
package
{
    import flash.display.Sprite;
    import flash.events.Event;
 
    public class Main extends Sprite
    {
        private var vehicles:Vector.<SteeredVehicle> = new Vector.<SteeredVehicle>();
        
        public function Main()
        {
            for (var i:int = 0; i < 30; i++)
            {
                vehicles.push(addChild(new SteeredVehicle(Math.random() * stage.stageWidth, Math.random() * stage.stageHeight)));
                vehicles[i].velocity = new Vector2D(Math.random() * 10 + 10, Math.random() * 10 + 10);
            }
        
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
 
        private function onEnterFrame(event:Event):void 
        {    
            for each (var vehicle:SteeredVehicle in vehicles)
            {
                vehicle.flock(vehicles);
                vehicle.update();
            }
        }
    }
}

class Vector2D
{
    public var x:Number;
    public var y:Number;

    public function Vector2D(x:Number, y:Number)
    {
        this.x = x;
        this.y = y;
    }

    public static function get ZERO():Vector2D
    {
        return new Vector2D(0, 0);
    }

    public function add(vec:Vector2D):Vector2D
    {
        this.x += vec.x;
        this.y += vec.y;

        return this;
    }

    public function subtract(vec:Vector2D):Vector2D
    {
        this.x -= vec.x;
        this.y -= vec.y;

        return this;
    }

    public function multiply(value:Number):Vector2D
    {
        this.x *= value;
        this.y *= value;

        return this;
    }

    public function divide(value:Number):Vector2D
    {
        this.x /= value;
        this.y /= value;

        return this;
    }

    public function get length():Number
    {
        return Math.sqrt(x * x + y * y);
    }

    public function set length(value:Number):void
    {
        var a:Number = angle;
        x = Math.cos(a) * value;
        y = Math.sin(a) * value;
    }

    public function dot(vec:Vector2D):Number
    {
        return this.x * vec.x + this.y * vec.y;
    }
    
    public function normalize(thickness:Number = 1.0):Vector2D
    {
        if (length == 0)
        {
            this.x = 1.0;
            return this;
        }

        var scale:Number = thickness / length;
        this.x *= scale;
        this.y *= scale;

        return this;
    }

    public function distance(vec:Vector2D):Number
    {
        return Math.sqrt(distanceSquared(vec));
    }

    public function distanceSquared(vec:Vector2D):Number
    {
        var tx:Number = this.x - vec.x;
        var ty:Number = this.y - vec.y;

        return tx * tx + ty * ty;
    }

    public function truncate(max:Number):Vector2D
    {
        length = Math.min(length, max);

        return this;
    }

    public function clone():Vector2D
    {
        return new Vector2D(x, y);
    }
    
    public function get angle():Number
    {
        return Math.atan2(y, x);
    }

    public function set angle(radian:Number):void
    {
        var len:Number = length;
        x = Math.cos(radian) * len;
        y = Math.sin(radian) * len;
    }
}

import flash.display.Sprite;

class Vehicle extends Sprite
{
    public static const WRAP:String = "wrap";
    public static const BOUNCE:String = "bounce";
    public var edgeBehavior:String = WRAP;
    public var velocity:Vector2D;
    public var maxSpeed:Number = 10.0;
    public var mass:Number = 1.0;

    public function Vehicle(x:Number, y:Number) 
    {
        this.x = x;
        this.y = y;
        velocity = Vector2D.ZERO;
    }

    public function update():void
    {
        velocity.truncate(maxSpeed);
        
        this.x += velocity.x;
        this.y += velocity.y;
        
        if (stage)
        {
            if (edgeBehavior == WRAP) wrap();
            else if (edgeBehavior == BOUNCE) bounce();
        }

        rotation = velocity.angle * 180 / Math.PI;
        draw();
    }
    
    private function wrap():void
    {
        if (this.x < 0)
        {
            this.x = stage.stageWidth - 1;
        }
        else if (stage.stageWidth <= this.x)
        {
            this.x = 0;
        }
        
        if (this.y < 0)
        {
            this.y = stage.stageHeight - 1;
        }
        else if (stage.stageHeight <= this.y)
        {
            this.y = 0;
        }
    }
    
    private function bounce():void
    {
        if (this.x < 0)
        {
            velocity.x = -velocity.x;
            this.x = 0;
        }
        else if (stage.stageWidth <= this.x)
        {
            velocity.x = -velocity.x;
            this.x = stage.stageWidth - 1;
        }
        
        if (this.y < 0)
        {
            velocity.y = -velocity.y;
            this.y = 0;
        }
        else if (stage.stageHeight <= this.y)
        {
            velocity.y = -velocity.y;
            this.y = stage.stageHeight - 1;
        }
    }

    public function get position():Vector2D
    {
        return new Vector2D(x, y);
    }

    protected function draw():void 
    {
        graphics.clear();
        graphics.lineStyle(2.0, 0x0);
        graphics.moveTo(5, 0);
        graphics.lineTo(-10, -5);
        graphics.lineTo(-10, 5);
        graphics.lineTo(5, 0);
    }
}

class SteeredVehicle extends Vehicle 
{
    public var force:Vector2D;
    public var maxForce:Number = 1.0;
    public var arriveDist:Number = 100.0;
    public var wanderDist:Number = 50.0;
    public var wanderRadius:Number = 20.0;
    public var wanderAngle:Number = 0.0;
    public var wanderAngleRange:Number = 0.5;
    public var pathIndex:int = 0;
    public var pathThreshold:Number = 10;
    public var tooCloseDist:Number = 30.0;
    public var inSightDist:Number = 120.0;

    public function SteeredVehicle(x:Number, y:Number) 
    {
        super(x, y);
        force = Vector2D.ZERO;
    }

    public function seek(target:Vector2D):void
    {
        var desiredVelocity:Vector2D = target.subtract(position);
        desiredVelocity.normalize().multiply(maxSpeed).subtract(velocity);
        force.add(desiredVelocity);
    }
    
    public function flee(target:Vector2D):void
    {
        var desiredVelocity:Vector2D = target.subtract(position);
        desiredVelocity.normalize().multiply(maxSpeed).subtract(velocity);
        force.subtract(desiredVelocity);
    }
    
    public function arrive(target:Vector2D):void
    {
        var desiredVelocity:Vector2D = target.subtract(position);
        var dist:Number = desiredVelocity.length;
        desiredVelocity.normalize().multiply(maxSpeed);
        if (dist < arriveDist) desiredVelocity.multiply(dist / arriveDist);
        desiredVelocity.subtract(velocity);
        force.add(desiredVelocity);
    }
    
    public function pursue(target:Vehicle):void
    {
        var frame:Number = target.position.distance(position) / maxSpeed;
        var predictedTarget:Vector2D = target.position.clone().add(target.velocity.clone().multiply(frame));
        seek(predictedTarget);
    }
    
    public function evade(target:Vehicle):void
    {
        var frame:Number = target.position.distance(position) / maxSpeed;
        var predictedTarget:Vector2D = target.position.clone().add(target.velocity.clone().multiply(frame));
        flee(predictedTarget);
    }
    
    public function wander():void
    {
        var center:Vector2D = velocity.clone().normalize().multiply(wanderDist);
        var offset:Vector2D = Vector2D.ZERO;
        offset.length = wanderRadius;
        offset.angle = wanderAngle;
        center.add(offset).subtract(velocity);
        force.add(center);
        
        wanderAngle += Math.random() * wanderAngleRange - wanderAngleRange / 2;
    }
    
    public function interpose(vehicle0:Vehicle, vehicle1:Vehicle):void
    {
        var midpoint:Vector2D = vehicle0.position.clone().add(vehicle1.position).divide(2);
        var frame:Number = position.distance(midpoint) / maxSpeed;
        
        var pos0:Vector2D = vehicle0.position.clone().add(vehicle0.velocity.multiply(frame));
        var pos1:Vector2D = vehicle1.position.clone().add(vehicle1.velocity.multiply(frame));
        
        midpoint = pos0.add(pos1).divide(2);
        arrive(midpoint);
    }
    
    public function followPath(path:Vector.<Vector2D>, loop:Boolean = false):void
    {
        try
        {
            var wayPoint:Vector2D = path[pathIndex];
        }
        catch (e:Error) { }
        if (wayPoint == null)
        {
            velocity = Vector2D.ZERO;
            return;
        }
        if (wayPoint.distance(position) < pathThreshold)
        {
            if (loop && pathIndex >= path.length - 1)
            {
                pathIndex = 0;
            }
            else
            {
                pathIndex++;
            }
        }
        
        if (!loop && pathIndex == path.length - 1)
        {
            arrive(wayPoint.clone());
        }
        else
        {
            seek(wayPoint.clone());
        }
    }
    
    public function flock(vehicles:Vector.<SteeredVehicle>):void
    {
        var avgVelocity:Vector2D = Vector2D.ZERO;
        var avgPosition:Vector2D = Vector2D.ZERO;
        var count:int = 0;
        
        for each (var vehicle:Vehicle in vehicles)
        {
            if (vehicle != this && inSight(vehicle))
            {
                avgVelocity.add(vehicle.velocity);
                avgPosition.add(vehicle.position);
                count++;
                
                if (position.distance(vehicle.position) < tooCloseDist)
                {
                    flee(vehicle.position);
                }
            }
        }
        if (count > 0)
        {
            avgVelocity.divide(count);
            avgPosition.divide(count);
            seek(avgPosition);
            force.add(avgVelocity.subtract(velocity));
        }
    }
    
    public function inSight(vehicle:Vehicle):Boolean
    {
        var diff:Vector2D = vehicle.position.subtract(position);
        if (diff.length > inSightDist) return false;
        var heading:Vector2D = velocity.clone().normalize();
        var dot:Number = diff.dot(heading);
        return dot > 0;
    }

    override public function update():void 
    {    
        force.truncate(maxForce);
        force.divide(mass);
        velocity.add(force);
        force = Vector2D.ZERO;
        super.update();
    }
}