Source of: Perlin Noise Flow Field, by Gemini 2.5 Pro
104 lines, no comments ยท 4,073 tokens, written in 37 seconds for $0.041
1 let particles = [];
2 let scale = 10;
3 let cols, rows;
4 let zoff = 0;
5 let flowfield;
6
7 function setup() {
8 createCanvas(600, 400);
9 cols = floor(width / scale);
10 rows = floor(height / scale);
11 flowfield = new Array(cols * rows);
12
13 for (let i = 0; i < 500; i++) {
14 particles[i] = new Particle();
15 }
16 background(0);
17 colorMode(HSB, 360, 100, 100, 1);
18 }
19
20 function draw() {
21 let yoff = 0;
22 for (let y = 0; y < rows; y++) {
23 let xoff = 0;
24 for (let x = 0; x < cols; x++) {
25 let index = x + y * cols;
26 let angle = noise(xoff, yoff, zoff) * TWO_PI * 4;
27 let v = p5.Vector.fromAngle(angle);
28 v.setMag(1);
29 flowfield[index] = v;
30 xoff += 0.1;
31 }
32 yoff += 0.1;
33 }
34 zoff += 0.005;
35
36 for (let i = 0; i < particles.length; i++) {
37 particles[i].follow(flowfield);
38 particles[i].update();
39 particles[i].edges();
40 particles[i].show();
41 }
42 }
43
44 class Particle {
45 constructor() {
46 this.pos = createVector(random(width), random(height));
47 this.vel = createVector(0, 0);
48 this.acc = createVector(0, 0);
49 this.maxspeed = 4;
50 this.prevPos = this.pos.copy();
51 this.h = random(360);
52 }
53
54 update() {
55 this.vel.add(this.acc);
56 this.vel.limit(this.maxspeed);
57 this.pos.add(this.vel);
58 this.acc.mult(0);
59 }
60
61 follow(vectors) {
62 let x = floor(this.pos.x / scale);
63 let y = floor(this.pos.y / scale);
64 let index = x + y * cols;
65 let force = vectors[index];
66 this.applyForce(force);
67 }
68
69 applyForce(force) {
70 this.acc.add(force);
71 }
72
73 show() {
74 stroke(this.h, 90, 90, 0.1);
75 this.h = (this.h + 0.5) % 360;
76 strokeWeight(1);
77 line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
78 this.updatePrev();
79 }
80
81 updatePrev() {
82 this.prevPos.x = this.pos.x;
83 this.prevPos.y = this.pos.y;
84 }
85
86 edges() {
87 if (this.pos.x > width) {
88 this.pos.x = 0;
89 this.updatePrev();
90 }
91 if (this.pos.x < 0) {
92 this.pos.x = width;
93 this.updatePrev();
94 }
95 if (this.pos.y > height) {
96 this.pos.y = 0;
97 this.updatePrev();
98 }
99 if (this.pos.y < 0) {
100 this.pos.y = height;
101 this.updatePrev();
102 }
103 }
104 }