xxxxxxxxxx
323
let boids = [];
const numBoids = 100;
let timeObstacles = [];
// Segment definitions for 0-9
const segments = {
'0': [1,1,1,1,1,1,0],
'1': [0,1,1,0,0,0,0],
'2': [1,1,0,1,1,0,1],
'3': [1,1,1,1,0,0,1],
'4': [0,1,1,0,0,1,1],
'5': [1,0,1,1,0,1,1],
'6': [1,0,1,1,1,1,1],
'7': [1,1,1,0,0,0,0],
'8': [1,1,1,1,1,1,1],
'9': [1,1,1,1,0,1,1]
};
function setup() {
createCanvas(480, 820);
// Initialize boids with random positions
for (let i = 0; i < numBoids; i++) {
boids.push(new Boid(random(width), random(height)));
}
}
// New function to draw plexus connections
function drawPlexusConnections() {
let connectionDistance = 80; // Maximum distance for connections
for (let i = 0; i < boids.length; i++) {
for (let j = i + 1; j < boids.length; j++) {
let d = dist(
boids[i].pos.x, boids[i].pos.y,
boids[j].pos.x, boids[j].pos.y
);
if (d < connectionDistance) {
// Calculate alpha and width based on distance
let alpha = map(d, 0, connectionDistance, 100, 0);
let lineWeight = map(d, 0, connectionDistance, 1.5, 0.1);
// Get colors of both boids
let color1 = boids[i].getCurrentColor();
let color2 = boids[j].getCurrentColor();
// Interpolate between the two colors
let lerpAmount = 0.5;
let r = lerp(red(color1), red(color2), lerpAmount);
let g = lerp(green(color1), green(color2), lerpAmount);
let b = lerp(blue(color1), blue(color2), lerpAmount);
stroke(r, g, b, alpha);
strokeWeight(lineWeight);
line(
boids[i].pos.x, boids[i].pos.y,
boids[j].pos.x, boids[j].pos.y
);
}
}
}
}
function drawDigit(x, y, digit, size) {
const segWidth = size * 0.075;
const segLength = size * 0.3;
push();
translate(x, y);
strokeWeight(segWidth);
strokeCap(ROUND);
let pattern = segments[digit];
// Horizontal segments
if (pattern[0]) line(-segLength/2, -segLength, segLength/2, -segLength);
if (pattern[6]) line(-segLength/2, 0, segLength/2, 0);
if (pattern[3]) line(-segLength/2, segLength, segLength/2, segLength);
// Vertical segments
if (pattern[5]) line(-segLength/2, -segLength, -segLength/2, 0);
if (pattern[4]) line(-segLength/2, 0, -segLength/2, segLength);
if (pattern[1]) line(segLength/2, -segLength, segLength/2, 0);
if (pattern[2]) line(segLength/2, 0, segLength/2, segLength);
// Store obstacle points
let points = [];
let step = segWidth;
if (pattern[0]) for (let i = -segLength/2; i <= segLength/2; i += step) points.push({x: x + i, y: y - segLength});
if (pattern[6]) for (let i = -segLength/2; i <= segLength/2; i += step) points.push({x: x + i, y: y});
if (pattern[3]) for (let i = -segLength/2; i <= segLength/2; i += step) points.push({x: x + i, y: y + segLength});
if (pattern[5]) for (let i = -segLength; i <= 0; i += step) points.push({x: x - segLength/2, y: y + i});
if (pattern[4]) for (let i = 0; i <= segLength; i += step) points.push({x: x - segLength/2, y: y + i});
if (pattern[1]) for (let i = -segLength; i <= 0; i += step) points.push({x: x + segLength/2, y: y + i});
if (pattern[2]) for (let i = 0; i <= segLength; i += step) points.push({x: x + segLength/2, y: y + i});
timeObstacles.push(points);
pop();
}
function draw() {
background(0, 130);
// Reset obstacle points
timeObstacles = [];
// Draw plexus connections first (behind everything)
drawPlexusConnections();
// Display digital clock
let digitSize = width * 0.3;
let spacing = digitSize * 0.6;
let startX = width/2 - spacing * 1.5;
let y = height/2;
push();
stroke(255);
noFill();
let now = new Date();
let totalSeconds = (now.getMinutes() * 60 + now.getSeconds()).toString().padStart(3, '0');
let timeString = totalSeconds;
for (let i = 0; i < timeString.length; i++) {
let x = startX + i * spacing;
drawDigit(x, y, timeString[i], digitSize);
}
pop();
// Update and show all boids
for (let boid of boids) {
boid.update();
boid.show();
}
}
class Boid {
constructor(x, y) {
this.pos = createVector(x, y);
this.vel = p5.Vector.random2D();
this.vel.setMag(random(2, 4));
this.acc = createVector();
this.maxForce = 0.65;
this.maxSpeed = 4;
this.size = 5;
}
// New method to get current color for plexus connections
getCurrentColor() {
let speed = this.vel.mag();
let slowColor = color(255, 105, 180); // Pink
let fastColor = color(0, 255, 200); // Cyan-green
return lerpColor(fastColor, slowColor, speed / this.maxSpeed);
}
align() {
let perceptionRadius = 50;
let steering = createVector();
let total = 0;
for (let other of boids) {
let d = dist(
this.pos.x, this.pos.y,
other.pos.x, other.pos.y
);
if (other != this && d < perceptionRadius) {
steering.add(other.vel);
total++;
}
}
if (total > 0) {
steering.div(total);
steering.setMag(this.maxSpeed);
steering.sub(this.vel);
steering.limit(this.maxForce);
}
return steering;
}
cohesion() {
let perceptionRadius = 150;
let steering = createVector();
let total = 0;
for (let other of boids) {
let d = dist(
this.pos.x, this.pos.y,
other.pos.x, other.pos.y
);
if (other != this && d < perceptionRadius) {
steering.add(other.pos);
total++;
}
}
if (total > 0) {
steering.div(total);
steering.sub(this.pos);
steering.setMag(this.maxSpeed);
steering.sub(this.vel);
steering.limit(this.maxForce);
}
return steering;
}
separate() {
let perceptionRadius = 150;
let steering = createVector();
let total = 0;
for (let other of boids) {
let d = dist(
this.pos.x, this.pos.y,
other.pos.x, other.pos.y
);
if (other != this && d < perceptionRadius) {
let diff = p5.Vector.sub(this.pos, other.pos);
diff.div(d * d);
steering.add(diff);
total++;
}
}
if (total > 0) {
steering.div(total);
steering.setMag(this.maxSpeed);
steering.sub(this.vel);
steering.limit(this.maxForce);
}
return steering;
}
avoidObstacles() {
let steering = createVector();
let outerRadius = 20;
let innerRadius = this.size + 3;
for (let obstacle of timeObstacles) {
let d = dist(this.pos.x, this.pos.y, obstacle.x, obstacle.y);
if (d < outerRadius) {
let normal = p5.Vector.sub(this.pos, createVector(obstacle.x, obstacle.y));
normal.normalize();
if (d < innerRadius) {
this.pos.add(normal.copy().mult(innerRadius - d));
let reflection = this.vel.copy();
let dotProduct = normal.dot(reflection);
normal.mult(2 * dotProduct);
reflection.sub(normal);
this.vel = reflection.mult(0.95);
let tangent = createVector(-normal.y, normal.x);
if (tangent.dot(this.vel) < 0) tangent.mult(-1);
steering.add(tangent.mult(this.maxForce * 3));
} else {
let force = map(d, innerRadius, outerRadius, 1, 0);
let avoidForce = normal.copy().mult(force * this.maxForce * 2);
let tangent = createVector(-normal.y, normal.x);
if (tangent.dot(this.vel) < 0) tangent.mult(-1);
avoidForce.add(tangent.mult(force * this.maxForce));
steering.add(avoidForce);
}
}
}
return steering;
}
update() {
let mouse = createVector(mouseX, mouseY);
let distToMouse = p5.Vector.dist(this.pos, mouse);
let desired = p5.Vector.sub(mouse, this.pos);
let speedMultiplier = map(distToMouse, 0, width/2, 0.5, 2);
desired.setMag(this.maxSpeed * speedMultiplier);
let steer = p5.Vector.sub(desired, this.vel);
steer.limit(this.maxForce * speedMultiplier);
this.acc.add(steer);
this.acc.add(this.align().mult(0.8));
this.acc.add(this.cohesion().mult(0.4));
this.acc.add(this.separate().mult(2.0));
this.acc.add(this.avoidObstacles());
this.vel.add(this.acc);
this.vel.limit(this.maxSpeed);
this.pos.add(this.vel);
this.acc.mult(0);
this.edges();
}
show() {
push();
translate(this.pos.x, this.pos.y);
noStroke();
let speed = this.vel.mag();
let dynamicSize = map(speed, 0, this.maxSpeed, this.size * 1, this.size * 1.2);
let dynamicOpacity = map(speed, 0, this.maxSpeed, 100, 255);
let speedColor = this.getCurrentColor();
fill(speedColor, dynamicOpacity);
circle(0, 0, dynamicSize);
pop();
}
edges() {
if (this.pos.x > width) this.pos.x = 0;
if (this.pos.x < 0) this.pos.x = width;
if (this.pos.y > height) this.pos.y = 0;
if (this.pos.y < 0) this.pos.y = height;
}
}