Media Art ProgrammingWeek 04 · Period 03 Handout

p5.js / Media Art Programming

4주차 3교시 — 학생 주도 실습: 인터랙티브 스케치

Conditionals and Interaction 주제의 학생용 강의 자료입니다.

WEEK 04 PERIOD 03 P5.JS MEDIA ART

4주차 3교시 — 학생 주도 실습: 인터랙티브 스케치

강의 아웃라인: week-04-outline 이전 교시: week-04-period2-student (마우스·키보드 인터랙션) 다음 주차: week-05-outline (애니메이션, random·map·constrain)

항목 내용
대상 P5.js 입문자 (테크아트 전공)
소요 시간 45분
사전 준비 1교시 조건문, 2교시 마우스·키보드 인터랙션·상태 변수
결과물 조건문·인터랙션 기반 인터랙티브 스케치 1점
실습 목표
  • 1·2교시의 조건문·마우스/키보드 인터랙션·상태 변수를 결합해 인터랙티브 스케치를 제작합니다
  • console.log()로 값을 확인하며 스스로 디버깅합니다
  • 3주차 기술(for문·HSB·잔상)을 인터랙션과 통합해 시각적으로 완성합니다

완성 기준 안내 + 실습 시작

3교시에서는 직접 인터랙티브 스케치를 만듭니다. 세 단계 완성 기준을 보고, 자신이 지금 어디쯤인지 스스로 판단할 수 있습니다.

완성 기준

단계 이름 완성 기준 핵심
기본 동작하는 스케치 마우스로 그리기 + 키보드(r/g/b)로 색상 전환 + c로 초기화 “그리고, 바꾸고, 지울 수 있다”
표준 모드가 있는 스케치 기본 + 상태 변수로 모드 추가 (도형 전환, mouseButton 지우기, brushSize 조절 중 1개 이상) “선택지가 있다”
심화 시각적으로 완성된 스케치 표준 + 3주차 기술 결합 (HSB 색상, 잔상 효과, for문 패턴, pmouseX 선 드로잉 중 1개 이상) “보기에도 좋다”

만 해도 오늘 목표 완료입니다. 까지 가면 충분히 훌륭합니다. 자기 속도에 맞게 진행하세요. 그리고 막히면 console.log()를 쓰세요. 변수에 어떤 값이 들어 있는지 콘솔에서 확인하면 문제 원인을 찾기 쉽습니다.

세 가지 방향

세 방향 중 하나를 골라 시작합니다 (자유롭게 섞어도 됩니다).

방향 설명 핵심 기술
A. 인터랙티브 드로잉 도구 마우스로 그리기 + 키보드로 도구 전환 mouseIsPressed, pmouseX, keyPressed(), key
B. 인터랙티브 패턴 3주차 패턴에 마우스/키보드 반응 추가 for문, dist(), mousePressed()
C. 리액티브 비주얼 마우스 위치에 실시간 반응하는 그래픽 mouseX/Y, dist(), if/else

무엇을 선택해야 할지 모르겠으면 A(드로잉)부터 시작하세요. 스타터 코드가 이미 A 기반입니다. 4주차에는 실습과제 제출이 없으니 부담 없이 실험해보세요.

환경 설정 + 스타터 코드

  1. P5.js Web Editor 접속 (로그인 확인)
  2. File → New → 스케치 이름을 week04-interactive로 변경
  3. 아래 스타터 코드를 복사-붙여넣기
// === 상태 변수 (draw() 밖에 선언) ===
let brushColor;
let brushSize = 20;

// === setup(): 한 번 실행 ===
function setup() {
  createCanvas(400, 400);
  background(255);
  brushColor = color(0, 150, 255);
}

// === draw(): 매 프레임 실행 (1초에 약 60번) ===
function draw() {
  // 여기에 그리기 코드

  // 마우스를 누르면 원 그리기
  if (mouseIsPressed) {
    noStroke();
    fill(brushColor);
    ellipse(mouseX, mouseY, brushSize, brushSize);
  }
}

// === mousePressed(): 클릭 시 1회 ===
function mousePressed() {
  // 여기에 클릭 이벤트 코드
}

// === keyPressed(): 키 누를 때 1회 ===
function keyPressed() {
  // 여기에 키보드 이벤트 코드
}

실행 버튼()을 눌러 마우스를 누르면서 움직이면 파란 원이 그려집니다. 여기서부터 시작합니다.


Step 1 — 기본: “그리고, 바꾸고, 지울 수 있다”

이 Step이 끝나면: 마우스로 그리고, 키보드로 색상을 바꾸고, c로 화면을 지울 수 있다.

