196 lines, 2 of them comments ยท 2,907 tokens, written in 41 seconds for $0.0015


  1  let stars = [];
  2  let palette;
  3  
  4  function setup() {
  5    createCanvas(windowWidth, windowHeight);
  6    pixelDensity(1);
  7    angleMode(RADIANS);
  8    palette = [
  9      [72, 220, 203],
 10      [103, 161, 255],
 11      [180, 126, 255],
 12      [255, 151, 194],
 13      [255, 209, 132]
 14    ];
 15  
 16    randomSeed(12);
 17    for (let i = 0; i < 180; i++) {
 18      stars.push({
 19        x: random(),
 20        y: random(),
 21        size: random(0.7, 2.2),
 22        phase: random(TWO_PI),
 23        speed: random(0.5, 1.8)
 24      });
 25    }
 26  }
 27  
 28  function draw() {
 29    background(7, 13, 29);
 30  
 31    const t = millis() * 0.00018;
 32    const cx = width * 0.5;
 33    const cy = height * 0.5;
 34    const unit = min(width, height);
 35    const scale = unit * 0.39;
 36  
 37    drawAtmosphere(cx, cy, unit);
 38    drawStars(t);
 39  
 40    push();
 41    translate(cx, cy);
 42    drawOrbitLines(scale, t);
 43    drawPetals(scale, t);
 44    drawContours(scale, t);
 45    drawCore(scale, t);
 46    pop();
 47  
 48    drawFrameDetails(cx, cy, unit, t);
 49  }
 50  
 51  function drawAtmosphere(cx, cy, unit) {
 52    noStroke();
 53    for (let i = 18; i >= 0; i--) {
 54      const r = unit * (0.08 + i * 0.025);
 55      const a = map(i, 18, 0, 1, 7);
 56      fill(26, 53, 91, a);
 57      circle(cx, cy, r * 2);
 58    }
 59  }
 60  
 61  function drawStars(t) {
 62    noStroke();
 63    for (const s of stars) {
 64      const twinkle = 0.35 + 0.65 * (0.5 + 0.5 * sin(t * 7 * s.speed + s.phase));
 65      fill(164, 207, 255, 50 + 150 * twinkle);
 66      circle(s.x * width, s.y * height, s.size * twinkle);
 67    }
 68  }
 69  
 70  function drawOrbitLines(r, t) {
 71    noFill();
 72    for (let i = 0; i < 5; i++) {
 73      const rr = r * (0.78 + i * 0.075) + sin(t * 4 + i) * 3;
 74      stroke(113, 177, 215, 24 + i * 3);
 75      strokeWeight(0.8);
 76      circle(0, 0, rr * 2);
 77    }
 78  
 79    // Small marks along the outer orbit give the bloom a quiet celestial rhythm.
 80    for (let i = 0; i < 72; i++) {
 81      const a = TWO_PI * i / 72 + t * 0.12;
 82      const inner = r * 0.91;
 83      const outer = inner + (i % 6 === 0 ? 9 : 3);
 84      stroke(141, 200, 229, i % 6 === 0 ? 100 : 40);
 85      line(cos(a) * inner, sin(a) * inner, cos(a) * outer, sin(a) * outer);
 86    }
 87  }
 88  
 89  function drawPetals(r, t) {
 90    const count = 12;
 91    for (let i = 0; i < count; i++) {
 92      const a = TWO_PI * i / count + t * 0.22;
 93      const pulse = 1 + 0.035 * sin(t * 5 + i * 0.8);
 94      const len = r * 0.77 * pulse;
 95      const w = r * (0.19 + 0.025 * sin(i * 2.3));
 96      const c = palette[i % palette.length];
 97  
 98      push();
 99      rotate(a);
100      noStroke();
101      fill(c[0], c[1], c[2], 22);
102      beginShape();
103      vertex(0, 0);
104      bezierVertex(-w * 0.95, -len * 0.28, -w * 0.75, -len * 0.82, 0, -len);
105      bezierVertex(w * 0.75, -len * 0.82, w * 0.95, -len * 0.28, 0, 0);
106      endShape(CLOSE);
107  
108      noFill();
109      stroke(c[0], c[1], c[2], 95);
110      strokeWeight(1);
111      beginShape();
112      vertex(0, 0);
113      bezierVertex(-w * 0.95, -len * 0.28, -w * 0.75, -len * 0.82, 0, -len);
114      bezierVertex(w * 0.75, -len * 0.82, w * 0.95, -len * 0.28, 0, 0);
115      endShape();
116  
117      stroke(c[0], c[1], c[2], 45);
118      strokeWeight(0.7);
119      bezier(0, -len * 0.04, -w * 0.12, -len * 0.4, w * 0.12, -len * 0.72, 0, -len * 0.96);
120      pop();
121    }
122  }
123  
124  function drawContours(r, t) {
125    const layers = 28;
126    const points = 220;
127    noFill();
128  
129    for (let layer = 0; layer < layers; layer++) {
130      const f = layer / (layers - 1);
131      const base = r * (0.17 + f * 0.76);
132      const color = palette[(layer + 1) % palette.length];
133      const alpha = 42 + 40 * (0.5 + 0.5 * sin(layer * 0.7 + t * 2));
134      stroke(color[0], color[1], color[2], alpha);
135      strokeWeight(layer % 4 === 0 ? 1.15 : 0.65);
136      beginShape();
137  
138      for (let j = 0; j <= points; j++) {
139        const a = TWO_PI * j / points;
140        const lobes = 1 + 0.105 * cos(12 * a + t * 0.8) + 0.035 * sin(7 * a - t * 0.5);
141        const ripple = 1 + 0.018 * sin(3 * a + layer * 0.43 + t * 1.8);
142        const rNow = base * lobes * ripple;
143        vertex(cos(a) * rNow, sin(a) * rNow);
144      }
145      endShape(CLOSE);
146    }
147  }
148  
149  function drawCore(r, t) {
150    const pulse = 1 + 0.08 * sin(t * 6);
151    noStroke();
152    for (let i = 8; i >= 0; i--) {
153      const d = r * (0.19 + i * 0.045) * pulse;
154      fill(98, 187, 221, 8 + i * 2);
155      circle(0, 0, d);
156    }
157  
158    stroke(191, 238, 242, 150);
159    strokeWeight(1);
160    noFill();
161    circle(0, 0, r * 0.2 * pulse);
162    noStroke();
163    fill(235, 247, 226, 220);
164    circle(0, 0, r * 0.035 * pulse);
165  
166    // A few fine rays radiate from the luminous center.
167    stroke(186, 231, 238, 85);
168    strokeWeight(0.7);
169    for (let i = 0; i < 24; i++) {
170      const a = TWO_PI * i / 24 + t * 0.3;
171      line(cos(a) * r * 0.12, sin(a) * r * 0.12,
172           cos(a) * r * 0.2, sin(a) * r * 0.2);
173    }
174  }
175  
176  function drawFrameDetails(cx, cy, unit, t) {
177    const margin = max(22, unit * 0.045);
178    noFill();
179    stroke(115, 177, 205, 70);
180    strokeWeight(1);
181    const len = 13;
182    const corners = [
183      [margin, margin, 1, 1],
184      [width - margin, margin, -1, 1],
185      [margin, height - margin, 1, -1],
186      [width - margin, height - margin, -1, -1]
187    ];
188    for (const [x, y, sx, sy] of corners) {
189      line(x, y, x + sx * len, y);
190      line(x, y, x, y + sy * len);
191    }
192  }
193  
194  function windowResized() {
195    resizeCanvas(windowWidth, windowHeight);
196  }