7주차 2교시 — 객체 배열과 클래스 확장
강의 아웃라인: week-07-outline 이전 교시: week-07-period1-student (왜 클래스가 필요한가 + class 기본 문법) 다음 교시: week-07-period3-student (학생 주도 실습)
| 항목 | 내용 |
|---|---|
| 대상 | P5.js 입문자 (테크아트 전공) |
| 소요 시간 | 45분 |
| 사전 준비 | 1교시 class 기본 문법 (constructor·this·메서드) |
- 객체 배열을 활용하여 수십~수백 개의 객체를 동시에 생성·관리할 수 있습니다
- 클래스에 바운싱, 색상 등 기능을 확장할 수 있습니다
- 마우스/키보드 인터랙션으로 객체를 동적으로 추가할 수 있습니다
1교시 복습
빠른 퀴즈
클래스 안에서 자기 자신의 x좌표를 참조하려면?
답: this.x입니다. this는
’이 객체 자신’이라는 뜻입니다.
설계도(클래스)로 실제 객체를 만드는 키워드는?
답: new입니다.
new Ball(200, 100) 이렇게 사용합니다.
ball.move()에서 move()는 뭐라고
부르나요?
답: 메서드입니다. 클래스 안에 정의된 함수입니다.
2교시 전환
1교시에서 공 1개를 만들어 보았습니다. 실제로 작품을 만들려면 공이
수십 개, 수백 개 필요합니다.
let ball1, ball2, ball3, ..., ball100처럼 변수 100개를
선언할 수는 없습니다.
6주차에서는 이런 문제를 배열로 해결했습니다. 오늘은 숫자 대신 객체를 배열에 넣습니다.
심화 개념 1 — 객체 배열: 단계적으로 만들어보기
Step A: 먼저 공 3개를 변수로 만들어보기
1교시에서 공 1개는 let ball = new Ball(...)로
만들었습니다. 이를 3개로 늘려 보겠습니다.
let ball1 = new Ball(100, 200, 2, 3);
let ball2 = new Ball(250, 150, -1, 2);
let ball3 = new Ball(350, 300, 3, -2);
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
ball1.move(); ball1.display();
ball2.move(); ball2.display();
ball3.move(); ball3.display();
}3개까지는 이렇게 관리할 수 있습니다. 하지만 10개, 50개가 되면
ball1부터 ball50까지 변수를 만들고,
draw()에서도 50줄을 써야 합니다.
이럴 때 배열을 사용합니다. 6주차에서 했던 것처럼 동일한 원리입니다.
Step B: 변수 3개를 배열 1개로 바꾸기
위 코드를 배열로 바꾸면 다음과 같습니다.
let balls = [];
function setup() {
createCanvas(400, 400);
balls[0] = new Ball(100, 200, 2, 3);
balls[1] = new Ball(250, 150, -1, 2);
balls[2] = new Ball(350, 300, 3, -2);
}
function draw() {
background(220);
for (let i = 0; i < balls.length; i++) {
balls[i].move();
balls[i].display();
}
}let balls = []; — 빈 배열 선언입니다. 6주차에서 했던
것과 똑같습니다.
balls[0], balls[1], balls[2]에
Ball 객체를 넣었습니다. 6주차에서 x[0] = 100;처럼 숫자를
넣었던 것과 같은 원리입니다. 숫자 대신 객체가 들어갈
뿐입니다.
balls[i].move() — ‘i번째 공아, 움직여라.’ for문으로
0번째부터 마지막까지 순회하면서 모든 공을 움직이고 그립니다.
Step C: push()로 50개 대량 생성
3개는 수동으로 넣었지만, 50개를 만들 때는 for문 +
push()를 사용하면 됩니다.
let balls = [];
function setup() {
createCanvas(400, 400);
for (let i = 0; i < 50; i++) {
balls.push(new Ball(
random(width), random(height),
random(-3, 3), random(-3, 3)
));
}
}
function draw() {
background(220);
for (let i = 0; i < balls.length; i++) {
balls[i].move();
balls[i].display();
}
}실행 결과: - 50개의 파란 원이 각각 다른 위치에서 시작, 각각 다른 방향과 속도로 이동 - 전부 화면 밖으로 나감 (바운싱 아직 없음)
balls.push(new Ball(...)) — push()로 배열에
추가하는 방식은 6주차와 같습니다. random(width),
random(-3, 3)처럼 매번 다른 랜덤 값이 들어가므로 각 공이
다른 위치와 속도를 가집니다.
6주차 배열 6개 vs 7주차 객체 배열 비교
| 6주차: 배열 6개 방식 | 7주차: 객체 배열 방식 |
|---|---|
let x = [], y = [], speedX = [], speedY = [], size = [], c = []; |
let balls = []; |
| 변수가 6줄 | 변수가 1줄 |
x[i] += speedX[i]; |
balls[i].move(); |
| 데이터가 흩어져 있음 | 데이터가 하나로 묶여 있음 |
| 속성 추가 시 배열 추가 필요 | 클래스에 프로퍼티만 추가 |
배열 6개가 배열 1개로 줄었습니다. 공 하나의 모든 데이터가 하나의 객체 안에 들어 있기 때문입니다.
공에 투명도(alpha) 속성을 추가하고 싶으면 배열 방식과 클래스 방식은 각각 어떻게 다를까요?
답: 배열 방식에서는 alpha[] 배열을 하나
더 만들어야 하고, 클래스 방식에서는 constructor에
this.alpha = 255; 한 줄만 추가하면 됩니다.
심화 개념 2 — 바운싱 + 색상: 클래스 확장
지금 공들이 전부 화면 밖으로 나가고, 다 같은 파란색이라 심심합니다. 클래스에 기능을 추가해서 한 번에 해결할 수 있습니다.
완성된 Ball 클래스
5주차 바운싱 코드를 bounce() 메서드로, 색상과 크기를
constructor에 추가합니다.
class Ball {
constructor(x, y, speedX, speedY) {
this.x = x;
this.y = y;
this.speedX = speedX;
this.speedY = speedY;
this.size = random(20, 50); // 랜덤 크기
this.c = color(random(255), random(255), random(255)); // 랜덤 색상
}
move() {
this.x += this.speedX;
this.y += this.speedY;
}
bounce() {
if (this.x > width || this.x < 0) {
this.speedX *= -1;
}
if (this.y > height || this.y < 0) {
this.speedY *= -1;
}
}
display() {
fill(this.c);
noStroke();
ellipse(this.x, this.y, this.size);
}
}this.size = random(20, 50) — 20에서 50 사이 랜덤
크기입니다. new Ball()을 할 때마다 random()이
실행되어 매번 다른 크기가 됩니다.
this.c = color(random(255), random(255), random(255)) —
랜덤 RGB 색상입니다. display()에서
fill(this.c) — 자기 자신의 색상으로
그립니다.
bounce() — 5주차 바운싱 코드가 그대로
메서드 안에 들어갔습니다. x가 this.x로,
speed가 this.speedX로 바뀌었을 뿐입니다.
draw()에서 사용
function draw() {
background(220);
for (let i = 0; i < balls.length; i++) {
balls[i].move();
balls[i].bounce();
balls[i].display();
}
}실행 결과: - 50개의 공이 각각 다른 크기, 다른 색상으로 벽에 튕기며 움직임
balls[i].move() — 움직이고,
balls[i].bounce() — 벽 확인하고,
balls[i].display() — 그립니다. 세 줄이면 공 하나의 전체
동작입니다. 코드가 무엇을 하는지 바로 읽힙니다.
1~6주차의 모든 개념이 여기서 만납니다:
변수(프로퍼티), 조건문(바운스 if), 함수(메서드), 배열(객체
배열), 반복문(for문 순회). 오늘 배우는 클래스는 지금까지 배운 내용을
하나로 묶는 구조입니다.
심화 개념 3 — 마우스 인터랙션: 클릭으로 공 추가
지금은 setup()에서 50개를 미리 만들어 놓았습니다.
클릭할 때마다 새 공이 생기면 더 재미있어집니다.
mousePressed()에서 객체 추가
function mousePressed() {
balls.push(new Ball(
mouseX, mouseY,
random(-3, 3), random(-3, 3)
));
}실행 결과: - 마우스를 클릭할 때마다 클릭한 위치에 새로운 공이 생성 - 각 공은 랜덤 속도, 랜덤 크기, 랜덤 색상
mousePressed() — 4주차에서 배운 클릭 이벤트입니다.
balls.push() — 6주차에서 배운 배열 추가입니다.
new Ball(mouseX, mouseY, ...) — 7주차 클래스로 객체
생성입니다.
4주차 인터랙션 + 6주차 배열 + 7주차 클래스가 한 코드 안에 결합됩니다. 세 줄에 세 주차의 개념이 모두 들어 있습니다.
바운스 시 색상 변경 보너스
벽에 부딪힐 때 색이 바뀌면 더 재미있습니다. bounce()
메서드에 한 줄만 추가하면 됩니다.
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)); // 색 변경!
}
}
바운싱 if문 안에
this.c = color(random(...)) 한 줄을 추가합니다. 벽에 부딪힐
때마다 색이 랜덤으로 바뀝니다.
미니 실습 — 코드 수정 체험
에디터에 아래 전체 코드를 복사해서 넣어 보세요. 그리고 다음을 바꿔 보세요.
class Ball {
constructor(x, y, speedX, speedY) {
this.x = x;
this.y = y;
this.speedX = speedX;
this.speedY = speedY;
this.size = random(20, 50);
this.c = color(random(255), random(255), random(255));
}
move() {
this.x += this.speedX;
this.y += this.speedY;
}
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));
}
}
display() {
fill(this.c);
noStroke();
ellipse(this.x, this.y, this.size);
}
}
let balls = [];
function setup() {
createCanvas(400, 400);
for (let i = 0; i < 20; i++) {
balls.push(new Ball(
random(width), random(height),
random(-4, 4), random(-4, 4)
));
}
}
function draw() {
background(30);
for (let i = 0; i < balls.length; i++) {
balls[i].move();
balls[i].bounce();
balls[i].display();
}
}
function mousePressed() {
balls.push(new Ball(
mouseX, mouseY,
random(-4, 4), random(-4, 4)
));
}실행되면 다음을 시도해 보세요.
- setup의
20을100으로 바꿔보기 — 공이 100개로 늘어남 random(-4, 4)를random(-1, 1)로 바꿔보기 — 느리게 움직임this.size = random(20, 50)을this.size = random(5, 80)으로 바꿔보기background(30)을background(30, 30, 30, 50)으로 바꿔보기 — 잔상 효과!
배경의 투명도를 낮추면 이전 프레임이 살짝 남아서 궤적이 보입니다.
실전 사례 시연
사례 1: 파티클 분수
class Particle {
constructor(x, y) {
this.x = x;
this.y = y;
this.speedX = random(-2, 2);
this.speedY = random(-8, -3);
this.size = random(5, 12);
this.c = color(random(255), random(100, 255), 0);
}
update() {
this.x += this.speedX;
this.y += this.speedY;
this.speedY += 0.15; // 중력!
}
display() {
fill(this.c);
noStroke();
ellipse(this.x, this.y, this.size);
}
}
let particles = [];
function setup() {
createCanvas(400, 400);
}
function draw() {
background(0, 0, 0, 40);
if (mouseIsPressed) {
for (let i = 0; i < 3; i++) {
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);
}
}
}
마우스를 누르면 파티클이 분수처럼 솟아올랐다가 떨어집니다.
핵심은 딱 한 줄입니다:
this.speedY += 0.15 — 매 프레임 y속도에 0.15를 더합니다.
처음엔 위로 올라가지만, 속도가 점점 바뀌어 결국 아래로 떨어집니다. 이
효과를 중력으로 볼 수 있습니다. 10주차에서 정식으로
다룹니다.
splice()는 화면 밖 파티클을 지우는 코드입니다.
13주차(파티클 시스템)에서 다시 다루므로, 지금은 개념만 알아두면
됩니다.
사례 2: 다양한 도형 — 맛보기
Ball 클래스의 display()에서 ellipse() 대신
rect()를 쓰면 네모가 됩니다. 이름을 바꾸면
Square 클래스로 확장할 수 있습니다. 같은 화면에 공과 네모를
동시에 띄울 수도 있습니다.
Ball과 Square 코드는 구조가 비슷합니다. 공통 부분을 자동으로 물려받는 상속(inheritance)이라는 개념이 있지만, 이 수업에서는 다루지 않습니다.
3교시 실습 안내
핵심 한 줄
3교시 실습이 곧 실습과제 3입니다. 제출 완료 시 만점입니다. 중간고사(8주차) 전까지 P5.js 웹 에디터 링크로 제출합니다.
필수 요구사항 4개
| # | 요구사항 | 한 줄 설명 |
|---|---|---|
| 1 | class 1개 이상 정의 |
constructor + 메서드 2개 이상 |
| 2 | 객체 배열로 10개 이상 관리 | let balls = []; + for문 |
| 3 | 각 객체가 독립적으로 움직이기 | move() + display() |
| 4 | 인터랙션 1개 | 클릭 추가, 키보드 제어 등 |
이 네 가지만 지키면 됩니다.
세 가지 방향
| 방향 | 한 줄 설명 |
|---|---|
| A. 바운싱 볼 월드 | 오늘 만든 코드에서 시작 — 가장 쉬움 |
| B. 파티클 아트 | 마우스에서 파티클 생성 + 중력 |
| C. 자유 주제 | 눈, 비, 별, 꽃잎 등 나만의 클래스 |
무엇을 골라야 할지 모르겠으면 A(바운싱 볼)부터 시작하세요. 2교시 미니 실습에서 이미 만들어 봤기 때문입니다.
3교시에서 자세한 스타터 코드와 단계별 가이드가 제공됩니다.