방향 A: 드로잉 도구 — 색상 전환 추가

스타터 코드의 keyPressed()에 색상 전환을 추가합니다.

function keyPressed() {
  if (key === 'r') {
    brushColor = color(255, 0, 0);    // r: 빨강
  } else if (key === 'g') {
    brushColor = color(0, 200, 0);    // g: 초록
  } else if (key === 'b') {
    brushColor = color(0, 150, 255);  // b: 파랑
  } else if (key === 'c') {
    background(255);                  // c: 캔버스 지우기
  }
}

이제 r, g, b로 색을 바꾸면서 그릴 수 있고, c로 초기화할 수 있습니다.

업그레이드 팁

2교시에서 배운 pmouseX/pmouseY로 부드러운 선을 그리고 싶다면 draw() 안의 ellipse()를 아래 코드로 바꿔보세요.

// draw() 안 — ellipse 대신 line으로 교체
if (mouseIsPressed) {
  stroke(brushColor);
  strokeWeight(brushSize / 4);
  line(pmouseX, pmouseY, mouseX, mouseY);  // 부드러운 선!
}

방향 B: 인터랙티브 패턴 — 토글 추가

스타터 코드를 완전히 교체합니다. 3주차 격자 패턴 + 클릭 토글.

let isRainbow = true;

function setup() {
  createCanvas(400, 400);
  colorMode(HSB, 360, 100, 100);
}

function draw() {
  background(0, 0, 10);
  noStroke();

  for (let i = 0; i < 10; i++) {
    for (let j = 0; j < 10; j++) {
      let x = i * 40 + 20;
      let y = j * 40 + 20;

      if (isRainbow) {
        fill((i + j) * 25, 80, 100);    // 무지개 모드
      } else {
        fill(0, 0, (i + j) * 7);        // 흑백 모드
      }
      ellipse(x, y, 25, 25);
    }
  }
}

function mousePressed() {
  isRainbow = !isRainbow;  // 클릭으로 모드 토글
}

클릭할 때마다 무지개 ↔ 흑백이 전환됩니다. 3주차 패턴 + 토글의 결합입니다.

방향 C: 리액티브 비주얼 — 마우스 반응 패턴

스타터 코드를 완전히 교체합니다.

function setup() {
  createCanvas(400, 400);
  colorMode(HSB, 360, 100, 100);
}

function draw() {
  background(0, 0, 10);
  noStroke();

  for (let i = 0; i < 10; i++) {
    for (let j = 0; j < 10; j++) {
      let x = i * 40 + 20;
      let y = j * 40 + 20;
      let d = dist(mouseX, mouseY, x, y);

      if (d < 80) {
        fill((i + j) * 25, 80, 100);  // 가까이: 밝은 색
        ellipse(x, y, 30, 30);        // 크게
      } else {
        fill(0, 0, 30);               // 멀리: 어두운 색
        ellipse(x, y, 10, 10);        // 작게
      }
    }
  }
}

마우스를 움직이면 가까운 원이 커지고 밝아집니다. dist()의 실전 활용입니다.

달성 체크

여기까지 하면 기본 달성 — “그리고, 바꾸고, 지울 수 있다”


Step 2 — 표준: “선택지가 있다”

이 Step이 끝나면: 상태 변수를 추가하여 사용자에게 2가지 이상의 선택지(모드, 도구, 크기 등)를 제공할 수 있다.

기본을 완성했다면, 상태 변수를 하나 더 추가해서 모드나 옵션을 만듭니다.

방향 A: 도형 전환 + mouseButton 지우기

도형 전환shapeMode 상태 변수를 추가합니다.

let shapeMode = 'circle';  //  상태 변수 추가 (draw() 밖)

function draw() {
  if (mouseIsPressed) {
    noStroke();
    fill(brushColor);

    //  도형 모드에 따라 다른 도형
    if (shapeMode === 'circle') {
      ellipse(mouseX, mouseY, brushSize, brushSize);
    } else if (shapeMode === 'square') {
      rect(mouseX - brushSize/2, mouseY - brushSize/2, brushSize, brushSize);
    }
  }
}

function keyPressed() {
  // 색상 전환 (Step 1 코드 유지)
  if (key === 'r') {
    brushColor = color(255, 0, 0);
  } else if (key === 'g') {
    brushColor = color(0, 200, 0);
  } else if (key === 'b') {
    brushColor = color(0, 150, 255);
  } else if (key === 'c') {
    background(255);
  }

  //  도형 전환 추가
  if (key === '1') {
    shapeMode = 'circle';
  } else if (key === '2') {
    shapeMode = 'square';
  }
}

