관리자 인증 확인 중...
B 또는 Space 로 복귀
LUNA CODE LAB · CLASS I Week 4 — 비행기와 부드러운 움직임 초4 · 중3 / 90분
1 / 13 📄 워크시트
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·가속도·마찰·정확한 숫자까지. 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분 관찰
  • "적은 어떻게 나타나서 어떻게 사라지는지" 생각해보기