xxxxxxxxxx
220
class Bloop {
constructor(dna, location) {
this.location = location.copy();
this.velocity = createVector(0, 0, 0);
this.acceleration = createVector(0, 0, 0);
this.dna = dna;
this.maxspeed = map(this.dna.genes[0], 0, 1, 20, 0);
this.maxforce = 1;
this.health = map(this.dna.genes[0], 0, 1, 0, 100);
this.r = map(this.dna.genes[0], 0, 1, 0, 100);
this.eatingRange = 0;
this.death = false;
}
run(bloops, foods) {
this.flock(bloops);
this.update();
this.boarder();
this.seeking(foods);
this.display();
}
flock(bloops) {
let sep = this.separate(bloops).mult(sepFactor);
let ali = this.align(bloops).mult(aliFactor);
let coh = this.cohesion(bloops).mult(cohFactor);
this.applyForce(sep);
this.applyForce(ali);
this.applyForce(coh);
}
update() {
this.velocity.add(this.acceleration);
this.velocity.limit(this.maxspeed);
this.location.add(this.velocity);
this.acceleration.mult(0);
this.r = map(this.health, 0, 500, 0, 500);
if (this.health > 0) {
this.health -= 0.01;
} else {
this.health = 0;
}
if (foods.length === 0) {
for (let i = 0; i < 50; i++) {
foods.push(new Food(random(-worldX / 2, worldX / 2), random(-worldY / 2, worldY / 2), random(-worldZ / 2, worldZ / 2)));
}
}
if (this.r > 0) {
this.eatingRange = map(foods.length, 0, 50, 500, 300);
}
}
boarder() {
if (this.location.x > worldX / 2) this.velocity.x *= -1;
if (this.location.x < -worldX / 2) this.velocity.x *= -1;
if (this.location.y > worldY / 2) this.velocity.y *= -1;
if (this.location.y < -worldY / 2) this.velocity.y *= -1;
if (this.location.z > worldZ / 2) this.velocity.z *= -1;
if (this.location.z < -worldZ / 2) this.velocity.z *= -1;
}
seeking(foods) {
for (let i = foods.length - 1; i >= 0; i--) {
let otherFood = foods[i];
let d = p5.Vector.dist(this.location, otherFood.location);
if (d > 0 && d < this.eatingRange) {
let desired = p5.Vector.sub(otherFood.location, this.location);
desired.normalize();
desired.mult(d < 200 ? map(d, 0, 200, 50, 5 * this.maxspeed) : this.maxspeed);
if (d < 10) {
foods.splice(i, 1);
this.health += 20;
}
let steer = p5.Vector.sub(desired, this.velocity);
steer.limit(this.maxforce);
this.applyForce(steer);
// Draw connection line
stroke(255, 0, 255, 150); // Pink line with transparency
strokeWeight(10);
/*line(
this.location.x,
this.location.y,
this.location.z,
otherFood.location.x,
otherFood.location.y,
otherFood.location.z
);*/
beginShape();
vertex(
this.location.x,
this.location.y,
this.location.z
);
vertex(
otherFood.location.x,
otherFood.location.y,
otherFood.location.z
);
endShape()
}
}
}
applyForce(force) {
this.acceleration.add(force);
}
separate(bloops) {
let desiredSeparation = 100;
let steer = createVector(0, 0, 0);
let count = 0;
for (let other of bloops) {
let d = p5.Vector.dist(this.location, other.location);
if (d > 0 && d < desiredSeparation) {
let diff = p5.Vector.sub(this.location, other.location);
diff.normalize();
diff.div(d);
steer.add(diff);
count++;
}
}
if (count > 0) {
steer.div(count);
}
if (steer.mag() > 0) {
steer.normalize();
steer.mult(this.maxspeed);
steer.sub(this.velocity);
steer.limit(this.maxforce);
}
return steer;
}
align(bloops) {
let sum = createVector(0, 0, 0);
let count = 0;
let neighborDist = 200;
for (let other of bloops) {
let d = p5.Vector.dist(this.location, other.location);
if (d > 0 && d < neighborDist) {
sum.add(other.velocity);
count++;
}
}
if (count > 0) {
sum.div(count);
sum.normalize();
sum.mult(this.maxspeed);
let steer = p5.Vector.sub(sum, this.velocity);
steer.limit(this.maxforce);
return steer;
} else {
return createVector(0, 0, 0);
}
}
cohesion(bloops) {
let sum = createVector(0, 0, 0);
let count = 0;
let neighborDist = 200;
for (let other of bloops) {
let d = p5.Vector.dist(this.location, other.location);
if (d > 0 && d < neighborDist) {
sum.add(other.location);
count++;
}
}
if (count > 0) {
sum.div(count);
return this.seek(sum);
} else {
return createVector(0, 0, 0);
}
}
seek(target) {
let desired = p5.Vector.sub(target, this.location);
desired.normalize();
desired.mult(this.maxspeed);
let steer = p5.Vector.sub(desired, this.velocity);
steer.limit(this.maxforce);
return steer;
}
display() {
push();
translate(this.location.x, this.location.y, this.location.z);
fill(255, map(this.health, 0, 150, 0, 255), 200);
//noFill();
stroke(0,255,0, 200);
strokeWeight(1);
noStroke();
sphere(this.r*1.2);
pop();
}
}