Watercolor wanderer forked from: 絵の具まぜまぜ(水彩風お絵かき)
also look http://wonderfl.net/c/8Tjs and other wonderfls from the same author : http://wonderfl.net/user/mtok
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.BlurFilter;
import flash.geom.Point;
import flash.geom.Rectangle;
import com.bit101.components.PushButton
public class RsakaneWaterColorClient extends Sprite
{
private var functions:Vector.<Function>;
private var rsakaneWaterColor:RsakaneWaterColor;
private var vehicle:Vehicle;
private var vehicle2:Vehicle;
private var vData1:Array;
private var vData2:Array;
private var bd:BitmapData;
private var blurFilter:BlurFilter;
private var rr:Rectangle;
private var pointOrigin:Point;
private var count:int;
private var bitmap:Bitmap;
public function RsakaneWaterColorClient()
{
bd = new BitmapData(465, 415, false);
rr = bd.rect;
blurFilter = new BlurFilter(1.05, 1.05, 1);
bitmap = new Bitmap(bd, "auto", true);
pointOrigin = new Point;
addChild(bitmap);
RsakaneWaterColor.bd = bd;
rsakaneWaterColor = addChild(new RsakaneWaterColor) as RsakaneWaterColor;
var sprite:Sprite = addChild(new Sprite) as Sprite;
vehicle = new Vehicle(sprite);
vehicle.edgeBehavior = Vehicle.BOUNCE;
var sprite2:Sprite = addChild(new Sprite) as Sprite;
vehicle2 = new Vehicle(sprite2);
vehicle2.edgeBehavior = Vehicle.BOUNCE;
vData1 = [new Point(vehicle.x, vehicle.y)];
vData2 = [new Point(vehicle2.x, vehicle2.y)];
addEventListener(Event.ENTER_FRAME, loop);
new PushButton(this,0,435,'unexpected',doRestart)
}
private function doRestart(e:Event):void
{
removeEventListener(Event.ENTER_FRAME, loop);
bd.dispose();
bd = new BitmapData(465, 415, true);
bitmap.bitmapData = bd;
RsakaneWaterColor.bd = bd;
addEventListener(Event.ENTER_FRAME, loop);
var pushButton:PushButton = e.target as PushButton;
pushButton.removeEventListener(MouseEvent.CLICK, doRestart);
pushButton.parent.removeChild(pushButton);
}
private function loop(e:Event):void
{
vehicle.wander();
vehicle.update();
rsakaneWaterColor.drawIt(vehicle.x, vehicle.y, vData1);
vehicle2.wander();
vehicle2.update();
rsakaneWaterColor.drawIt(vehicle2.x, vehicle2.y, vData2, 0xff0000);
if ( !((count++) % 10) )
{
trace("111111111" )
bd.applyFilter(bd, rr, pointOrigin , blurFilter);
}
}
}
}
import com.bit101.components.*;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import frocessing.color.ColorHSV;
class RsakaneWaterColor extends Sprite
{
private const DIFF:Number = 0.02;
public static var bd:BitmapData;
private var image:BitmapData;
private var buffer:Array = new Array();
private var i:int = 0;
private var r:int = 0;
private var g:int = 0;
private var b:int = 0;
//private var color:int = 0x00FFFF;
private var color:int = 0;
private var strengthSlider:HUISlider;
private var cslider:HUISlider;
private var factor:Number;
private var dd:int;
private var circle:Sprite;
private var _brushSize:Number;
public function RsakaneWaterColor()
{
addEventListener(Event.ADDED_TO_STAGE, init);
//Wonderfl.capture_delay( 30 );
circle = new Sprite();
brushSize = 10;
brushSize = 10;
setBrushSize(brushSize);
var button:PushButton = new PushButton(this, 365, 445, "clear", clear);
strengthSlider = new HUISlider(this, 180, 445, "strength");
strengthSlider.minimum = 0.1;
strengthSlider.maximum = 0.8;
strengthSlider.value = 0.8;
var cslider:Slider = new Slider();
cslider.y = 465 - cslider.height - 10;
cslider.x = 1;
cslider.addEventListener(Event.CHANGE, function():void { color = cslider.value; } );
//addChild(cslider);
var vbox:VBox = new VBox(this, 10,330);
factor = 0.15;
var hUISlider:HUISlider = new HUISlider(vbox, 10, 10, 'dt', onhhhfh);
hUISlider.minimum = factor - 0.14;
hUISlider.maximum = factor + 0.5;
hUISlider.value = factor;
dd = 1;
var hUISlider2:HUISlider = new HUISlider(vbox, 10, 30, 'dx', onDD);
hUISlider2.minimum = 0;
hUISlider2.maximum = 30;
hUISlider2.value = dd;
var hUISlider3:HUISlider = new HUISlider(vbox, 10, 30, 'brush', onBrush);
hUISlider3.minimum = 1;
hUISlider3.maximum = 30;
hUISlider3.value = brushSize;
}
private function onBrush(e:Event):void
{
brushSize = HUISlider(e.target).value;
setBrushSize(brushSize);
}
private function onDD(e:Event):void
{
dd = HUISlider(e.target).value;
}
private function onhhhfh(e:Event):void
{
var hUISlider:HUISlider = HUISlider(e.target);
factor = hUISlider.value;
}
private function init(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
clear();
stage.quality = "best";
//stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
//stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
public function clear(event:Event = null):void
{
bd.fillRect(bd.rect, 0xFFFFFF);
}
private function onMouseDown(event:MouseEvent):void
{
doPencilLow(mouseX, mouseY);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
}
private function onMouseUp(event:MouseEvent):void
{
doPencilRise();
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
}
private function onMouseMove(event:MouseEvent):void
{
//var mx:int = mouseX;
//var my:int = mouseY;
drawIt(mouseX,mouseY,buffer);
}
private function setBrushSize(size:Number):void
{
circle.graphics.clear();
circle.graphics.beginFill(0x0);
circle.graphics.drawCircle(size, size, size);
circle.graphics.endFill();
image = new BitmapData(size*2, size*2, true, 0x0);
image.draw(circle);
}
public function doPencilLow(xx:Number, yy:Number):void
{
buffer.push(new Point(xx, yy));
}
public function doPencilRise():void
{
buffer = new Array();
i = 0;
}
public function drawIt(mx:int, my:int, bufferParam:Array, colorParam:uint=0 ):void
{
mx = Math.max(0, mx);
my = Math.max(0, my);
mx = Math.min(bd.width, mx);
my = Math.min(bd.height, my);
bufferParam.push(new Point(mx, my));
if (bufferParam.length < 4) return;
bufferParam.shift();
var prev:Point = bufferParam[bufferParam.length-3];
var next:Point = bufferParam[bufferParam.length-2];
next.x = (prev.x + bufferParam[bufferParam.length-1].x) / 2;
next.y = (prev.y + bufferParam[bufferParam.length-1].y) / 2;
var dx:Number = next.x - prev.x;
var dy:Number = next.y - prev.y;
//var s:Number = 0.3 / Math.sqrt(dx * dx + dy * dy) / 2;
var s:Number = factor / Math.sqrt(dx * dx + dy * dy)
var colorA:ColorHSV = new ColorHSV();
var colorB:ColorHSV = new ColorHSV();
var colorC:ColorHSV = new ColorHSV();
var colorD:ColorHSV = new ColorHSV();
var colorE:ColorHSV = new ColorHSV();
colorE.value = colorParam;
for (var t:Number = 0.0; t < 1.0; t += s)
{
var tx:Number = prev.x + dx * t;
var ty:Number = prev.y + dy * t;
colorA.value = (tx - dd < 0) ? 0xFFFFFF : bd.getPixel(tx - dd, ty);
colorB.value = (bd.width <= tx + dd) ? 0xFFFFFF : bd.getPixel(tx + dd, ty);
colorC.value = (ty - dd < 0) ? 0xFFFFFF : bd.getPixel(tx, ty - dd);
colorD.value = (bd.height <= ty + dd) ? 0xFFFFFF : bd.getPixel(tx, ty + dd);
r = r + ((colorA.r + colorB.r + colorC.r + colorD.r) / 4 - r) * (1.0 - strengthSlider.value);
g = g + ((colorA.g + colorB.g + colorC.g + colorD.g) / 4 - g) * (1.0 - strengthSlider.value);
b = b + ((colorA.b + colorB.b + colorC.b + colorD.b) / 4 - b) * (1.0 - strengthSlider.value);
r = r + (colorE.r - r) * DIFF;
g = g + (colorE.g - g) * DIFF;
b = b + (colorE.b - b) * DIFF;
colorA.r = r;
colorA.g = g;
colorA.b = b;
image.threshold(image, image.rect, new Point(), "!=", 0x0, colorA.value32, 0xFF000000);
bd.copyPixels(image, image.rect, new Point(prev.x + dx * t, prev.y + dy * t));
}
i++;
}
public function get brushSize():Number
{
return _brushSize;
}
public function set brushSize(value:Number):void
{
_brushSize = value;
}
}
class Slider extends Sprite
{
private var bar:Sprite;
private var bd:BitmapData;
public var value:Number = 0x00FF00;
public function Slider()
{
var color:ColorHSV = new ColorHSV();
bd = new BitmapData(200, 30, false, 0xFF0000);
addChild(new Bitmap(bd));
for (var x:int = 0; x < bd.width; x++)
{
color.h = 360 * (x / bd.width);
bd.fillRect(new Rectangle(x, 0, 1, bd.height), color.value);
}
bar = new Sprite();
bar.graphics.beginFill(0x0);
bar.graphics.moveTo(0, 30);
bar.graphics.lineTo(-10, 40);
bar.graphics.lineTo(10, 40);
bar.graphics.endFill();
addChild(bar);
bar.x = 100;
onEnterFrame();
this.addEventListener(MouseEvent.CLICK, function():void { bar.x = mouseX; onEnterFrame(); } );
bar.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
private function onMouseDown(event:MouseEvent):void
{
bar.startDrag(false, new Rectangle(0, 0, bd.width, 0));
var stop:Function = function():void { bar.stopDrag(); removeEventListener(Event.ENTER_FRAME, onEnterFrame); };
stage.addEventListener(Event.MOUSE_LEAVE, stop);
stage.addEventListener(MouseEvent.MOUSE_UP, stop);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(event:Event = null):void
{
value = bd.getPixel(bar.x, 0);
this.dispatchEvent(new Event(Event.CHANGE));
}
}
class Vector2D {
private var _x:Number;
private var _y:Number;
public function Vector2D(x:Number = 0, y:Number = 0) {
_x = x;
_y = y;
}
/**
* draw
*/
public function draw(graphics:Graphics, color:uint):void {
graphics.lineStyle(0, color);
graphics.moveTo(0, 0);
graphics.lineTo(_x, _y);
}
public function get x():Number { return _x; }
public function set x(value:Number):void
{
_x = value;
}
public function get y():Number { return _y; }
public function set y(value:Number):void
{
_y = value;
}
/**
* 複製する
* @return
*/
public function clone():Vector2D {
return new Vector2D(_x, _y);
}
/**
* ベクトルをゼロに
* @return
*/
public function zero():Vector2D {
_x = _y = 0;
return this;
}
/**
* ベクトルがゼロか?
* @return
*/
public function isZero():Boolean {
return _x == 0 && _y == 0;
}
/**
* ベクトルの大きさを指定したサイズに
*/
public function set length(value:Number):void {
var a:Number = angle;
_x = Math.cos(a) * value;
_y = Math.sin(a) * value;
}
/**
* ベクトルの長さ
*/
public function get length():Number {
return Math.sqrt(lengthSQ);
}
/**
* ベクトルの長さの2乗
*/
public function get lengthSQ():Number {
return _x * _x + _y * _y;
}
public function get angle():Number {
return Math.atan2(_y, _x);
}
public function set angle(value:Number):void
{
var len:Number = length;
_x = Math.cos(value) * len;
_y = Math.sin(value) * len;
}
/**
* ベクトルを正規化する
* ベクトルが0の場合、結果を(1,0)とする
* @return
*/
public function normalize():Vector2D {
if (length == 0) {
_x = 1;
}else {
var len:Number = length;
_x /= len;
_y /= len;
}
return this;
}
/**
* ベクトルの大きさをmaxまでにカットする。
* @param max
* @return
*/
public function truncate(max:Number):Vector2D {
var len:Number = length;
if (len > max) {
length = max;
}
return this;
}
/**
* ベクトルの向きを逆に
* @return
*/
public function reverse():Vector2D {
_x = -_x;
_y = -_y;
return this;
}
/**
* ベクトルが正規化されているか?
* @return
*/
public function isNormalized():Boolean {
return length == 1.0;
}
/**
* ベクトル Vとの内積を求める
* @param v
* @return
*/
public function dotProduct(v:Vector2D):Number {
return _x * v._x + _y * v._y;
}
/**
* 内積からベクトルのなす角を求める -PI/2 ~ PI/2
* @param v1
* @param v2
* @return
*/
public static function angleBetween(v1:Vector2D, v2:Vector2D):Number {
if (!v1.isNormalized()) v1 = v1.clone().normalize();
if (!v2.isNormalized()) v2 = v2.clone().normalize();
return Math.acos(v1.dotProduct(v2));
}
/**
* ベクトルvが右にあるか左にあるか、
* @param v
* @return
*/
public function sign(v:Vector2D):int {
return this.perp.dotProduct(v) < 0 ? -1 : 1;
}
/**
* 直交するベクトル
*/
public function get perp():Vector2D {
return new Vector2D( -y, x);
}
public function distance(v:Vector2D):Number {
return Math.sqrt(distanceSQ(v));
}
public function distanceSQ(v:Vector2D):Number {
var dx:Number = v._x - _x;
var dy:Number = v._y - _y;
return dx * dx + dy * dy;
}
public function add(v:Vector2D):Vector2D {
return new Vector2D(_x + v._x, _y + v._y);
}
public function subtract(v:Vector2D):Vector2D {
return new Vector2D(_x - v._x, _y - v._y);
}
public function multiply(value:Number):Vector2D {
return new Vector2D(_x * value, _y * value);
}
public function divide(value:Number):Vector2D{
if (value == 0) {}//後で考える
return new Vector2D(_x / value, _y / value);
}
public function equals(v:Vector2D):Boolean {
return _x == v._x && _y == v._y;
}
public function toString():String {
return "[Vector2D( x:" + _x + ", y:" + _y + ", )]";
}
}
class Vehicle {
protected var _mass:Number = 1.0;
protected var _maxSpeed:Number = 10;
protected var _position:Vector2D;
protected var _velocity:Vector2D;
private var _edgeBehavior:Function;
public static const WRAP:String = "wrap";
public static const BOUNCE:String = "bounce";
private var _maxForce:Number = 1;
private var _steeringForce:Vector2D;
private var _arrivalThreshold:Number = 100;
private var _wanderAngle:Number = 0;
private var _wanderDistance:Number = 3;
private var _wanderRadius:Number = 10;
private var _wanderRange:Number = 3;
private var _avoidDistance:Number = 100;
private var _avoidBuffer:Number = 10;
private var _pathIndex:int = 0;
private var _pathThreshold:Number = 20;
private var _tooCloseDist:Number = 30;
private var _inSightDist:Number = 200;
private var sprite:Sprite;
public function get x():Number { return sprite.x; }
public function get y():Number { return sprite.y; }
public function Vehicle(sprite:Sprite=null) {
this.sprite = sprite;
_steeringForce = new Vector2D();
_position = new Vector2D();
_velocity = new Vector2D();
_edgeBehavior = wrap;
draw();
}
protected function draw():void
{
if (!sprite)
{
return;
}
var g:Graphics = sprite.graphics;
g.clear();
g.lineStyle(0);
g.moveTo(10, 0);
g.lineTo( -10, 5);
g.lineTo( -10, -5);
g.lineTo(10, 0);
}
public function update():void {
_steeringForce.truncate(maxForce);
_steeringForce = _steeringForce.divide(_mass);
_velocity = _velocity.add(_steeringForce);
_velocity.truncate(_maxSpeed);
_steeringForce.x = _steeringForce.y = 0;
_position = _position.add(_velocity);
_edgeBehavior();
x = position.x;
y = position.y;
sprite.rotation = _velocity.angle * 180 / Math.PI;
}
/**
* 跳ね返る
*/
private function bounce():void {
if (sprite.stage != null) {
var w:Number = sprite.stage.stageWidth;
var h:Number = sprite.stage.stageHeight;
if (position.x > w) {
position.x = w;
_velocity.x *= -1;
}else if(position.x < 0){
position.x = 0;
_velocity.x *= -1;
}
if (position.y > h) {
position.y = h;
_velocity.y *= -1;
}else if (position.y < 0) {
position.y = 0
_velocity.y *= -1;
}
}
}
/**
* 反対側に移動する。
*/
private function wrap():void {
if (sprite.stage != null) {
var w:Number = sprite.stage.stageWidth;
var h:Number = sprite.stage.stageHeight;
if (position.x > w) position.x = 0;
if (position.x < 0) position.x = w;
if ( position.y > h) position.y = 0;
if ( position.y < 0) position.y = h;
}
}
public function get edgeBehavior():String{
if ( _edgeBehavior == bounce) return Vehicle.BOUNCE;
if (_edgeBehavior == wrap) return Vehicle.WRAP;
return "";
}
public function set edgeBehavior(value:String):void{
switch(value) {
case Vehicle.BOUNCE:
_edgeBehavior = bounce;
break;
case Vehicle.WRAP:
default:
_edgeBehavior = wrap;
break;
}
}
public function get mass():Number { return _mass; }
public function set mass(value:Number):void
{
_mass = value;
}
public function get maxSpeed():Number { return _maxSpeed; }
public function set maxSpeed(value:Number):void
{
_maxSpeed = value;
}
public function get position():Vector2D { return _position; }
public function set position(value:Vector2D):void
{
_position = value;
x = _position.x;
y = _position.y;
}
public function get velocity():Vector2D { return _velocity; }
public function set velocity(value:Vector2D):void
{
_velocity = value;
}
public function set x(value:Number):void
{
sprite.x = value;
_position.x = value;
}
public function set y(value:Number):void
{
sprite.y = value;
_position.y = value;
}
public function get maxForce():Number { return _maxForce; }
public function set maxForce(value:Number):void
{
_maxForce = value;
}
public function get pathIndex():int { return _pathIndex; }
public function set pathIndex(value:int):void
{
_pathIndex = value;
}
public function get pathThreshold():Number { return _pathThreshold; }
public function set pathThreshold(value:Number):void
{
_pathThreshold = value;
}
public function get inSightDist():Number { return _inSightDist; }
public function set inSightDist(value:Number):void
{
_inSightDist = value;
}
public function get tooCloseDist():Number { return _tooCloseDist; }
public function set tooCloseDist(value:Number):void
{
_tooCloseDist = value;
}
/**
* Seek behavior
* @param target
*/
public function seek(target:Vector2D):void {
var desiredVelocity:Vector2D = target.subtract(_position);
desiredVelocity.normalize();
desiredVelocity = desiredVelocity.multiply(_maxSpeed);
var force:Vector2D = desiredVelocity.subtract(_velocity);
_steeringForce = _steeringForce.add(force);
}
public function flee(target:Vector2D):void {
var desiredVelocity:Vector2D = target.subtract(_position);
desiredVelocity.normalize();
desiredVelocity = desiredVelocity.multiply(_maxSpeed);
var force:Vector2D = desiredVelocity.subtract(_velocity);
_steeringForce = _steeringForce.subtract(force);
}
public function arrive(target:Vector2D):void {
var desiredVelocity:Vector2D = target.subtract(_position);
desiredVelocity.normalize();
var dist:Number = _position.distance(target);
if (dist > _arrivalThreshold) {
desiredVelocity = desiredVelocity.multiply(_maxSpeed);
}else {
//_arrivalThresholdまで近づいたらスピードダウン
desiredVelocity = desiredVelocity.multiply(_maxSpeed * dist / _arrivalThreshold);
}
var force:Vector2D = desiredVelocity.subtract(_velocity);
_steeringForce = _steeringForce.add(force);
}
public function pursue(target:Vehicle):void {
//現在位置からターゲットまでかかる時間
var lookAheadTime:Number = position.distance(target.position) / _maxSpeed;
var predictedTarget:Vector2D = target.position.add(target.velocity.multiply(lookAheadTime));
seek(predictedTarget);
}
public function evade(target:Vehicle):void {
//現在位置からターゲットまでかかる時間
var lookAheadTime:Number = position.distance(target.position) / _maxSpeed;
var predictedTarget:Vector2D = target.position.subtract(target.velocity.multiply(lookAheadTime));
flee(predictedTarget);
}
public function wander():void {
//進行方向から_wanderDistance進んだ位置をcenter
var center:Vector2D = velocity.clone().normalize().multiply(_wanderDistance);
//centerからのずれ
var offset:Vector2D = new Vector2D(0,0);
offset.length = _wanderRadius;
offset.angle = _wanderAngle;
_wanderAngle += Math.random() * _wanderRange - _wanderRange * 0.5;
var force:Vector2D = center.add(offset);
_steeringForce = _steeringForce.add(force);
}
public function avoid(circles:Array):void {
var i:int;
var len:int = circles.length;
var c:Circle;
var heading:Vector2D;
var feeler:Vector2D;
var projection:Vector2D;
var dist:Number;
var force:Vector2D;
for (i = 0; i < len; i++) {
heading = _velocity.clone().normalize();
c = circles[i] as Circle;
var difference:Vector2D = c.position.subtract(_position);
var dotProd:Number = difference.dotProduct(heading);
//進行方向前方にCircleがあるか?
if (dotProd > 0) {
feeler = heading.multiply(_avoidDistance);
projection = heading.multiply(dotProd);
dist = projection.subtract(difference).length;
//衝突するか?
if (dist < c.radius + _avoidBuffer && projection.length < feeler.length) {
force = heading.multiply(_maxSpeed);
force.angle += difference.sign(_velocity) * Math.PI / 2;
force = force.multiply(1.0 - projection.length / feeler.length);
_steeringForce = _steeringForce.add(force);
//スピードを落とす
_velocity = _velocity.multiply(projection.length / feeler.length);
}
}
}
}
public function followPath(path:Array, loop:Boolean = false):void {
var wayPoint:Vector2D = path[_pathIndex] as Vector2D;
if (wayPoint == null) return;
if (_position.distance(wayPoint) < _pathThreshold) {
if (_pathIndex >= path.length - 1) {
if (loop) {
_pathIndex = 0;
}
}else {
_pathIndex++;
}
}
if (_pathIndex >= path.length - 1 && !loop) {
arrive(wayPoint);
}else {
seek(wayPoint);
}
}
/**
* flocking
* @param vehicles
*/
public function flock(vehicles:Array):void {
var averageVelocity:Vector2D = _velocity.clone();
var averagePosition:Vector2D = new Vector2D();
var inSightCount:int = 0;
var len:int = vehicles.length;
var v:Vehicle;
/*
* inSightの範囲にある他のVehicleの平均位置と速度を求める。
* 近づきすぎている場合は、fleeする。
*/
for (var i:int = 0; i < len; i++) {
v = vehicles[i] as Vehicle;
if (v != this && inSight(v)) {
averageVelocity = averageVelocity.add(v.velocity);
averagePosition = averagePosition.add(v.position);
if (tooClose(v)) {
flee(v.position);
}
inSightCount++;
}
}
if (inSightCount > 0) {
averagePosition = averagePosition.divide(inSightCount);
averageVelocity = averageVelocity.divide(inSightCount);
//求めた平均位置に向かって移動する。
seek(averagePosition);
//速度を求めた平均速度へと変化させる方向に力を加える
_steeringForce.add(averageVelocity.subtract(_velocity));
}
}
public function tooClose(vehicle:Vehicle):Boolean {
return _position.distance(vehicle.position) < _tooCloseDist;
}
public function inSight(vehicle:Vehicle):Boolean {
if (_position.distance(vehicle.position) > _inSightDist) {
return false;
}
var heading:Vector2D = _velocity.clone().normalize();
var difference:Vector2D = vehicle.position.subtract(_position);
var dotProd:Number = difference.dotProduct(heading);
if (dotProd < 0) return false;
return true;
}
}
class Circle extends Sprite {
private var _radius:Number;
private var _color:uint;
public function Circle(radius:Number, color:uint = 0x000000) {
_radius = radius;
_color = color;
graphics.lineStyle(0, _color);
graphics.drawCircle(0, 0, _radius);
}
public function get radius():Number { return _radius; }
public function set radius(value:Number):void
{
_radius = value;
}
public function get position():Vector2D {
return new Vector2D(x, y);
}
}