xxxxxxxxxx
242
let particles = [];
let branches = []; // Array to hold branch positions
let treeHeight = 200;
let decayStarted = false;
let time = 0; // Declare and initialize the time variable
let flockDuration = 120; // Extend the time in seconds for flocking around branches
function setup() {
createCanvas(800, 800);
colorMode(HSB, 360, 100, 100, 100);
// Calculate the branch positions for particle initialization
calculateBranches(width / 2, height / 2 + 200, -PI / 2, treeHeight, 5);
// Initialize particles as seeds around the branches
for (let i = 0; i < 1000; i++) {
let branch = random(branches);
let offsetX = random(-10, 10);
let offsetY = random(-10, 10);
particles.push(new Particle(branch.x + offsetX, branch.y + offsetY));
}
}
function draw() {
// Clear the background to remove residue
background(0);
// Draw the tree with recursive branches
drawFractalTree(width / 2, height / 2 + 200, -PI / 2, treeHeight, 5);
// Increment time for animation effects
time += deltaTime / 1000;
// Start decay phase after a certain time
if (time > flockDuration && !decayStarted) {
decayStarted = true;
for (let particle of particles) {
particle.startDecay();
}
}
// Update and display particles
for (let particle of particles) {
particle.applyFlocking(particles);
particle.applyForces();
particle.update();
particle.display();
}
}
function drawFractalTree(x, y, angle, length, depth) {
if (depth === 0) return;
let xEnd = x + cos(angle) * length;
let yEnd = y + sin(angle) * length;
stroke(30, 80, 40);
strokeWeight(depth + 1);
line(x, y, xEnd, yEnd);
branches.push(createVector(xEnd, yEnd));
drawFractalTree(xEnd, yEnd, angle - PI / 6, length * 0.7, depth - 1);
drawFractalTree(xEnd, yEnd, angle + PI / 6, length * 0.7, depth - 1);
}
function calculateBranches(x, y, angle, length, depth) {
if (depth === 0) return;
let xEnd = x + cos(angle) * length;
let yEnd = y + sin(angle) * length;
branches.push(createVector(xEnd, yEnd));
calculateBranches(xEnd, yEnd, angle - PI / 6, length * 0.7, depth - 1);
calculateBranches(xEnd, yEnd, angle + PI / 6, length * 0.7, depth - 1);
}
class Particle {
constructor(x, y) {
this.position = createVector(x, y);
this.velocity = p5.Vector.random2D().mult(1); // Increased initial speed
this.acceleration = createVector();
this.maxSpeed = 1; // Increased max speed for fluidity
this.maxForce = 0.1; // Increased max force for faster reactions
this.size = random(2, 3);
this.hue = 0;
this.alpha = 255;
this.bloomed = false;
this.decaying = false;
this.decayCounter = 0;
}
applyFlocking(particles) {
let alignment = this.align(particles);
let cohesion = this.cohere(particles);
let separation = this.separate(particles);
alignment = alignment || createVector(0, 0);
cohesion = cohesion || createVector(0, 0);
separation = separation || createVector(0, 0);
alignment.mult(1);
cohesion.mult(1.5); // Increased influence
separation.mult(1.5); // Increased influence
this.acceleration.add(alignment);
this.acceleration.add(cohesion);
this.acceleration.add(separation);
}
applyForces() {
if (!this.decaying) {
let nearestBranch = this.findNearestBranch();
if (nearestBranch) {
let pullToBranch = p5.Vector.sub(nearestBranch, this.position);
pullToBranch.setMag(0.1); // Adjust strength of pull towards branch
this.acceleration.add(pullToBranch);
}
} else {
this.acceleration.add(createVector(0, 0.02)); // Gravity-like force during decay
}
}
findNearestBranch() {
let nearest = null;
let minDist = Infinity;
for (let branch of branches) {
let d = dist(this.position.x, this.position.y, branch.x, branch.y);
if (d < minDist) {
minDist = d;
nearest = branch;
}
}
return nearest;
}
startDecay() {
this.decaying = true;
this.velocity = createVector(0, random(1, 2)); // Start falling
}
align(particles) {
let perceptionRadius = 50;
let steering = createVector();
let total = 0;
for (let other of particles) {
let d = dist(this.position.x, this.position.y, other.position.x, other.position.y);
if (other !== this && d < perceptionRadius) {
steering.add(other.velocity);
total++;
}
}
if (total > 0) {
steering.div(total);
steering.setMag(this.maxSpeed);
steering.sub(this.velocity);
steering.limit(this.maxForce);
}
return steering;
}
cohere(particles) {
let perceptionRadius = 50;
let steering = createVector();
let total = 0;
for (let other of particles) {
let d = dist(this.position.x, this.position.y, other.position.x, other.position.y);
if (other !== this && d < perceptionRadius) {
steering.add(other.position);
total++;
}
}
if (total > 0) {
steering.div(total);
steering.sub(this.position);
steering.setMag(this.maxSpeed);
steering.sub(this.velocity);
steering.limit(this.maxForce);
}
return steering;
}
separate(particles) {
let perceptionRadius = 25;
let steering = createVector();
let total = 0;
for (let other of particles) {
let d = dist(this.position.x, this.position.y, other.position.x, other.position.y);
if (other !== this && d < perceptionRadius) {
let diff = p5.Vector.sub(this.position, other.position);
diff.div(d * d);
steering.add(diff);
total++;
}
}
if (total > 0) {
steering.div(total);
steering.setMag(this.maxSpeed);
steering.sub(this.velocity);
steering.limit(this.maxForce);
}
return steering;
}
update() {
if (!this.bloomed && random() < 0.01) {
this.hue = random(300, 360);
this.size = random(4, 8);
this.bloomed = true;
}
if (this.decaying) {
this.alpha -= 2;
if (this.alpha <= 0) {
this.alpha = 0;
}
}
this.velocity.add(this.acceleration);
this.velocity.limit(this.maxSpeed);
this.position.add(this.velocity);
this.acceleration.mult(0);
}
display() {
fill(this.hue, 60, 90, this.alpha);
noStroke();
ellipse(this.position.x, this.position.y, this.size, this.size * 0.6);
}
}