xxxxxxxxxx
248
class Boid {
constructor() {
// Initialize boid's position with a random depth (z-axis)
this.pos = createVector(width/4, height/4, random(-50, 50));
this.pos = createVector(width / 4, height / 4, random(-50, 50));
this.vel = p5.Vector.random3D();
this.vel.setMag(random(0.5, 1.5));
// Initialize acceleration and other parameters
this.acc = createVector(0, 0, 0);
this.maxForce = 0.085; // Maximum steering force
this.maxVel = 4; // Maximum velocity
this.fov = 40; // Field of view (how far the boid can see, however I use different values for different behaviors);
this.halfWidth = width / 2;
this.halfHeight = height / 2;
// this.maxDist = 1000;
this.col = randomGaussian(0, 20);// Random color for pigeons
}
// Function to handle canvas edges
checkEdges() {
if (this.pos.x > width) {
// this.pos.x = -width/2;
this.vel.x *= -1;
} else if (this.pos.x < -width) {
// this.pos.x = width/2;
this.vel.x *= -1;
}
if (this.pos.y > height) {
// this.pos.y = -height/2;
this.vel.y *= -1;
} else if (this.pos.y < -height) {
// this.pos.y = height/2;
this.vel.y *= -1;
}
if (this.pos.z > 2000) {
// this.pos.z = -1000;
this.vel.z *= -1;
} else if (this.pos.z < -2000) {
// this.pos.z = 1000;
this.vel.z *= -1;
}
}
// Function to update the boid's position and behavior
update(boids, d) {
this.checkEdges();
this.flock(boids);
this.vel.add(this.acc);
this.pos.add(this.vel);
this.acc.set(0, 0, 0);
this.vel.limit(this.maxVel);
}
// Function for alignment behavior
align(boids, d) {
let fov = 30;
let steering = createVector();
// Boids In View
let biv = 0;
for (let other of boids) {
let d = dist(
this.pos.x,
this.pos.y,
this.pos.z,
other.pos.x,
other.pos.y,
other.pos.z
);
if (other != this && d < fov) {
steering.add(other.vel);
biv++;
}
}
if (biv > 0) {
steering.div(biv);
steering.setMag(this.maxVel);
steering.sub(this.vel);
steering.limit(this.maxForce);
}
return steering;
}
// Function for separation behavior
seperate(boids, d) {
let fov = 13;
let steering = createVector();
let biv = 0;
for (let other of boids) {
let d = dist(
this.pos.x,
this.pos.y,
this.pos.z,
other.pos.x,
other.pos.y,
other.pos.z
);
if (other != this && d < fov) {
let diff = p5.Vector.sub(this.pos, other.pos);
diff.div(d);
steering.add(diff);
biv++;
}
}
if (biv > 0) {
steering.div(biv);
steering.setMag(this.maxVel);
steering.sub(this.vel);
steering.limit(this.maxForce);
}
return steering;
}
// Function for cohesion behavior
cohesion(boids, d) {
let fov = this.fov;
let steering = createVector();
let biv = 0;
for (let other of boids) {
let d = dist(
this.pos.x,
this.pos.y,
this.pos.z,
other.pos.x,
other.pos.y,
other.pos.z
);
if (other != this && d < fov) {
steering.add(other.pos);
biv++;
}
}
if (biv > 0) {
steering.div(biv);
steering.setMag(this.maxVel);
steering.sub(this.pos);
steering.sub(this.vel);
steering.limit(this.maxForce);
}
return steering;
}
// Function to apply flocking behaviors (gets steering values form all 3 functions and adds them to the acceleration)
flock(boids) {
let alignment = this.align(boids);
let cohesion = this.cohesion(boids);
let seperation = this.seperate(boids);
this.acc.add(alignment);
this.acc.add(cohesion);
this.acc.add(seperation);
this.acc.limit(this.maxForce);
}
render(boids) {
this.update(boids);
strokeWeight(4);
// Make boids less opaque the further away they are on the Z-axis
stroke(this.col, 255 * ((this.pos.z + 500) / 1000));
point(this.pos.x, this.pos.y, this.pos.z);
}
}
let flockList = [];
class Flock {
constructor() {
// Create a flock of 200 boids
for (let i = 0; i < 200; i++) {
flockList.push(new Boid());
}
}
render() {
for (let boid of flockList) {
// boid.flock(flockList);
boid.render(flockList);
}
}
}
class pigeonTower {
constructor() {
// Define the size and corners of the pigeon tower
this.size = createVector(200, 100);
this.tlcorner = createVector(-this.size.x / 2, -this.size.y / 2);
this.blcorner = createVector(-this.size.x / 2, this.size.y / 2);
this.trcorner = createVector(this.size.x / 2, -this.size.y / 2);
this.brcorner = createVector(this.size.x / 2, this.size.y / 2);
this.maincolor = [38, 141, 0];// Main color for the tower
this.secondarycolor = [190, 180, 80]; // Secondary color for the tower
}
render() {
push();
translate(width / 2, height / 2);
stroke(0);
strokeWeight(1);
// Draw the main body of the tower
fill(this.maincolor);
rect(-this.size.x / 2, -this.size.y / 2, this.size.x, this.size.y);
fill(this.secondarycolor);
triangle(
this.tlcorner.x,
this.tlcorner.y,
this.blcorner.x,
this.blcorner.y,
-30,
0
);
triangle(
this.trcorner.x,
this.trcorner.y,
this.brcorner.x,
this.brcorner.y,
30,
0
);
push();
rotate(0.785);
rect(-22.5, -22.5, 45, 45);
pop();
fill(19, 71, 0);
rect(this.blcorner.x, this.blcorner.y, 10, 200);
rect(this.brcorner.x, this.brcorner.y, -10, 200);
push();
rotate(-1);
rect(this.blcorner.x, this.blcorner.y - 98, 10, 220);
rotate(2);
rect(this.brcorner.x, this.brcorner.y - 98, -10, 220);
pop();
push();
fill(0, 110, 149);
triangle(-20, this.blcorner.y, 20, this.brcorner.y, 0, 30);
triangle(-20, -this.blcorner.y, 20, -this.brcorner.y, 0, -30);
translate(40, 0);
triangle(-20, this.blcorner.y, 20, this.brcorner.y, 0, 35);
triangle(-20, -this.blcorner.y, 20, -this.brcorner.y, 0, -30);
translate(-80, 0);
triangle(-20, this.blcorner.y, 20, this.brcorner.y, 0, 35);
triangle(-20, -this.blcorner.y, 20, -this.brcorner.y, 0, -30);
pop();
fill(50, 170, 150);
pop();
}
}