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주차에는 실습과제 제출이 없으니 부담 없이 실험해보세요.
환경 설정 + 스타터 코드
- P5.js Web Editor 접속 (로그인 확인)
- File → New → 스케치 이름을
week04-interactive로 변경 - 아래 스타터 코드를 복사-붙여넣기
// === 상태 변수 (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)을 사용했다면, 그80을radius로 바꿔야 클릭이 실제로 반영됩니다.
// Step 1의 draw() 안 — 80을 radius로 교체
if (d < radius) { // 80 → radius로 변경!
fill((i + j) * 25, 80, 100);
ellipse(x, y, 30, 30);
}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줄 정리
- 조건문 + 인터랙션 = 인터랙티브 작품: if/else로 판단하고, 마우스/키보드로 입력 받고, 화면에 반응
- 상태 변수 패턴: 변수 선언(draw 밖) → 이벤트로 변경 → draw()에서 렌더링
- 막히면 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분 |