https://editor.p5js.org/sl9964/full/NG8Z96dUx
<aside>
Below are the New Code Added:
class Fish {
constructor(x, y, type, size, baseColor) {
this.pos = createVector(x, y);
this.size = size;
this.baseColor = baseColor;
this.type = type;
this.assignStand();
if (type === "radical") {
this.vel = createVector(random(-0.2, 0.2), random(-0.2, 0.2));
this.jumpChance = 0.02;
} else if (type === "moderate") {
this.vel = createVector(random(-1, 1), random(-1, 1));
this.jumpChance = 0.1;
} else if (type === "shifting") {
this.vel = createVector(random(-2, 2), random(-2, 2));
this.jumpChance = 0.5;
}
this.acc = createVector(0, 0);
this.time = 0;
}
assignStand() {
if (this.pos.x < 400 && this.pos.y < 400) {
this.stand = "authorCommunism";
this.minX = 0;
this.minY = 0;
this.boundX = 400;
this.boundY = 400;
}
if (this.pos.x > 400 && this.pos.y < 400) {
this.stand = "authorCapitalism";
this.minX = 400;
this.minY = 0;
this.boundX = 800;
this.boundY = 400;
}
if (this.pos.x < 400 && this.pos.y > 400) {
this.stand = "anarchyCommunism";
this.minX = 0;
this.minY = 400;
this.boundX = 400;
this.boundY = 800;
}
if (this.pos.x > 400 && this.pos.y > 400) {
this.stand = "anarchyCapitalism";
this.minX = 400;
this.minY = 400;
this.boundX = 800;
this.boundY = 800;
}
}
changeStand() {
let prevStand = this.stand;
this.assignStand();
if (this.stand !== prevStand) {
this.shine();
}
}
attracted(target, G, low, high, time) {
this.time++;
if (this.time<time) {
let force = p5.Vector.sub(target, this.pos);
let dsquared = force.magSq();
dsquared = constrain(dsquared, low, high);
let strength = G / dsquared;
force.setMag(strength);
this.applyForce(force);
}
}
update() {
if(random()<0.01){
this.time=0;
}else if (random() < 0.1) {
this.moveFreely();
} else {
this.vel.add(this.acc);
}
this.pos.add(this.vel);
this.acc.mult(0);
this.changeStand();
this.checkBoundaries();
this.shine();
}
checkBoundaries() {
if (this.pos.x <= this.minX || this.pos.x >= this.boundX) {
if (random() > this.jumpChance) {
this.reflectVelocity("x");
} else {
this.changeStand();
}
this.pos.x = constrain(this.pos.x, 0, this.boundX);
}
if (this.pos.y <= this.minY || this.pos.y >= this.boundY) {
if (random() > this.jumpChance) {
this.reflectVelocity("y");
} else {
this.changeStand();
}
this.pos.y = constrain(this.pos.y, 0, this.boundY);
}
}
reflectVelocity(axis) {
if (axis === "x") {
this.vel.x *= this.type === "shifting" ? -1 : -0.5;
} else if (axis === "y") {
this.vel.y *= this.type === "shifting" ? -1 : -0.5;
}
}
shine() {
let stabilityX = constrain(map(abs(this.vel.x), 0, 1, 75, 100), 75, 100);
let stabilityY = constrain(map(abs(this.vel.y), 0, 3, 25, 100), 25, 100);
colorMode(HSL, 360, 100, 100, 1);
let hue;
switch (this.stand) {
case "authorCommunism":
hue = 350;
break;
case "authorCapitalism":
hue = 0;
break;
case "anarchyCommunism":
hue = 190;
break;
case "anarchyCapitalism":
hue = 200;
break;
default:
hue = 100;
break;
}
this.baseColor = color(hue, stabilityX, stabilityY);
}
clicked() {
let d = dist(mouseX, mouseY, this.pos.x, this.pos.y);
if (d < this.size / 2) {
this.baseColor = "black";
console.log(this); // Log this Fish object
}
}
show() {
fill(this.baseColor);
noStroke();
if (this.type === "radical") {
rect(this.pos.x, this.pos.y, this.size);
} else if (this.type === "moderate") {
ellipse(this.pos.x, this.pos.y, this.size);
} else if (this.type === "shifting") {
const height = (sqrt(3) / 2) * this.size;
triangle(
this.pos.x - this.size / 2,
this.pos.y + height / 2,
this.pos.x + this.size / 2,
this.pos.y + height / 2,
this.pos.x,
this.pos.y - height / 2
);
}
}
}
<aside>
minX minY boundX boundY
to let each fish continuously adjust its stand based on its exact location on the canvas.assignStand()
and a changeStand()
method to actively check for changes in a fish's stand. If a fish enters a new area, it immediately triggers the shine
method. It was part of the performance solution.time
parameter in the attracted()
method. So mouse interaction has limited influence like in the real world.update
function, I included a mechanism to randomly reset the attraction timer, so some random fish are always ready to be attracted again. I also use this action to perform any property changes inside the class Fish{}
so the sketch.js will be cleaner.rect()
and ellipse()
.clicked
method allows me to debug and to check if any fish is fine using console.log.
</aside>let noiseScale = 0.05;
let points = [];
let fishGroup = [];
let gradientBG;
let gradientBG1;
let type;
function preload(){
// fish=loadImage('seafish.webp');
}
function setup() {
createCanvas(800, 800);
colorMode(HSL, 360, 100, 100, 1);
createGradient();
generatePoints(100);
for (let p of points) {
let randomList = [
"radical", "radical",
"moderate", "moderate", "moderate", "moderate", "moderate",
"shifting", "shifting", "shifting"
];
let index = int(random(randomList.length));
let type = randomList[index];
fishGroup.push(new Fish(p.x, p.y, type, 25, 'white'));
}
}
function draw() {
image(gradientBG,0,0);
image(gradientBG1,0,0);
createAxis();
sampleColor='white';
for (let fish of fishGroup) {
if (0 < mouseX && mouseX < width*0.8 && 0 < mouseY && mouseY < height*0.8) {
let mouse = createVector(mouseX, mouseY);
fish.attracted(mouse,5,25,400,20);
} else {
fish.moveFreely();
}
fish.show();
fish.update();
}
}
function mousePressed(){
for (let fish of fishGroup) {
fish.clicked();
}
}