1을 누르면 원, 2를 누르면 사각형으로 그려집니다.

mouseButton 지우기 — 2교시에서 배운 mouseButton을 활용합니다.

// draw() 안의 mouseIsPressed 블록을 이렇게 수정
if (mouseIsPressed) {
  noStroke();
  if (mouseButton === LEFT) {
    fill(brushColor);
    ellipse(mouseX, mouseY, brushSize, brushSize);  // 왼쪽: 그리기
  } else if (mouseButton === RIGHT) {
    fill(255);
    ellipse(mouseX, mouseY, brushSize * 2, brushSize * 2);  // 오른쪽: 지우기
  }
}

왼쪽 클릭은 그리기, 오른쪽 클릭은 지우기입니다.

방향 B: 키보드로 색상 팔레트 전환

let isRainbow = true;
let palette = 'warm';  //  상태 변수 추가

function draw() {
  background(0, 0, 10);
  noStroke();

  for (let i = 0; i < 10; i++) {
    for (let j = 0; j < 10; j++) {
      let x = i * 40 + 20;
      let y = j * 40 + 20;

      if (isRainbow) {
        //  palette에 따라 색상 범위가 달라짐
        if (palette === 'warm') {
          fill((i + j) * 15, 80, 100);        // 빨강~노랑 계열
        } else {
          fill((i + j) * 15 + 180, 80, 100);  // 파랑~보라 계열
        }
      } else {
        fill(0, 0, (i + j) * 7);
      }
      ellipse(x, y, 25, 25);
    }
  }
}

function keyPressed() {
  if (key === 'w') {
    palette = 'warm';    // 따뜻한 색
  } else if (key === 'p') {
    palette = 'cool';    // 차가운 색
  }
}

클릭으로 무지개/흑백 토글, w/p 키로 따뜻한 색↔차가운 색 팔레트 전환. 마우스와 키보드를 동시에 활용합니다.

방향 C: 마우스 클릭으로 반응 범위 변경

let radius = 80;  //  상태 변수 추가

function mousePressed() {
  radius += 20;
  if (radius > 200) {
    radius = 40;  // 최대치 넘으면 리셋
  }
}

클릭할 때마다 반응 범위가 커지다가, 200을 넘으면 다시 작아집니다.

중요: Step 1에서 if (d < 80)을 사용했다면, 그 80radius로 바꿔야 클릭이 실제로 반영됩니다.

// Step 1의 draw() 안 — 80을 radius로 교체
if (d < radius) {          //  80 → radius로 변경!
  fill((i + j) * 25, 80, 100);
  ellipse(x, y, 30, 30);
}
동작하지 않으면 console.log()

mousePressed() 안에 console.log("radius:", radius);를 넣어보세요. 클릭할 때마다 radius 값이 바뀌는지 콘솔에서 확인할 수 있습니다.

달성 체크

여기까지 하면 표준 달성 — “선택지가 있다”


Step 3 — 심화: “보기에도 좋다”

이 Step이 끝나면: 3주차 기술을 결합하여 시각적으로 풍성하고 자기만의 스타일이 드러나는 스케치를 완성한다.

기본 기능이 다 되면, 3주차에서 배운 것들을 결합해 시각적으로 완성도 있게 만듭니다.

아이디어 1: pmouseX로 부드러운 선 드로잉

// draw() 안 — ellipse 대신 line 사용
if (mouseIsPressed) {
  stroke(brushColor);
  strokeWeight(brushSize / 4);
  line(pmouseX, pmouseY, mouseX, mouseY);
}

이것만 바꿔도 드로잉 결과물이 훨씬 자연스러워집니다.

아이디어 2: HSB 색상 + 마우스 위치로 색상 매핑

// setup() 안에 추가
colorMode(HSB, 360, 100, 100);

// draw() 안 — mouseIsPressed 블록 내부
if (mouseIsPressed) {
  noStroke();
  //  마우스 x좌표에 따라 hue가 0~360으로 변화
  let hue = map(mouseX, 0, width, 0, 360);
  fill(hue, 80, 100);
  ellipse(mouseX, mouseY, brushSize, brushSize);
}

map()은 ’마우스 x좌표(0~400)를 hue(0~360)로 변환’해줍니다.

아이디어 3: 잔상 + 투명도 효과

function draw() {
  // 완전히 지우지 않고 반투명으로 덮기 → 잔상 효과
  background(0, 0, 100, 20);  //  네 번째 값 = alpha (투명도)

  if (mouseIsPressed) {
    noStroke();
    fill(brushColor);
    ellipse(mouseX, mouseY, brushSize, brushSize);
  }
}

