Source of: Harmonic Flowfield Nexus, by Gemini 3.7 Flash
94 lines, no comments ยท 1,382 tokens, written in 10 seconds for $0.0053
1 let particles = [];
2 const NUM_PARTICLES = 600;
3 let noiseScale = 0.005;
4 let noiseZ = 0;
5 let baseHue = 180;
6
7 function setup() {
8 createCanvas(windowWidth, windowHeight);
9 colorMode(HSB, 360, 100, 100, 100);
10 background(0);
11 for (let i = 0; i < NUM_PARTICLES; i++) {
12 particles.push(new Particle());
13 }
14 }
15
16 function draw() {
17 background(0, 0, 0, 8);
18 noiseZ += 0.002;
19 baseHue = (baseHue + 0.2) % 360;
20
21 for (let i = 0; i < particles.length; i++) {
22 particles[i].update();
23 particles[i].display();
24 particles[i].checkEdges();
25 }
26 }
27
28 class Particle {
29 constructor() {
30 this.pos = createVector(random(width), random(height));
31 this.prevPos = this.pos.copy();
32 this.vel = createVector(0, 0);
33 this.acc = createVector(0, 0);
34 this.maxSpeed = random(2, 4.5);
35 this.hueOffset = random(-40, 40);
36 this.weight = random(1, 2.5);
37 this.lifespan = random(50, 150);
38 this.age = 0;
39 }
40
41 update() {
42 this.prevPos = this.pos.copy();
43 let angle = noise(this.pos.x * noiseScale, this.pos.y * noiseScale, noiseZ) * TWO_PI * 4;
44 let force = p5.Vector.fromAngle(angle).mult(0.5);
45
46 if (mouseIsPressed || (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height)) {
47 let mouse = createVector(mouseX, mouseY);
48 let dir = p5.Vector.sub(this.pos, mouse);
49 let dist = dir.mag();
50 if (dist < 200 && dist > 1) {
51 dir.normalize();
52 let pushForce = map(dist, 0, 200, mouseIsPressed ? -3 : 2, 0);
53 force.add(dir.mult(pushForce));
54 }
55 }
56
57 this.acc.add(force);
58 this.vel.add(this.acc);
59 this.vel.limit(this.maxSpeed);
60 this.pos.add(this.vel);
61 this.acc.mult(0);
62 this.age++;
63
64 if (this.age > this.lifespan) {
65 this.reset();
66 }
67 }
68
69 display() {
70 let currentHue = (baseHue + this.hueOffset + 360) % 360;
71 stroke(currentHue, 80, 100, 60);
72 strokeWeight(this.weight);
73 line(this.prevPos.x, this.prevPos.y, this.pos.x, this.pos.y);
74 }
75
76 checkEdges() {
77 if (this.pos.x < 0 || this.pos.x > width || this.pos.y < 0 || this.pos.y > height) {
78 this.reset();
79 }
80 }
81
82 reset() {
83 this.pos = createVector(random(width), random(height));
84 this.prevPos = this.pos.copy();
85 this.vel.mult(0);
86 this.age = 0;
87 this.lifespan = random(100, 250);
88 }
89 }
90
91 function windowResized() {
92 resizeCanvas(windowWidth, windowHeight);
93 background(0);
94 }