WEEK 04 · 2026
비행기가
진짜처럼 흐른다
가속도 · 관성 · 화면 경계. 사각형 움직임에서 진짜 비행기 조종으로. 오늘 끝나면 — 키를 떼도 슬그머니 미끄러지는 비행기가 손에 들어옵니다. Phase 2 시작!
Duration90 minutes
ToolClaude Code · Canvas
Output조종 가능한 비행기
Phase2D 비행기 게임 (1/4)
02 / Learning Goals⏱ 5분
오늘의 학습 목표
1
가속도와 관성
물리 시간 그 가속도 맞아요. 빨라지고 느려지는 진짜 자연 법칙으로 비행기 움직임.
2
속도 변수의 힘
vx · vy 두 변수만 추가하면 모든 게 부드러워진다. 게임 디자인의 핵심 비밀.
3
화면 경계 처리
비행기가 화면 밖으로 못 나가게. Math.max·Math.min 한 줄 마법.
4
비행기 모양 그리기
사각형 + 삼각형 머리. AI한테 "비행기 모양"이라 하면 진짜 그려줘요.
03 / Concept⏱ 10분
움직임에는 관성이 있다
지난주 캐릭터는 키를 떼면 "딱" 멈췄어요. 현실에선 그런 게 없죠. 달리던 자동차도 브레이크 밟아도 쭉 미끄러지면서 멈춰요. 그게 관성.
🎮
키 누름
속도(vx)에
가속도 더하기
가속도 더하기
→
💨
속도 적용
x += vx
매 프레임
매 프레임
→
🌬
감속
vx *= 0.95
마찰처럼
마찰처럼
핵심 공식: 위치 += 속도, 그리고 속도 *= 0.95 (매 프레임 5% 줄어듦 = 마찰).
04 / Prompt Engineering⏱ 12분
물리 용어로 정확히 요청
❌ 막연한 요청
"비행기 부드럽게
움직이게 해줘"
움직이게 해줘"
왜 안 좋나? "부드럽게"가 사람마다 다름. AI가 lerp·easing·smoothstep 중 마음대로 고름.
결과: 의도와 다른 느낌.
✓ 물리 용어
"비행기에 vx, vy 속도 변수 추가.
키 누르면 vx에 가속도 0.3 더하고
매 프레임 vx *= 0.95 (마찰).
x += vx로 위치 갱신."
키 누르면 vx에 가속도 0.3 더하고
매 프레임 vx *= 0.95 (마찰).
x += vx로 위치 갱신."
왜 좋나? vx·가속도·마찰·정확한 숫자까지. AI가 정확히 그것만 구현.
결과: 일관된 비행기 느낌.
💡 오늘의 핵심: "vx · vy · 가속도 · 마찰 · 경계" 다섯 단어. 게임 만드는 사람들의 공용어.
05 / Live Build · Step 1⏱ 6분
Step 1 — 비행기 그리기
사각형 몸통 + 삼각형 머리. 두 도형 조합만으로 비행기 느낌 충분. 어려운 그림 X.
1
Claude에게 보낼 요청
"800×600 캔버스에 비행기 하나 그려.
사각형 몸통(40×60, 흰색) +
위쪽에 삼각형 머리(빨강)로.
캔버스 가운데 아래쪽(x=380, y=480)에 배치.
배경은 진한 네이비(#0a0a1f) — 우주 느낌."
✓
예상 결과 — drawPlane 함수
function drawPlane(x, y) {
// 몸통 (사각형)
ctx.fillStyle = 'white';
ctx.fillRect(x, y, 40, 60);
// 머리 (삼각형) — 위쪽 뾰족
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.moveTo(x, y); // 왼쪽 위
ctx.lineTo(x + 40, y); // 오른쪽 위
ctx.lineTo(x + 20, y - 25); // 꼭짓점
ctx.fill();
}
🎙
그래픽의 진리
"AAA 게임도 결국 도형 조합이에요. 비행기 = 사각형 + 삼각형. 자동차 = 사각형 + 원 4개. 마리오 = 사각형 + 동그라미 + 점 두 개. 복잡해 보이는 것도 단순한 도형들 합."
05 / Live Build · Step 2⏱ 6분
Step 2 — 기본 키 조종
먼저 지난주처럼 "눌리면 그만큼 이동" 단순 조종부터. 이걸 비교 기준으로 두고 다음 단계에서 부드럽게 바꿉니다.
2
Claude에게 보낼 요청
"keys 객체랑 게임 루프 가져와서
비행기 위치(x, y)를 화살표 키로 움직이게.
좌우는 ±5픽셀, 위아래도 ±5픽셀.
일단 단순하게 — 키 떼면 즉시 멈춤.
(다음 단계에서 부드럽게 바꿀 거임)"
✓
예상 결과 — 단순 조종 (비교용)
let plane = { x: 380, y: 480 };
function update() {
ctx.fillStyle = '#0a0a1f';
ctx.fillRect(0, 0, 800, 600);
if (keys['ArrowRight']) plane.x += 5;
if (keys['ArrowLeft']) plane.x -= 5;
if (keys['ArrowUp']) plane.y -= 5;
if (keys['ArrowDown']) plane.y += 5;
drawPlane(plane.x, plane.y);
requestAnimationFrame(update);
}
🎮
학생 액션
비행기를 키로 조종해보기. 키 떼면 즉시 멈춤 — 이게 "딱딱한" 느낌. 이걸 다음 단계에서 비행기처럼 부드럽게 바꿀 거예요.
05 / Live Build · Step 3⏱ 8분
Step 3 — 속도와 가속도
이제 진짜 변화 — 위치를 직접 바꾸지 말고 속도(vx, vy)를 바꾼다. 위치는 매 프레임 속도만큼 자동 이동.
3
Claude에게 보낼 요청
"비행기에 vx, vy 속도 변수 추가.
화살표 키 누르면 vx, vy에 가속도 0.3 누적.
실제 위치는 x += vx, y += vy로 갱신.
키 떼도 일단 vx·vy가 남아있어서 미끄러짐."
✓
예상 결과 — 위치 vs 속도
let plane = { x: 380, y: 480, vx: 0, vy: 0 };
const ACC = 0.3; // 가속도
function update() {
// 1. 키 입력 → 속도 변화
if (keys['ArrowRight']) plane.vx += ACC;
if (keys['ArrowLeft']) plane.vx -= ACC;
if (keys['ArrowUp']) plane.vy -= ACC;
if (keys['ArrowDown']) plane.vy += ACC;
// 2. 속도 → 위치 갱신
plane.x += plane.vx;
plane.y += plane.vy;
drawPlane(plane.x, plane.y);
requestAnimationFrame(update);
}
🎙
핵심 깨달음
"지난 단계에선 키 누르면 x를 직접 바꿨어요. 지금은 키가 vx를 바꾸고, vx가 x를 바꿔요. 한 다리 건너요. 그래서 키 떼도 vx가 살아 있으니 비행기가 미끄러져요. 이게 관성."
05 / Live Build · Step 4⏱ 7분
Step 4 — 마찰로 멈추기
방금은 미끄러져서 영원히 안 멈췄죠? 매 프레임 속도를 5%씩 줄이면 — 천천히 자연스럽게 멈춥니다.
4
Claude에게 보낼 요청
"매 프레임마다 vx, vy에 0.95 곱하기 추가.
이게 마찰 효과 — 5%씩 속도가 줄어들어
키를 떼면 천천히 멈춤.
참고: 0.95 대신 0.98이면 더 미끄럽고, 0.9면 빨리 멈춤."
✓
예상 결과 — 마찰 한 줄 마법
const FRICTION = 0.95;
function update() {
// 키 → 속도
if (keys['ArrowRight']) plane.vx += ACC;
// ... 다른 방향 동일 ...
// 🔥 마찰 — 5%씩 속도 감소
plane.vx *= FRICTION;
plane.vy *= FRICTION;
// 속도 → 위치
plane.x += plane.vx;
plane.y += plane.vy;
drawPlane(plane.x, plane.y);
requestAnimationFrame(update);
}
🎙
왜 곱하기 0.95인가
"속도 10에서 0.95 곱하면 9.5. 그다음 9.025. 그다음 8.57... 점점 작아지다 사실상 0. 1초에 60번 곱하면 5초쯤 거의 멈춰요. 자동차 브레이크랑 똑같아요. 0.99로 바꾸면 얼음판 위 미끄럼."
⚙️
학생 액션
FRICTION 값을 0.99, 0.95, 0.85로 바꿔보고 차이 비교. 어떤 게 비행기 느낌, 어떤 게 자동차, 어떤 게 얼음판?
05 / Live Build · Step 5⏱ 7분
Step 5 — 화면 경계 가두기
비행기가 화면 밖으로 날아가면 보이지 않죠. Math.max·Math.min 한 줄로 화면 안에 가두기.
5
Claude에게 보낼 요청
"비행기가 캔버스(800×600) 밖으로 못 나가게.
x는 0과 760 사이 (비행기 너비 40 빼고),
y는 25와 540 사이 (위 머리 25 + 아래 60).
경계에 닿으면 그 방향 속도 0으로 (튕기지 말고)."
✓
예상 결과 — clamp 패턴
// 위치 갱신 후 경계 처리
plane.x += plane.vx;
plane.y += plane.vy;
// 🛡 화면 안에 가두기 (clamp)
if (plane.x < 0) { plane.x = 0; plane.vx = 0; }
if (plane.x > 760) { plane.x = 760; plane.vx = 0; }
if (plane.y < 25) { plane.y = 25; plane.vy = 0; }
if (plane.y > 540) { plane.y = 540; plane.vy = 0; }
// 또는 한 줄로:
plane.x = Math.max(0, Math.min(760, plane.x));
🎙
Phase 2 시작
"이제 진짜 비행기 같아요. 가속·관성·마찰·경계 — 모든 슈팅 게임의 기본 4종 세트. 다음 주엔 여기에 미사일을 추가하고, 그 다음엔 적도 나옵니다. 본격 비행기 게임 시작!"
10 / Checkpoint⏱ 5분
여기까지 됐나? 확인하기
✅잘 됐다면
- 비행기 모양이 캔버스에 보임 (사각+삼각)
- 화살표 키로 비행기가 네 방향 이동
- 키 떼면 슬그머니 미끄러지다 멈춤
- 화면 끝에서 밖으로 안 나감
- 대각선 이동도 자연스럽게
⚠️자주 막히는 부분
- 너무 빨라요 → ACC를 0.15로 줄이기
- 안 멈춰요 → FRICTION 0.95 확인
- 너무 안 움직임 → FRICTION을 0.98로
- 비행기 잘림 → 경계 숫자 확인 (40·60 차이)
- 잔상 남음 → 매 프레임 배경 다시 그리기
11 / Challenge⏱ 10분
더 해보고 싶다면 도전
🌌
별 배경. 검은 우주 배경에 흰색 점 100개 흩뿌리고 매 프레임마다 아래로 천천히 떨어지게 (스크롤 효과).
난이도 ★
🔥
엔진 불꽃. 비행기 뒤(아래쪽)에 주황색 불꽃이 깜빡깜빡 그려지게. 속도(vy)가 빠를수록 길게.
난이도 ★★
🌀
비행기 기울이기. 좌우로 움직일 때 비행기가 진짜 비행기처럼 좌우로 살짝 기울어 보이게. ctx.rotate 써야 함 — AI한테 추천 받기.
난이도 ★★★
12 / Student Gallery⏱ 7분
작년 친구들 작품
✈️
기본 비행기
🚀
로켓 변형
🌌
우주 배경
🔥
엔진 불꽃
🌀
기울이기
⭐
별 스크롤
📌 첫 학기 종료 후 학생 결과물 사진을 여기에 채울 예정입니다.
13 / Next Week⏱ 5분
다음 시간 예고
WEEK 05 · COMING UP
미사일과 적 —
본격 슈팅 시작
비행기에서 미사일이 발사되고, 위에서 적 비행기가 내려옵니다. 충돌하면 적이 폭발하고 점수 +1. 진짜 게임 화면이 완성돼요! 배열(array)·여러 미사일 동시 관리·spawn 패턴까지 배웁니다.
PREPARE · 준비물
- 이번 주 만든 비행기 파일 가져오기
- 스페이스 키로 발사하는 슈팅 게임 5분 관찰
- "적은 어떻게 나타나서 어떻게 사라지는지" 생각해보기