xxxxxxxxxx
170
class Vehicle {
constructor(x, y, col, r) {
this.position = createVector(x, y);
this.velocity = createVector(0, 0);
this.acceleration = createVector(0, 0);
this.r = r;
this.maxspeed = 4;
this.maxforce = 0.2;
this.color = col;
this.wanderTheta = 0;
this.currentPath = [];
this.paths = [this.currentPath];
}
wander() {
// creating projected wandering point
let wanderPoint = this.velocity.copy();
wanderPoint.setMag(100);
wanderPoint.add(this.position);
//displaying wandering point
// fill(255, 0, 0);
// noStroke();
// circle(wanderPoint.x, wanderPoint.y, 8);
//creating a circular path around my wandering point
let wanderRadius = 20;
// noFill();
// stroke(0);
// circle(wanderPoint.x, wanderPoint.y, wanderRadius * 2);
// line(this.position.x, this.position.y, wanderPoint.x, wanderPoint.y);
//the angle is relevant to the direction the vehicle's current velocity
let theta = this.wanderTheta + this.velocity.heading();
//finding the point on the circumference of the circular path, remember polar to cartesian coordinates
let x = wanderRadius * cos(theta);
let y = wanderRadius * sin(theta);
wanderPoint.add(x, y);
//displaying new wandering point on circular path and line to it
// fill(0, 255, 0);
// noStroke();
// circle(wanderPoint.x, wanderPoint.y, 10);
// stroke(0);
// line(this.position.x, this.position.y, wanderPoint.x, wanderPoint.y);
//the steering force here is equivalent to the desired velocity = target-position
let steer = wanderPoint.sub(this.position);
steer.setMag(this.maxForce);
this.applyForce(steer);
//random displacement along the circumference
let displaceRange = 0.3;
this.wanderTheta += random(-displaceRange, displaceRange);
}
//The pursue method is figuring out the predicted future position and calling the seek() method
pursue(vehicle) {
let target = vehicle.position.copy();
let prediction = vehicle.velocity.copy();
prediction.mult(10); //looking 10 steps ahead
target.add(prediction);
// fill(0, 255, 0);
// circle(target.x, target.y, 10); //to visualise the prediction
return this.seek(target);
}
evade(vehicle) {
let pursuit = this.pursue(vehicle);
pursuit.mult(-1);
return pursuit;
}
arrive(target) {
let desired = p5.Vector.sub(target, this.position);
let distance = desired.mag();
let r = 100; //our raduis for threshold
if (distance < r) {
let m = map(distance, 0, r, 0, this.maxspeed);
desired.setMag(m);
} else {
desired.setMag(this.maxspeed);
}
let steer = p5.Vector.sub(desired, this.velocity);
steer.limit(this.maxforce);
return steer;
}
seek(target) {
let desired = p5.Vector.sub(target, this.position);
desired.setMag(this.maxspeed);
let steer = p5.Vector.sub(desired, this.velocity);
steer.limit(this.maxforce);
return steer;
}
flee(target) {
return this.seek(target).mult(-1);
}
applyForce(force) {
this.acceleration.add(force);
}
update() {
this.velocity.add(this.acceleration);
this.velocity.limit(this.maxspeed);
this.position.add(this.velocity);
this.acceleration.set(0,0);
this.currentPath.push(this.position.copy());
}
show() {
let angle = this.velocity.heading();
fill(this.color);
stroke(0);
push();
translate(this.position.x, this.position.y);
rotate(angle);
triangle(-this.r, -this.r / 2, -this.r, this.r / 2, this.r, 0);
pop();
push();
for (let path of this.paths) {
beginShape();
noFill();
stroke(255);
for (let v of path) {
vertex(v.x, v.y);
}
endShape();
}
pop();
}
edges() {
let cross_edge = false;
if (this.position.x > width + this.r) {
this.position.x = -this.r;
cross_edge = true;
} else if (this.position.x < -this.r) {
this.position.x = width + this.r;
cross_edge = true;
}
if (this.position.y > height + this.r) {
this.position.y = -this.r;
cross_edge = true;
} else if (this.position.y < -this.r) {
this.position.y = height + this.r;
cross_edge = true;
}
if (cross_edge == true) {
this.currentPath = [];
this.paths.push(this.currentPath);
}
}
}