class Koi {
constructor(startX, startY, color) {
this.color = color[randInt(0, 4)];
this.offsetX = random(-100, 100);
this.offsetY = random(-100, 100);
this.position = p5Instance.createVector(
startX + this.offsetX,
startX + this.offsetY
);
this.maxForce = maxForce;
this.maxSpeed = maxSpeed;
this.velocity = P5.Vector.random2D();
this.acceleration = P5.Vector.random2D();
this.acceleration.div(10);
this.baseSize = randInt(8, 12);
this.bodyLength = this.baseSize * 2;
this.body = Array.from(
{
length: this.bodyLength,
},
() => {
return {
...this.position,
};
}
);
}
edges() {
if (this.position.x > width + 50) {
this.position.x = -50;
} else if (this.position.x < -50) {
this.position.x = width + 50;
}
if (this.position.y > height + 50) {
this.position.y = -50;
} else if (this.position.y < -50) {
this.position.y = height + 50;
}
}
// this function returns the steerring force
//* Calculate the steering force
calculateSteeringForce(kois, forceType) {
let perceptionRadius = perceptionR;
let steering = p5Instance.createVector();
let total = 0;
for (let eachKoi of kois) {
let distanceToCurrentKoi = p5Instance.dist(
this.position.x,
this.position.y,
eachKoi.position.x,
eachKoi.position.y
);
if (eachKoi != this && distanceToCurrentKoi < perceptionRadius) {
switch (forceType) {
case "align":
steering.add(eachKoi.velocity);
break;
case "cohesion":
steering.add(eachKoi.position);
break;
case "seperation":
let diff = P5.Vector.sub(this.position, eachKoi.position);
steering.add(diff);
break;
default:
break;
}
total++;
}
}
if (total > 0) {
steering.div(total);
if (forceType === "cohesion") steering.sub(this.position);
steering.setMag(this.maxSpeed); // above is divided, so that we can have more control on the magnitude of the steering force
steering.sub(this.velocity);// this is where the force finally becomes the steering force, before is till the desired force
steering.limit(this.maxForce);
}
return steering;
}
flock(kois) {
// force is equal to acceleration in a world where mass = 1. F = M * a
this.acceleration.mult(0);
this.acceleration.add(this.calculateSteeringForce(kois, "align"));
this.acceleration.add(this.calculateSteeringForce(kois, "cohesion"));
this.acceleration.add(this.calculateSteeringForce(kois, "separation"));
}
updateBody() {
this.body.unshift({
...this.position,
});
this.body.pop();
// console.log(this.position)
}
update() {
this.position.add(this.velocity);
this.velocity.add(this.acceleration);
this.velocity.limit(this.maxSpeed)
// without below nothing will be moving
this.updateBody();
}
show() {
this.body.forEach((body_part, index) => {
let size;
if (index < this.bodyLength / 6) {
size = this.baseSize + index * 2;
} else {
size = this.baseSize * 2 - index;
}
context.globalAlpha = (this.bodyLength - index) / (this.bodyLength * 50);
context.beginPath();
context.strokeStyle = this.color;
context.arc(body_part.x, body_part.y, size, 0, Math.PI * 2);
// console.log((this.bodyLength - index)/this.bodyLength)
context.fillStyle = this.color;
context.fill();
});
}
}