xxxxxxxxxx
200
var mr = 0.01;
let mcounter = 0;
class Vehicle {
constructor(x, y, dna) {
this.acceleration = createVector(0, 0);
this.velocity = createVector(0, -2);
this.position = createVector(x, y);
this.r = 4;
this.maxspeed = 5;
this.maxforce = 0.5;
this.health = 1;
this.dna = [];
if (dna === undefined) {
// Food weight
this.dna[0] = random(-2, 2);
// Poison weight
this.dna[1] = random(-2, 2);
// Food perception
this.dna[2] = random(0, 100);
// Poision Percepton
this.dna[3] = random(0, 100);
} else {
// Mutation
this.dna[0] = dna[0];
if (random(1) < mr) {
this.dna[0] += random(-0.1, 0.1);
}
this.dna[1] = dna[1];
if (random(1) < mr) {
this.dna[1] += random(-0.1, 0.1);
}
this.dna[2] = dna[2];
if (random(1) < mr) {
this.dna[2] += random(-10, 10);
}
this.dna[3] = dna[3];
if (random(1) < mr) {
this.dna[3] += random(-10, 10);
}
}
}
// Method to update location
update() {
this.health -= 0.005;
// Update velocity
this.velocity.add(this.acceleration);
// Limit speed
this.velocity.limit(this.maxspeed);
this.position.add(this.velocity);
// Reset accelerationelertion to 0 each cycle
this.acceleration.mult(0);
if (mcounter >= 180){//closed
mcounter--;
}
else if(mcounter <= 180/TWO_PI) {
mcounter++;
}
else{
mcounter = 0;
}
}
applyForce(force) {
// We could add mass here if we want A = F / M
this.acceleration.add(force);
}
behaviors(good, bad) {
const steerG = this.eat(good, 0.2, this.dna[2]);
const steerB = this.eat(bad, -1, this.dna[3]);
steerG.mult(this.dna[0]);
steerB.mult(this.dna[1]);
this.applyForce(steerG);
this.applyForce(steerB);
}
clone() {
if (random(1) < 0.002) {
return new Vehicle(this.position.x, this.position.y, this.dna);
} else {
return null;
}
}
eat(list, nutrition, perception) {
let record = Infinity;
let closest = null;
for (let i = list.length - 1; i >= 0; i--) {
const d = this.position.dist(list[i]);
if (d < this.maxspeed) {
list.splice(i, 1);
this.health += nutrition;
} else {
if (d < record && d < perception) {
record = d;
closest = list[i];
}
}
}
// This is the moment of eating!
if (closest != null) {
return this.seek(closest);
}
return createVector(0, 0);
}
// A method that calculates a steering force towards a target
// STEER = DESIRED MINUS VELOCITY
seek(target) {
const desired = p5.Vector.sub(target, this.position); // A vector pointing from the location to the target
// Scale to maximum speed
desired.setMag(this.maxspeed);
// Steering = Desired minus velocity
const steer = p5.Vector.sub(desired, this.velocity);
steer.limit(this.maxforce); // Limit to maximum steering force
return steer;
//this.applyForce(steer);
}
dead() {
return (this.health < 0)
}
display() {
// Draw a triangle rotated in the direction of velocity
const angle = this.velocity.heading() + PI / 2;
push();
translate(this.position.x, this.position.y);
rotate(angle);
if (debug.checked()) {
strokeWeight(3);
stroke(0, 255, 0);
noFill();
line(0, 0, 0, -this.dna[0] * 25);
strokeWeight(2);
ellipse(0, 0, this.dna[2] * 2);
stroke(255, 0, 0);
line(0, 0, 0, -this.dna[1] * 25);
ellipse(0, 0, this.dna[3] * 2);
}
noStroke();
let mopen = map(mcounter,200,180/TWO_PI,185,180);
let mclose = map(mcounter,PI,180,TWO_PI+PI,PI);
fill('white');
arc(this.r, this.r, 30, 30, mopen, mclose, PIE);
fill('black');
circle(this.r,this.r-8,5);
pop();
}
boundaries() {
const d = 25;
let desired = null;
if (this.position.x < d) {
desired = createVector(this.maxspeed, this.velocity.y);
} else if (this.position.x > width - d) {
desired = createVector(-this.maxspeed, this.velocity.y);
}
if (this.position.y < d) {
desired = createVector(this.velocity.x, this.maxspeed);
} else if (this.position.y > height - d) {
desired = createVector(this.velocity.x, -this.maxspeed);
}
if (desired !== null) {
desired.normalize();
desired.mult(this.maxspeed);
const steer = p5.Vector.sub(desired, this.velocity);
steer.limit(this.maxforce);
this.applyForce(steer);
}
}
}