Autonomous Agent - flow field following-practice - 2013-9-4
@author javid jafari
/**
* Copyright J.J ( http://wonderfl.net/user/J.J )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/amxL
*/
package {
import flash.filters.GlowFilter;
import flash.text.TextFieldAutoSize;
import flash.text.TextField;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Sprite;
/*
@author javid jafari
*/
public class FieldFlow extends Sprite {
public var w : int;
public var h : int;
private var canvas : Bitmap;
private var field : FField;
private var vs : Vector.<Vehicle>
private var t : TextField;
public function FieldFlow() {
stage.frameRate=60
w=this.stage.stageWidth
h=this.stage.stageHeight
canvas=new Bitmap()
canvas.bitmapData=new BitmapData(w, h,false,0x000000)
canvas.smoothing=true
addChild(canvas);
t=new TextField()
t.selectable=false
t.textColor=0xffffff
t.filters=[new GlowFilter(0x000000)]
t.autoSize=TextFieldAutoSize.LEFT
t.text="press anykey to change fields\n"
t.appendText("click on stage to add new vehicle")
addChild(t)
field=new FField(20,canvas)
vs=new Vector.<Vehicle>()
for (var i : int = 0; i < 20; i++) {
var v:Vehicle=new Vehicle(Math.random()*w+10, Math.random()*h+10, 10)
vs.push(v)
addChild(v)
}
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown)
addEventListener(Event.ENTER_FRAME, loop)
stage.addEventListener(MouseEvent.MOUSE_UP, onUp)
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeydown)
}
private function onKeydown(event : KeyboardEvent) : void {
field.reGen()
}
private function onUp(event : MouseEvent) : void {
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseDown)
}
private function loop(event : Event) : void {
for (var i : int = 0; i < vs.length; i++) {
var v:Vehicle=vs[i];
v.update()
v.flow(field)
if(v.isDead){removeChild(v),vs.splice(i, 1)}
}
}
private function mouseDown(event : MouseEvent) : void {
var v:Vehicle=new Vehicle(mouseX, mouseY, 10)
vs.push(v)
addChild(v)
if(stage.hasEventListener(MouseEvent.MOUSE_MOVE)==false) stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseDown);
}
}
}
import flash.display.Shape;
import frocessing.math.PerlinNoise;
import flash.geom.Matrix;
import flash.display.BitmapData;
import flash.geom.Vector3D;
import flash.display.Bitmap;
class FField {
private var cols:int,rows:int;
private var resolution:int;
private var field:Vector.<Vector.<Vector3D>>;
private var canvas:BitmapData
private var m:Matrix
private var s:Shape
private var perlin:PerlinNoise
public function FField(_r:int,con:Bitmap):void{
perlin=new PerlinNoise()
canvas=con.bitmapData
resolution=_r;
cols=con.width/resolution;
rows=con.height/resolution;
m=new Matrix()
field=new Vector.<Vector.<Vector3D>>()
s=new Shape()
with(s.graphics){
lineStyle(1,0x808080)
moveTo(0, 0)
lineTo(15, 0)
moveTo(15, 0)
lineTo(15-4, -2)
moveTo(15, 0)
lineTo(15-4, 2)
}
init()
display()
}
private function init():void{
var center:Vector3D=new Vector3D(800/2,200/2)
for (var i : int = 0; i <= cols; i++) {
field.push(new Vector.<Vector3D>())
for (var j : int = 0; j <=rows; j++) {
/*var v:Vector3D=new Vector3D(i*resolution,j*resolution);
v=v.subtract(center)
v.scaleBy(-1)*/
var angle:Number=perlin.noise(i/10,j/10)*(Math.PI*2)
var v:Vector3D=new Vector3D(Math.cos(angle),Math.sin(angle))
field[i].push(v);
}
}}
private function display():void{
for (var i : int = 0; i <=cols; i++) {
for (var j : int = 0; j <=rows; j++) {
drawVec(field[i][j], i*resolution, j*resolution, 2)
}
}}
public function lookUp(lc:Vector3D):Vector3D{
var column:int=int(lc.x/resolution);
var row:int=int(lc.y/resolution);
if(column<0 || column>cols || row<0 || row>rows) return null;
else return field[column][row].clone();
}
public function reGen():void{
canvas.fillRect(canvas.rect, 0)
perlin.noiseSeed(int(Math.random()*200))
field.length=0
init()
display()
}
private function drawVec(_v:Vector3D,x:Number,y:Number,scl:Number):void{
var v:Vector3D=_v.clone()
var angle:Number=Math.atan2(v.y,v.x);
v.normalize()
var len:Number=v.length
m.identity()
m.scale(len, len)
m.rotate(angle)
m.tx=x;
m.ty=y;
canvas.draw(s,m)
}
}
import flash.display.Sprite;
class Vehicle extends Sprite{
private var loc:Vector3D
private var acc:Vector3D
private var vel:Vector3D
private var mass:Number=1
public var isDead:Boolean=false
public function Vehicle (_x:Number,_y:Number,r:Number):void{
this.rotation+=90
loc=new Vector3D(_x,_y);
acc=new Vector3D()
vel=new Vector3D()
with(this.graphics){
lineStyle(0,0,0)
beginFill(0x990000);
moveTo(r/2, -r);
graphics.lineTo(r, r);
graphics.lineTo(0, r);
graphics.lineTo(r/2, -r);
}
}
public function update():void{
vel=vel.add(acc);
loc=loc.add(vel);
acc.scaleBy(0);
var angle:Number=Math.atan2(vel.y, vel.x)
this.rotation=((180/Math.PI)*angle)+90
this.x=loc.x
this.y=loc.y
}
public function applyForce(f:Vector3D):void{
var force:Vector3D=f.clone()
force.scaleBy(1/mass)
acc=acc.add(force);
}
public function flow(field:FField):void{
var des:Vector3D=field.lookUp(loc);
if(des==null) { isDead=true;return;}
des.scaleBy(5);
var steer:Vector3D=des.subtract(vel);
steer=limit(steer, .1);
applyForce(steer)
}
private function limit(v:Vector3D,lim:Number):Vector3D{
if(v.length>lim) v.normalize() , v.scaleBy(lim);
return v;
}
}