Source of: Flow Field Particles, by Claude Sonnet 5
124 lines, no comments ยท 1,543 tokens, written in 13 seconds for $0.016
1 let particles = [];
2 const numParticles = 800;
3 let zoff = 0;
4 let noiseScale = 0.008;
5
6 function setup() {
7 createCanvas(windowWidth, windowHeight);
8 background(10, 10, 20);
9 colorMode(HSB, 360, 100, 100, 100);
10 for (let i = 0; i < numParticles; i++) {
11 particles.push(new Particle());
12 }
13 }
14
15 function draw() {
16 background(10, 10, 20, 4);
17
18 for (let p of particles) {
19 p.follow();
20 p.update();
21 p.edges();
22 p.show();
23 }
24
25 zoff += 0.002;
26 }
27
28 class Particle {
29 constructor() {
30 this.pos = createVector(random(width), random(height));
31 this.vel = createVector(0, 0);
32 this.acc = createVector(0, 0);
33 this.maxSpeed = random(1.5, 3.5);
34 this.hue = random(360);
35 this.prevPos = this.pos.copy();
36 this.lifespan = random(100, 300);
37 this.age = 0;
38 }
39
40 follow() {
41 let angle = noise(
42 this.pos.x * noiseScale,
43 this.pos.y * noiseScale,
44 zoff
45 ) * TWO_PI * 4;
46 let force = p5.Vector.fromAngle(angle);
47 force.setMag(0.1);
48 this.acc.add(force);
49 }
50
51 update() {
52 this.vel.add(this.acc);
53 this.vel.limit(this.maxSpeed);
54 this.pos.add(this.vel);
55 this.acc.mult(0);
56 this.age++;
57
58 if (this.age > this.lifespan) {
59 this.reset();
60 }
61 }
62
63 reset() {
64 this.pos = createVector(random(width), random(height));
65 this.vel = createVector(0, 0);
66 this.prevPos = this.pos.copy();
67 this.age = 0;
68 this.hue = (this.hue + random(20, 60)) % 360;
69 this.lifespan = random(100, 300);
70 }
71
72 edges() {
73 if (this.pos.x > width) {
74 this.pos.x = 0;
75 this.updatePrev();
76 }
77 if (this.pos.x < 0) {
78 this.pos.x = width;
79 this.updatePrev();
80 }
81 if (this.pos.y > height) {
82 this.pos.y = 0;
83 this.updatePrev();
84 }
85 if (this.pos.y < 0) {
86 this.pos.y = height;
87 this.updatePrev();
88 }
89 }
90
91 updatePrev() {
92 this.prevPos = this.pos.copy();
93 }
94
95 show() {
96 let speed = this.vel.mag();
97 let bright = map(speed, 0, this.maxSpeed, 40, 100);
98 let alpha = map(this.age, 0, this.lifespan, 60, 0);
99
100 stroke(this.hue, 70, bright, alpha);
101 strokeWeight(1.5);
102 line(this.prevPos.x, this.prevPos.y, this.pos.x, this.pos.y);
103
104 this.updatePrev();
105 }
106 }
107
108 function windowResized() {
109 resizeCanvas(windowWidth, windowHeight);
110 background(10, 10, 20);
111 }
112
113 function mousePressed() {
114 zoff += 5;
115 for (let i = 0; i < 20; i++) {
116 let p = new Particle();
117 p.pos = createVector(mouseX, mouseY);
118 p.prevPos = p.pos.copy();
119 particles.push(p);
120 }
121 if (particles.length > numParticles * 1.5) {
122 particles.splice(0, 20);
123 }
124 }