๐ŸŽ‡ Wobbling Anemone

BamgasiJMยท2025๋…„ 11์›” 30์ผ

p5.js Art

๋ชฉ๋ก ๋ณด๊ธฐ
35/65
post-thumbnail

๐Ÿ“ p5.js

// ์ „์—ญ ๋ณ€์ˆ˜
let lines = [];
const NUM_LINES = 24;

function setup() {
  createCanvas(windowWidth, windowHeight);
  colorMode(HSL, 360, 100, 100, 1);
  // LineSegment ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
  for (let i = 0; i < NUM_LINES; i++) {
    lines.push(new LineSegment(i, NUM_LINES));
  }
}

function draw() {
  // ํŠธ๋ ˆ์ผ ํšจ๊ณผ
  fill(0, 0, 0, 0.02);
  noStroke();
  rect(0, 0, width, height);

  const cx = width / 2;
  const cy = height / 2;
  const mx = mouseX;
  const my = mouseY;

  // ๋ชจ๋“  ์„  ์—…๋ฐ์ดํŠธ & ๋ Œ๋”
  for (let line of lines) {
    line.update(cx, cy, mx, my, frameCount);
    line.display(cx, cy);
  }

  // ๋งˆ์šฐ์Šค ํ”ผ๋“œ๋ฐฑ (์ž‘์€ ๊ณ ๋ฆฌ)
  if (dist(mx, my, cx, cy) < 250) {
    noFill();
    stroke(360, 0, 100, 0.7);
    strokeWeight(1.5);
    ellipse(mx, my, 14, 14);
  }
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}

// LineSegment ํด๋ž˜์Šค ์ •์˜
class LineSegment {
  constructor(index, total) {
    this.index = index;
    this.angle = (TWO_PI * index) / total; // ์›ํ˜• ๋ฐฐ์น˜
    this.len = 0;
    this.targetLen = random(100, 350);
    this.hue = (index * (360 / total)) % 360;
    this.baseAngle = this.angle; // ์›๋ž˜ ๊ฐ๋„ (๋งˆ์šฐ์Šค ์˜ํ–ฅ ๊ณ„์‚ฐ์šฉ ๊ธฐ์ค€)
  }

  update(cx, cy, mx, my, frameCount) {
    const dx = mx - cx;
    const dy = my - cy;
    const mouseDist = dist(mx, my, cx, cy);
    const mouseAngle = atan2(dy, dx);
    const dMax = 250;

    // ๋งˆ์šฐ์Šค ๊ทผ์ ‘๋„ (0~1)
    const influence = constrain(map(mouseDist, 0, dMax, 1, 0), 0, 1);

    // ์ด ์„ ๊ณผ ๋งˆ์šฐ์Šค ๊ฐ๋„์˜ ์ฐจ์ด โ†’ ๋น„์Šทํ•œ ๋ฐฉํ–ฅ์ผ์ˆ˜๋ก ์˜ํ–ฅ โ†‘
    let angleDiff = abs(((this.baseAngle - mouseAngle + PI) % TWO_PI) - PI);
    const proximity = map(angleDiff, 0, PI, 1, 0);

    // ๊ธธ์ด ๋ชฉํ‘œ ๊ฐฑ์‹  + ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ๋ณด๊ฐ„
    this.targetLen = map(influence * proximity, 0, 1, 120, 450);
    this.len = lerp(this.len, this.targetLen, 0.12);

    // ์ƒ‰์ƒ ๊ณ„์‚ฐ
    this.h = (this.hue + influence * 150) % 360;
    this.s = map(influence, 0, 1, 60, 100);
    this.b = map(influence, 0, 1, 40, 95);
    this.a = map(influence * proximity, 0, 1, 0.3, 0.95);
    this.weight = map(influence * proximity, 0, 1, 1.5, 8);

    // ํšŒ์ „๊ฐ’ (sin cos ํ˜ผํ•ฉ)
    this.angle =
      this.baseAngle +
      sin(frameCount * 0.06 + this.index * 0.2) * 0.2 +
      cos(frameCount * 0.03) * 0.3;
  }

  display(cx, cy) {
    push();
    translate(cx, cy);
    rotate(this.angle);

    // ์„ 
    stroke(this.h, this.s, this.b, this.a);
    strokeWeight(this.weight);
    line(0, 0, this.len, 0);

    // ๋์  ๊ฐ•์กฐ
    fill(this.h, this.s, this.b, this.a * 0.7);
    noStroke();
    ellipse(this.len, 0, 5, 5);
    pop();
  }
}

profile
Coding Art with Blender / oF / Processing / p5.js / nannou

0๊ฐœ์˜ ๋Œ“๊ธ€