148 lines, no comments ยท 1,666 tokens, written in 17 seconds for $0.050


  1  let particles = [];
  2  let palette;
  3  let zoff = 0;
  4  let seedValue;
  5  
  6  function setup() {
  7    createCanvas(windowWidth, windowHeight);
  8    pixelDensity(1);
  9    colorMode(HSB, 360, 100, 100, 100);
 10    blendMode(ADD);
 11    seedValue = floor(random(999999));
 12    palette = [
 13      color(185, 90, 95, 18),
 14      color(210, 95, 100, 16),
 15      color(275, 80, 100, 14),
 16      color(315, 85, 100, 12),
 17      color(120, 65, 95, 10)
 18    ];
 19    resetSketch();
 20  }
 21  
 22  function draw() {
 23    noStroke();
 24    blendMode(BLEND);
 25    fill(230, 45, 5, 9);
 26    rect(0, 0, width, height);
 27    blendMode(ADD);
 28  
 29    zoff += 0.003;
 30  
 31    for (let p of particles) {
 32      p.update();
 33      p.show();
 34    }
 35  
 36    drawGlow(width * 0.5, height * 0.5, min(width, height) * 0.55);
 37  }
 38  
 39  function resetSketch() {
 40    randomSeed(seedValue);
 41    noiseSeed(seedValue);
 42    background(230, 55, 4);
 43    particles = [];
 44  
 45    let count = floor(map(width * height, 250000, 2200000, 280, 1200, true));
 46    for (let i = 0; i < count; i++) {
 47      particles.push(new Particle(random(width), random(height), random(palette)));
 48    }
 49  }
 50  
 51  class Particle {
 52    constructor(x, y, c) {
 53      this.pos = createVector(x, y);
 54      this.prev = this.pos.copy();
 55      this.vel = p5.Vector.random2D().mult(random(0.2, 1.4));
 56      this.acc = createVector(0, 0);
 57      this.col = c;
 58      this.size = random(0.7, 2.4);
 59      this.life = random(100, 360);
 60      this.maxSpeed = random(1.1, 3.4);
 61      this.noiseScale = random(0.0018, 0.0045);
 62    }
 63  
 64    update() {
 65      this.prev.set(this.pos);
 66  
 67      let n = noise(this.pos.x * this.noiseScale, this.pos.y * this.noiseScale, zoff);
 68      let angle = n * TAU * 3.4 + sin(zoff * 8) * 0.35;
 69      let flow = p5.Vector.fromAngle(angle).mult(0.12);
 70      this.acc.add(flow);
 71  
 72      if (mouseIsPressed || mouseX > 0 && mouseY > 0) {
 73        let mouse = createVector(mouseX, mouseY);
 74        let toMouse = p5.Vector.sub(mouse, this.pos);
 75        let d = constrain(toMouse.mag(), 35, 520);
 76        let strength = mouseIsPressed ? 2.8 : 0.55;
 77        toMouse.normalize().mult(strength / (d * 0.035));
 78        toMouse.rotate(HALF_PI * 0.85);
 79        this.acc.add(toMouse);
 80      }
 81  
 82      let center = createVector(width / 2, height / 2);
 83      let inward = p5.Vector.sub(center, this.pos);
 84      inward.setMag(0.006);
 85      this.acc.add(inward);
 86  
 87      this.vel.add(this.acc);
 88      this.vel.limit(this.maxSpeed);
 89      this.pos.add(this.vel);
 90      this.acc.mult(0);
 91      this.life--;
 92  
 93      if (this.pos.x < -30 || this.pos.x > width + 30 || this.pos.y < -30 || this.pos.y > height + 30 || this.life <= 0) {
 94        this.respawn();
 95      }
 96    }
 97  
 98    show() {
 99      let alphaBoost = map(this.vel.mag(), 0, this.maxSpeed, 8, 42);
100      stroke(hue(this.col), saturation(this.col), brightness(this.col), alphaBoost);
101      strokeWeight(this.size);
102      line(this.prev.x, this.prev.y, this.pos.x, this.pos.y);
103  
104      if (random() < 0.012) {
105        noStroke();
106        fill(hue(this.col), saturation(this.col), 100, 18);
107        circle(this.pos.x, this.pos.y, this.size * random(3, 8));
108      }
109    }
110  
111    respawn() {
112      let a = random(TAU);
113      let r = random(min(width, height) * 0.08, min(width, height) * 0.48);
114      this.pos.set(width / 2 + cos(a) * r, height / 2 + sin(a) * r);
115      this.prev.set(this.pos);
116      this.vel = p5.Vector.random2D().mult(random(0.2, 1.5));
117      this.life = random(120, 420);
118      this.col = random(palette);
119    }
120  }
121  
122  function drawGlow(x, y, radius) {
123    noFill();
124    for (let i = 0; i < 7; i++) {
125      stroke(205 + i * 10, 70, 100, 2.5);
126      strokeWeight(1 + i * 0.6);
127      circle(x, y, radius * (0.58 + i * 0.075 + sin(frameCount * 0.01 + i) * 0.01));
128    }
129  }
130  
131  function mousePressed() {
132    for (let i = 0; i < 40; i++) {
133      particles.push(new Particle(mouseX + random(-20, 20), mouseY + random(-20, 20), random(palette)));
134    }
135  }
136  
137  function keyPressed() {
138    if (key === 's' || key === 'S') saveCanvas('aurora-particle-garden', 'png');
139    if (key === 'r' || key === 'R') {
140      seedValue = floor(random(999999));
141      resetSketch();
142    }
143  }
144  
145  function windowResized() {
146    resizeCanvas(windowWidth, windowHeight);
147    resetSketch();
148  }