103 lines, no comments ยท 1,030 tokens, written in 17 seconds for $0.011


  1  let motes = [];
  2  let time = 0;
  3  let paused = false;
  4  let paletteShift = 0;
  5  
  6  function setup() {
  7    createCanvas(windowWidth, windowHeight);
  8    pixelDensity(1);
  9    colorMode(HSB, 360, 100, 100, 100);
 10    strokeWeight(1.2);
 11    resetScene();
 12  }
 13  
 14  function resetScene() {
 15    background(230, 55, 5);
 16    noiseSeed(floor(random(100000)));
 17    paletteShift = random(-25, 25);
 18    time = 0;
 19    const count = constrain(floor(width * height / 650), 450, 1800);
 20    motes = Array.from({ length: count }, () => new Mote());
 21  }
 22  
 23  class Mote {
 24    constructor() {
 25      this.reset();
 26    }
 27  
 28    reset() {
 29      this.x = random(width);
 30      this.y = random(height);
 31      this.speed = random(0.7, 2.4);
 32      this.life = random(100, 500);
 33      this.tint = random(-15, 15);
 34    }
 35  
 36    step() {
 37      const oldX = this.x;
 38      const oldY = this.y;
 39      const scale = 0.0018;
 40      const field = noise(this.x * scale, this.y * scale, time);
 41      const angle = field * TWO_PI * 2.8;
 42      let vx = cos(angle) * this.speed;
 43      let vy = sin(angle) * this.speed;
 44  
 45      if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
 46        const dx = this.x - mouseX;
 47        const dy = this.y - mouseY;
 48        const distance = sqrt(dx * dx + dy * dy);
 49        const force = max(0, 1 - distance / 220) * 3;
 50        if (distance > 1) {
 51          vx += (-dy / distance) * force;
 52          vy += (dx / distance) * force;
 53        }
 54      }
 55  
 56      this.x += vx;
 57      this.y += vy;
 58      this.life--;
 59  
 60      if (this.x < 0 || this.x > width || this.y < 0 || this.y > height || this.life < 0) {
 61        this.reset();
 62        return;
 63      }
 64  
 65      const hue = (155 + field * 120 + this.tint + paletteShift + 360) % 360;
 66      stroke(hue, 65, 95, 35);
 67      line(oldX, oldY, this.x, this.y);
 68    }
 69  }
 70  
 71  function draw() {
 72    if (paused) return;
 73  
 74    blendMode(BLEND);
 75    noStroke();
 76    fill(230, 55, 5, 5);
 77    rect(0, 0, width, height);
 78  
 79    blendMode(ADD);
 80    for (const mote of motes) mote.step();
 81    blendMode(BLEND);
 82    time += 0.002;
 83  }
 84  
 85  function mousePressed() {
 86    resetScene();
 87  }
 88  
 89  function keyPressed() {
 90    if (key === ' ') {
 91      paused = !paused;
 92      return false;
 93    }
 94    if (key === 's' || key === 'S') {
 95      saveCanvas('aurora-currents', 'png');
 96    }
 97  }
 98  
 99  function windowResized() {
100    resizeCanvas(windowWidth, windowHeight);
101    resetScene();
102  }
103