7주차 3교시 — 학생 주도 실습: 클래스를 활용한 다중 오브젝트 작품
강의 아웃라인: week-07-outline 이전 교시: week-07-period2-student (객체 배열과 클래스 확장) 다음 주차: 8주차 — 중간고사 (1~7주차)
| 항목 | 내용 |
|---|---|
| 대상 | P5.js 입문자 (테크아트 전공) |
| 소요 시간 | 45분 |
| 사전 준비 | 1교시 class 기본 문법, 2교시 객체 배열·클래스 확장 |
| 결과물 | 클래스·객체 배열 기반 다중 오브젝트 스케치 1점 (실습과제 3) |
-
class문법으로 독립 객체를 정의하고, 객체 배열로 다수의 객체를 생성·관리하는 작품을 제작합니다 - 1~6주차 개념(변수·조건문·반복문·함수·배열)이 클래스 안에서 통합되는 것을 체감합니다
완성 기준 안내 + 실습 시작
1-2교시에 배운 클래스와 객체 배열을 합쳐서 직접 작품을 만드는 시간입니다. 세 단계 완성 기준이 있습니다.
완성 기준
| 단계 | 이름 | 완성 기준 | 핵심 |
|---|---|---|---|
| 기본 | 클래스로 움직이는 객체 | class 정의(constructor + move + display) + 객체 배열로 10개 이상 + for문 순회 | “클래스로 여러 개가 움직인다” |
| 표준 | 기능 확장 + 인터랙션 | 기본 + bounce() 메서드 + 랜덤 색상/크기 + mousePressed()로 클릭 추가 | “튕기고, 예쁘고, 반응한다” |
| 심화 | 완성된 작품 | 표준 + 시각 효과 (잔상, 바운스 색변경, HSB 등) + 키보드 인터랙션 | “보기 좋고, 인터랙션도 풍부하다” |
만 해도 오늘 목표 완료입니다. 까지 가면 충분히 도전적인 단계입니다. 자기 속도에 맞게 진행하세요!
이 스케치가 곧 실습과제 3입니다. 수업 중에 기본을 만들고, 중간고사(8주차) 전까지 발전시켜서 P5.js 웹 에디터 링크로 제출합니다. 제출 완료 시 만점입니다.
세 가지 방향
세 방향 중 하나를 골라 시작합니다. 자유롭게 섞어도 됩니다.
| 방향 | 설명 | 핵심 기술 | 1-2교시 연결 |
|---|---|---|---|
| A. 바운싱 볼 월드 | Ball 클래스 + 객체 배열 + 클릭으로 추가 | class, 배열, 바운싱, mousePressed | 2교시 미니 실습 확장 |
| B. 파티클 아트 | 마우스에서 파티클 생성 + 중력 효과 | class, push, speedY += 0.1, 잔상 | 2교시 사례 1 확장 |
| C. 자유 주제 | 나만의 클래스 설계 (별, 꽃, 눈, 비 등) | class 설계, 창의적 display() | 새로운 방향 |
무엇을 골라야 할지 모르겠으면 A(바운싱 볼 월드)부터 시작하세요. 2교시에서 이미 만들어 봤으므로 가장 친숙합니다.
환경 설정
- P5.js Web Editor 접속 (로그인 확인)
- File → New → 스케치 이름을
week07-class로 변경 - 아래 세 방향 중 하나를 골라 스타터 코드를 복사-붙여넣기
스타터 코드
방향 A: 바운싱 볼 월드
class Ball {
constructor(x, y, speedX, speedY) {
this.x = x;
this.y = y;
this.speedX = speedX;
this.speedY = speedY;
this.size = 30;
}
move() {
this.x += this.speedX;
this.y += this.speedY;
}
display() {
fill(100, 150, 255);
noStroke();
ellipse(this.x, this.y, this.size);
}
}
let balls = [];
function setup() {
createCanvas(400, 400);
// 시작할 때 공 5개 생성
for (let i = 0; i < 5; i++) {
balls.push(new Ball(
random(width), random(height),
random(-3, 3), random(-3, 3)
));
}
}
function draw() {
background(30);
for (let i = 0; i < balls.length; i++) {
balls[i].move();
// TODO: balls[i].bounce(); ← 이 메서드를 만들어보세요!
balls[i].display();
}
}
// TODO: mousePressed()로 클릭하면 공 추가하기
// TODO: keyPressed()로 키보드 이벤트 추가하기실행하면 파란 공 5개가 움직입니다. 바운싱이 아직 없어서 화면 밖으로 나갑니다. 여기서부터 시작합니다.
방향 B: 파티클 아트
class Particle {
constructor(x, y) {
this.x = x;
this.y = y;
this.speedX = random(-2, 2);
this.speedY = random(-5, -1);
this.size = random(5, 12);
}
update() {
this.x += this.speedX;
this.y += this.speedY;
this.speedY += 0.1; // 중력
}
display() {
fill(255, 200);
noStroke();
ellipse(this.x, this.y, this.size);
}
}
let particles = [];
function setup() {
createCanvas(400, 400);
}
function draw() {
background(0, 0, 0, 40); // 잔상 효과
// 마우스 누르고 있으면 파티클 생성
if (mouseIsPressed) {
particles.push(new Particle(mouseX, mouseY));
}
for (let i = 0; i < particles.length; i++) {
particles[i].update();
particles[i].display();
}
// 화면 밖 파티클 제거
for (let i = particles.length - 1; i >= 0; i--) {
if (particles[i].y > height) {
particles.splice(i, 1);
}
}
}
// TODO: 파티클에 색상 추가하기
// TODO: 키보드로 중력 방향 바꾸기마우스를 누르고 있으면 하얀 파티클이 위로 솟아올랐다 떨어집니다. 여기서부터 시작합니다.
방향 C: 자유 주제 (눈 내리기 예시)
class Snowflake {
constructor() {
this.x = random(width);
this.y = random(-50, 0);
this.size = random(3, 8);
this.speed = random(1, 3);
this.drift = random(-0.5, 0.5); // 좌우 흔들림
}
update() {
this.y += this.speed;
this.x += this.drift;
}
display() {
fill(255);
noStroke();
ellipse(this.x, this.y, this.size);
}
}
let snowflakes = [];
function setup() {
createCanvas(400, 400);
}
function draw() {
background(20, 20, 40);
// 매 프레임 눈 1개 생성
snowflakes.push(new Snowflake());
for (let i = 0; i < snowflakes.length; i++) {
snowflakes[i].update();
snowflakes[i].display();
}
// 화면 밖 눈 제거
for (let i = snowflakes.length - 1; i >= 0; i--) {
if (snowflakes[i].y > height) {
snowflakes.splice(i, 1);
}
}
}
// TODO: 눈 색상이나 크기를 바꿔 보세요
// TODO: 마우스 근처에서 눈이 밀려나게 만들어보세요눈이 위에서 아래로 내립니다. 각 눈송이는 서로 다른 크기, 속도, 좌우 흔들림을 가집니다. 이 코드를 바탕으로 자유롭게 바꿔 보세요.
Step 1 — 스타터 코드 실행 + 숫자 바꿔보기 → 기본 달성
목표: 스타터 코드가 동작하는지 확인하고, 숫자를 바꿔보며 클래스 구조를 체감합니다.
이 단계를 마치면 기본 달성!
방향 A 기준
코드 분석 포인트: 1. class Ball { } —
설계도 전체 구조 2. constructor(x, y, speedX, speedY) —
매개변수로 위치와 속도를 받음 3. this.x,
this.y, this.size — 프로퍼티에 저장 4.
move(), display() — 메서드로 동작 정의 5.
balls.push(new Ball(...)) — 배열에 객체 추가 6.
balls[i].move(), balls[i].display() —
for문으로 전체 순회
1-2교시에서 배운 내용이 모두 여기에 있습니다. 하나씩 확인해 보세요.
이 단계에서 할 것: - 공 개수를 5에서
20으로 바꿔보기
(for (let i = 0; i < 20; i++)) - 실행해서 공 20개가
되는지 확인 - this.size = 30을
this.size = random(20, 50)으로 바꿔보기 - 속도 범위를
random(-3, 3) → random(-5, 5)로 바꿔보기
힌트 (막히면 펼쳐보세요)
setup() 안의 for문에서
i < 5를 i < 20으로 바꾸면 됩니다.
balls.length가 자동으로 20이 되므로 draw()는
수정할 필요 없습니다.
this.size는 class Ball의
constructor() 안에서 바꾸면 됩니다. 30 대신
random(20, 50)을 넣으면 공마다 다른 크기가 됩니다.
방향 B 기준
이 단계에서 할 것: - 한 번에 생성하는 파티클 수
바꾸기 (1개 → 3개) - this.size의 random()
범위를 바꿔보기 - 중력 값 0.1을 0.3으로
바꿔보기 — 더 빨리 떨어짐
방향 C 기준
이 단계에서 할 것: - 눈 크기 범위를 바꿔보기
(random(3, 8) → random(2, 15)) - 눈 속도를
바꿔보기 (random(1, 3) → random(0.5, 5)) -
배경색을 바꿔보기 — 밤하늘 색, 회색 하늘 등
Step 2 — 기능 확장 + 인터랙션 추가 → 표준 달성
목표: 클래스에 메서드를 추가하고, 마우스 인터랙션을 넣습니다.
이 단계를 마치면 표준 달성!
방향 A 기준: bounce() 추가 + 색상 + 클릭 인터랙션
공이 화면 밖으로 나가는 문제를 해결하기 위해 bounce()
메서드를 추가합니다. 이 메서드가 공을 벽에서 튕기게 만듭니다.
할 일 1 — bounce() 메서드 추가:
// class Ball { } 안에 추가
bounce() {
if (this.x > width || this.x < 0) {
this.speedX *= -1;
}
if (this.y > height || this.y < 0) {
this.speedY *= -1;
}
}draw()에서 balls[i].bounce();를 호출합니다.
주석 처리된 TODO 부분입니다.
할 일 2 — 랜덤 색상 추가:
constructor에서
this.c = color(random(255), random(255), random(255));를
추가하고, display()에서 fill(100, 150, 255)를
fill(this.c)로 바꿉니다.
할 일 3 — 클릭으로 공 추가:
function mousePressed() {
balls.push(new Ball(
mouseX, mouseY,
random(-3, 3), random(-3, 3)
));
}마우스를 클릭한 위치에서 랜덤 속도의 공이 추가됩니다.
힌트 (막히면 펼쳐보세요)
bounce()메서드는display()아래에, class의 중괄호}안에 넣으세요draw()에서balls[i].move();다음 줄에balls[i].bounce();를 추가this.c를 constructor에 추가할 때,this.size다음 줄에 넣으면 됩니다mousePressed()함수는draw()밖에 독립적으로 선언해야 합니다
에러가 나면 확인할 것: - bounce() 안에
function을 쓰지 않았는지 (클래스 안에서는 function 안 씀!)
- this.c에서 this를 빠뜨리지 않았는지
방향 B 기준: 색상 추가 + 클릭 폭발
할 일 1 — constructor에 색상 추가:
this.c = color(random(255), random(100, 255), random(100));할 일 2 — display()에서 색상 사용:
fill(this.c);할 일 3 — 클릭하면 한 번에 많은 파티클 폭발:
function mousePressed() {
for (let i = 0; i < 20; i++) {
particles.push(new Particle(mouseX, mouseY));
}
}방향 C 기준: 투명도 + 클릭 인터랙션
할 일 1 — constructor에 투명도 추가:
this.alpha = random(100, 255);할 일 2 — display()에서 사용:
fill(255, this.alpha);할 일 3 — 클릭하면 눈 폭풍 (한번에 30개):
function mousePressed() {
for (let i = 0; i < 30; i++) {
snowflakes.push(new Snowflake());
}
}Step 3 — 시각 효과 + 키보드 → 심화 달성
목표: 잔상, 색상 변경, HSB, 키보드 인터랙션 등으로 작품을 발전시킵니다.
이 단계를 마치면 심화 달성!
잔상 효과 (전 방향 공통)
// background(30); 을 아래로 교체
background(30, 30, 30, 50); // 반투명 배경 → 잔상 효과배경의 투명도를 낮추면 이전 프레임이 살짝 남아서 궤적이 보입니다.
바운스 시 색 변경 (방향 A)
bounce() {
if (this.x > width || this.x < 0) {
this.speedX *= -1;
this.c = color(random(255), random(255), random(255)); // 색 변경!
}
if (this.y > height || this.y < 0) {
this.speedY *= -1;
this.c = color(random(255), random(255), random(255));
}
}HSB 색상 모드 (전 방향 공통)
function setup() {
createCanvas(400, 400);
colorMode(HSB, 360, 100, 100); // HSB 모드!
// ...
}
// constructor에서 색상 생성 시:
this.c = color(random(360), 80, 100); // 선명한 랜덤 색상키보드 인터랙션 (방향 A)
function keyPressed() {
if (key === 'c') {
balls = []; // 모든 공 삭제
}
if (key === 'r') {
// 공 10개 다시 생성
for (let i = 0; i < 10; i++) {
balls.push(new Ball(
random(width), random(height),
random(-3, 3), random(-3, 3)
));
}
}
}정보 표시 (전 방향 공통)
// draw() 맨 마지막에 추가
fill(255);
noStroke();
textSize(14);
text("objects: " + balls.length, 10, 20);파티클 크기 줄이기 (방향 B — 수명 효과)
// update() 안에 추가
this.size -= 0.1; // 점점 작아짐
// display() 수정 — 크기가 0 이하면 안 그림
display() {
if (this.size > 0) {
fill(this.c);
noStroke();
ellipse(this.x, this.y, this.size);
}
}완성 예시 — 방향 A 바운싱 볼 월드 ( 심화)
class Ball {
constructor(x, y, speedX, speedY) {
this.x = x;
this.y = y;
this.speedX = speedX;
this.speedY = speedY;
this.size = random(15, 45);
this.c = color(random(360), 80, 100);
}
move() {
this.x += this.speedX;
this.y += this.speedY;
}
bounce() {
if (this.x > width || this.x < 0) {
this.speedX *= -1;
this.c = color(random(360), 80, 100);
}
if (this.y > height || this.y < 0) {
this.speedY *= -1;
this.c = color(random(360), 80, 100);
}
}
display() {
fill(this.c);
noStroke();
ellipse(this.x, this.y, this.size);
}
}
let balls = [];
function setup() {
createCanvas(400, 400);
colorMode(HSB, 360, 100, 100);
for (let i = 0; i < 20; i++) {
balls.push(new Ball(
random(width), random(height),
random(-4, 4), random(-4, 4)
));
}
}
function draw() {
background(0, 0, 10, 50); // 잔상 효과
for (let i = 0; i < balls.length; i++) {
balls[i].move();
balls[i].bounce();
balls[i].display();
}
// 정보 표시
fill(0, 0, 100);
noStroke();
textSize(14);
text("Bouncing Ball World", 10, 20);
text("balls: " + balls.length + " | click to add | 'c' to clear", 10, 38);
}
function mousePressed() {
balls.push(new Ball(
mouseX, mouseY,
random(-4, 4), random(-4, 4)
));
}
function keyPressed() {
if (key === 'c') {
balls = [];
}
if (key === 'r') {
for (let i = 0; i < 10; i++) {
balls.push(new Ball(
random(width), random(height),
random(-4, 4), random(-4, 4)
));
}
}
}실행 결과: - 어두운 배경에 선명한 HSB 색상의 공들이
잔상을 남기며 바운싱 - 벽에 닿으면 색상 변경 - 클릭하면 공 추가 -
c 키로 전부 삭제, r 키로 10개 재생성 -
좌상단에 공 개수 표시
마무리
스케치 저장
Ctrl+S (Mac: Cmd+S)로 스케치를 저장하세요. P5.js Web Editor에서 저장하면 자동으로 계정에 연결됩니다.
오늘 한 것 돌아보기
| 완성 기준 | 핵심 기술 | 확인 |
|---|---|---|
| 기본 | class 정의 + 객체 배열 + for문 순회 | “내 스케치에 클래스로 만든 객체가 여러 개 움직이고 있나?” |
| 표준 | bounce() + 랜덤 색상/크기 + mousePressed() | “벽에서 튕기고, 색상이 다양하고, 클릭하면 추가되나?” |
| 심화 | 잔상 + 바운스 색변경 + HSB + 키보드 | “시각적으로 완성도 있고, 인터랙션도 풍부한가?” |
어디까지 갔든 괜찮습니다. 중요한 것은 클래스와 객체 배열을 직접 써본 경험입니다.
실습과제 3 제출 안내
| 항목 | 내용 |
|---|---|
| 과제명 | 클래스를 활용한 다중 오브젝트 작품 |
| 제출 기한 | 8주차(중간고사) 수업 전까지 |
| 제출 방식 | P5.js Web Editor 링크 공유 |
| 평가 | 제출 완료 시 만점 |
| # | 필수 요구사항 |
|---|---|
| 1 | class 1개 이상 정의 (constructor + 메서드 2개
이상) |
| 2 | 객체 배열로 10개 이상 관리 |
| 3 | 각 객체가 독립적으로 움직이거나 변화 |
| 4 | 인터랙션 1개 이상 (마우스 클릭, 키보드 등) |
까지 도달했다면 이미 요구사항 4개를 모두 충족합니다. 수업 중에 만든 것을 다듬어서 제출하면 됩니다.
중간고사(8주차) 예고
다음 주는 중간고사입니다. 범위는 1~7주차입니다.
도형을 그리고(1-2주) → 색을 칠하고 반복하고(3주) → 클릭/키보드에 반응하고(4주) → 움직이고 튕기고(5주) → 함수와 배열로 정리하고(6주) → 클래스로 하나로 묶는다(7주)
오늘 만든 Ball 클래스 코드를 다시 한 번 읽어보세요. 1~7주차의 모든 개념이 이 클래스 안에 다 들어 있습니다.