Source of: Aetheric Currents, by Gemini 4 Argon
111 lines, no comments ยท 1,169 tokens, written in 22 seconds for $0.012
1 let particles = [];
2 const numParticles = 1800;
3 const noiseScale = 0.004;
4 let zOff = 0;
5
6 function setup() {
7 createCanvas(windowWidth, windowHeight);
8 colorMode(HSB, 360, 100, 100, 100);
9 background(240, 30, 5);
10
11 for (let i = 0; i < numParticles; i++) {
12 particles.push(new Particle());
13 }
14 }
15
16 function draw() {
17 blendMode(BLEND);
18 noStroke();
19 fill(240, 30, 5, 6);
20 rect(0, 0, width, height);
21
22 blendMode(ADD);
23
24 for (let p of particles) {
25 p.follow();
26 p.update();
27 p.show();
28 p.edges();
29 }
30
31 zOff += 0.002;
32 }
33
34 class Particle {
35 constructor() {
36 this.pos = createVector(random(width), random(height));
37 this.vel = createVector(0, 0);
38 this.acc = createVector(0, 0);
39 this.maxSpeed = random(1.5, 3.5);
40 this.prevPos = this.pos.copy();
41 this.hueOffset = random(-30, 30);
42 }
43
44 follow() {
45 let angle = noise(this.pos.x * noiseScale, this.pos.y * noiseScale, zOff) * TWO_PI * 4;
46 let force = p5.Vector.fromAngle(angle);
47 force.mult(0.3);
48 this.applyForce(force);
49
50 if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
51 let mouse = createVector(mouseX, mouseY);
52 let dir = p5.Vector.sub(this.pos, mouse);
53 let d = dir.mag();
54 if (d < 150) {
55 dir.normalize();
56 let swirl = createVector(-dir.y, dir.x);
57 swirl.mult(map(d, 0, 150, 2, 0));
58 this.applyForce(swirl);
59 }
60 }
61 }
62
63 applyForce(force) {
64 this.acc.add(force);
65 }
66
67 update() {
68 this.vel.add(this.acc);
69 this.vel.limit(this.maxSpeed);
70 this.pos.add(this.vel);
71 this.acc.mult(0);
72 }
73
74 show() {
75 let baseHue = (frameCount * 0.2 + (this.pos.x + this.pos.y) * 0.05 + this.hueOffset) % 360;
76 if (baseHue < 0) baseHue += 360;
77
78 stroke(baseHue, 80, 90, 20);
79 strokeWeight(1.5);
80 line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
81 this.updatePrev();
82 }
83
84 updatePrev() {
85 this.prevPos.x = this.pos.x;
86 this.prevPos.y = this.pos.y;
87 }
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 }
96
97 function windowResized() {
98 resizeCanvas(windowWidth, windowHeight);
99 blendMode(BLEND);
100 background(240, 30, 5);
101 }
102
103 function mousePressed() {
104 noiseSeed(millis());
105 blendMode(BLEND);
106 background(240, 30, 5);
107 for (let p of particles) {
108 p.pos.set(random(width), random(height));
109 p.updatePrev();
110 }
111 }