Source of: Flow Field Particles, by Claude Opus 4.7
95 lines, no comments ยท 1,287 tokens, written in 14 seconds for $0.034
1 let particles = [];
2 let flowfield;
3 let cols, rows;
4 const scl = 20;
5 let zoff = 0;
6 let hueOffset = 0;
7
8 function setup() {
9 createCanvas(windowWidth, windowHeight);
10 colorMode(HSB, 360, 100, 100, 100);
11 cols = floor(width / scl);
12 rows = floor(height / scl);
13 flowfield = new Array(cols * rows);
14 for (let i = 0; i < 300; i++) {
15 particles.push(new Particle());
16 }
17 background(230, 30, 10);
18 }
19
20 function draw() {
21 noStroke();
22 fill(230, 30, 10, 5);
23 rect(0, 0, width, height);
24
25 let yoff = 0;
26 for (let y = 0; y < rows; y++) {
27 let xoff = 0;
28 for (let x = 0; x < cols; x++) {
29 const index = x + y * cols;
30 const angle = noise(xoff, yoff, zoff) * TWO_PI * 2;
31 const v = p5.Vector.fromAngle(angle);
32 v.setMag(0.3);
33 flowfield[index] = v;
34 xoff += 0.1;
35 }
36 yoff += 0.1;
37 }
38 zoff += 0.003;
39 hueOffset += 0.2;
40
41 for (const p of particles) {
42 p.follow(flowfield);
43 p.update();
44 p.edges();
45 p.show();
46 }
47 }
48
49 function windowResized() {
50 resizeCanvas(windowWidth, windowHeight);
51 cols = floor(width / scl);
52 rows = floor(height / scl);
53 flowfield = new Array(cols * rows);
54 background(230, 30, 10);
55 }
56
57 class Particle {
58 constructor() {
59 this.pos = createVector(random(width), random(height));
60 this.vel = createVector(0, 0);
61 this.acc = createVector(0, 0);
62 this.maxSpeed = 2.5;
63 this.prev = this.pos.copy();
64 this.h = random(360);
65 }
66 follow(vectors) {
67 const x = floor(this.pos.x / scl);
68 const y = floor(this.pos.y / scl);
69 const index = x + y * cols;
70 const force = vectors[index];
71 if (force) this.acc.add(force);
72 }
73 update() {
74 this.vel.add(this.acc);
75 this.vel.limit(this.maxSpeed);
76 this.pos.add(this.vel);
77 this.acc.mult(0);
78 }
79 show() {
80 stroke((this.h + hueOffset) % 360, 80, 100, 40);
81 strokeWeight(1.2);
82 line(this.pos.x, this.pos.y, this.prev.x, this.prev.y);
83 this.updatePrev();
84 }
85 updatePrev() {
86 this.prev.x = this.pos.x;
87 this.prev.y = this.pos.y;
88 }
89 edges() {
90 if (this.pos.x > width) { this.pos.x = 0; this.updatePrev(); }
91 if (this.pos.x < 0) { this.pos.x = width; this.updatePrev(); }
92 if (this.pos.y > height) { this.pos.y = 0; this.updatePrev(); }
93 if (this.pos.y < 0) { this.pos.y = height; this.updatePrev(); }
94 }
95 }