Learning
레슨 7 / 8·25분

실전: 인터랙티브 아트

인터랙티브 아트 프로젝트

지금까지 배운 p5.js 기능을 모두 활용하여 마우스와 키보드에 반응하는 인터랙티브 제너러티브 아트 작품을 만듭니다. 파티클 시스템, 색상 변환, 수학 함수, 좌표 변환을 결합하여 독창적인 비주얼을 구현합니다.

javascript
// 제너러티브 꽃 패턴
let petals = [];
let colorPalette;
let mode = 0;

function setup() {
  createCanvas(800, 800);
  colorMode(HSB, 360, 100, 100, 100);
  background(0);
  colorPalette = [0, 30, 60, 180, 270, 330]; // 색상 팔레트
}

function draw() {
  // 반투명 배경으로 잔상
  background(0, 0, 0, 3);

  // 마우스 움직임에 따라 꽃잎 생성
  let speed = dist(mouseX, mouseY, pmouseX, pmouseY);
  if (speed > 2) {
    let hue = colorPalette[int(random(colorPalette.length))];
    petals.push({
      x: mouseX,
      y: mouseY,
      angle: random(TWO_PI),
      size: random(20, 60),
      hue: hue,
      life: 100,
      rotSpeed: random(-0.02, 0.02),
      petalCount: int(random(5, 12)),
    });
  }

  // 꽃잎 렌더링
  for (let i = petals.length - 1; i >= 0; i--) {
    let p = petals[i];
    drawFlower(p);
    p.angle += p.rotSpeed;
    p.life -= 0.5;
    if (p.life <= 0) petals.splice(i, 1);
  }
}
javascript
// 꽃 그리기 함수
function drawFlower(p) {
  push();
  translate(p.x, p.y);
  rotate(p.angle);

  let alpha = map(p.life, 0, 100, 0, 80);

  for (let j = 0; j < p.petalCount; j++) {
    rotate(TWO_PI / p.petalCount);
    fill(p.hue, 70, 90, alpha);
    noStroke();
    ellipse(p.size / 3, 0, p.size, p.size / 3);
  }

  // 꽃 중심
  fill(60, 90, 100, alpha);
  ellipse(0, 0, p.size / 4);
  pop();
}

function keyPressed() {
  if (key === 'c') background(0);          // 화면 지우기
  if (key === 's') saveCanvas('art', 'png'); // 저장
  if (key === '1') mode = 0;                // 꽃 모드
  if (key === '2') mode = 1;                // 기하학 모드
}

function mousePressed() {
  // 클릭하면 원형 폭발
  for (let i = 0; i < 20; i++) {
    let angle = random(TWO_PI);
    let dist = random(50, 150);
    petals.push({
      x: mouseX + cos(angle) * dist,
      y: mouseY + sin(angle) * dist,
      angle: angle,
      size: random(30, 80),
      hue: colorPalette[int(random(colorPalette.length))],
      life: 100,
      rotSpeed: random(-0.03, 0.03),
      petalCount: int(random(5, 12)),
    });
  }
}
javascript
// 기하학적 패턴 모드
function drawGeometricPattern() {
  push();
  translate(width / 2, height / 2);
  let t = frameCount * 0.01;

  for (let i = 0; i < 100; i++) {
    let angle = map(i, 0, 100, 0, TWO_PI * 3);
    let r = map(sin(angle * 3 + t), -1, 1, 50, 300);
    let x = cos(angle + t * 0.5) * r;
    let y = sin(angle + t * 0.5) * r;

    let hue = map(i, 0, 100, 0, 360);
    fill(hue, 80, 100, 60);
    noStroke();

    let size = map(sin(t + i * 0.1), -1, 1, 3, 15);
    ellipse(x, y, size);
  }
  pop();
}

// saveCanvas로 작품 저장
// saveCanvas('myArt', 'png');
// saveFrames('frame', 'png', 5, 25); // 5초간 25fps로 프레임 저장
  • push() / pop() — 변환 상태 격리로 복잡한 패턴 구성
  • dist(x1, y1, x2, y2) — 두 점 사이의 거리 계산
  • pmouseX / pmouseY — 이전 프레임의 마우스 좌표
  • saveCanvas(name, ext) — 캔버스를 이미지로 저장
  • TWO_PI, HALF_PI, QUARTER_PI — 자주 쓰는 각도 상수
💡

제너러티브 아트에서는 무작위성과 규칙성의 균형이 핵심입니다. random()으로 다양성을, noise()와 sin/cos로 일관성을 부여하세요. 결과물이 마음에 들면 saveCanvas()로 저장할 수 있습니다.