3주차에서 본 잔상 효과입니다. alpha 값을 낮추면 이전 프레임이 서서히 사라집니다.

아이디어 4: for문으로 스프레이 효과

// draw() 안 — 마우스 주변에 여러 원 동시 그리기
if (mouseIsPressed) {
  noStroke();
  for (let i = 0; i < 5; i++) {
    let offsetX = random(-20, 20);
    let offsetY = random(-20, 20);
    fill(brushColor);
    ellipse(mouseX + offsetX, mouseY + offsetY, brushSize * 0.5, brushSize * 0.5);
  }
}

한 번에 원 하나 대신 5개를 흩뿌리듯 그립니다. random()으로 위치를 약간씩 흩뜨리면 스프레이 느낌이 납니다.

달성 체크

여기까지 하면 심화 달성 — “보기에도 좋다”


Step 4 — 확장 (선택, 남는 시간)

까지 했다면, 더 도전해볼 수 있는 것들입니다.

확장 A: 속도 기반 필압 드로잉

// draw() 안
if (mouseIsPressed) {
  let speed = dist(mouseX, mouseY, pmouseX, pmouseY);
  let weight = constrain(speed * 1.5, 1, 30);  // 속도→굵기 변환

  stroke(brushColor);
  strokeWeight(weight);
  line(pmouseX, pmouseY, mouseX, mouseY);
}

빠르게 움직이면 굵게, 느리게 움직이면 가늘게 — 실제 붓처럼 느껴집니다. constrain()은 ’최소 1, 최대 30으로 범위 제한’하는 함수입니다 (5주차에서 배움).

확장 B: dist()로 원형 버튼 구현

// draw() 맨 아래에 버튼 그리기 추가
function draw() {
  // ... 기존 드로잉 코드 ...

  // 우측 하단에 초기화 버튼
  if (dist(mouseX, mouseY, 370, 370) < 20) {
    fill(255, 100, 100);  // hover: 밝은 빨강
  } else {
    fill(200, 50, 50);
  }
  noStroke();
  ellipse(370, 370, 40, 40);
}

function mousePressed() {
  // 버튼 클릭 감지
  if (dist(mouseX, mouseY, 370, 370) < 20) {
    background(255);  // 캔버스 초기화
  }
}

확장 C: 클릭 카운터로 비주얼 변화

let clickCount = 0;

function mousePressed() {
  clickCount = clickCount + 1;
  console.log("clicks:", clickCount);  //  콘솔에서 확인
}

function draw() {
  // clickCount에 따라 배경색 변화
  let bgHue = (clickCount * 30) % 360;
  background(bgHue, 30, 95);

  // ... 나머지 드로잉 코드 ...
}

마무리

스케치 저장 확인

지금 바로 Ctrl+S (Mac은 Cmd+S)로 저장하세요. 오늘 제출할 과제는 아니지만, 나중에 참고할 수 있으니 저장해두세요.

완성 기준 최종 확인

단계 완성 기준 체크
기본 그리고 + 바꾸고 + 지울 수 있다
표준 상태 변수로 모드/옵션 추가
심화 3주차 기술 결합으로 시각적 완성

만 했어도 오늘 목표 완료입니다. 다음에 이어서 발전시킬 수도 있습니다.

오늘 배운 것 3줄 정리

3교시 핵심 요약
  1. 조건문 + 인터랙션 = 인터랙티브 작품: if/else로 판단하고, 마우스/키보드로 입력 받고, 화면에 반응
  2. 상태 변수 패턴: 변수 선언(draw 밖) → 이벤트로 변경 → draw()에서 렌더링
  3. 막히면 console.log(): 값을 확인하면 무엇이 잘못됐는지 찾을 수 있다

5주차 예고

오늘 인터랙션으로 ‘반응하는 작품’을 만들었습니다. 다음 주에는 ‘스스로 움직이는 작품’을 만듭니다. 오늘 count = count + 1로 카운터를 만들었습니다. 같은 원리로 x = x + speed를 하면 도형이 매 프레임 움직입니다. 이것이 다음 주 애니메이션의 핵심입니다. 오늘 만든 인터랙티브 스케치에 움직임을 더하면 실습과제 2의 기초가 됩니다. 저장해두세요.

(선택) 사전 학습 영상

미리 보면 다음 주 내용을 이해하기 쉬워집니다.

영상 내용 시간
The Coding Train 3.1 — Conditional Statements 조건문 복습 약 12분
The Coding Train 3.3 — else, else if, AND, OR 논리 연산자 복습 약 12분