관리자 인증 확인 중...
B 또는 Space 로 복귀
LUNA CODE LAB · CLASS I Week 3 — 입력·충돌·게임 상태 초4 · 중3 / 90분
1 / 13 📄 워크시트
WEEK 03 · 2026

키보드로
조종하고 부딪힌다

화살표 키 · 충돌 감지 · 게임 상태 전환. 오늘 끝나면 — 시작 화면이 뜨고, 키로 조종하고, 끝나는 진짜 게임 구조가 완성됩니다. Phase 1 마무리.

Duration90 minutes
ToolClaude Code · Canvas
Output조종 가능한 데모
Phase기본 게임 로직 (3/3)
02 / Learning Goals⏱ 5분

오늘의 학습 목표

1
키보드 이벤트
keydown·keyup 두 개로 누르는 순간과 떼는 순간을 안다. 캐릭터 조종의 진짜 시작.
2
박스 충돌 감지 (AABB)
두 사각형이 겹쳤는지 확인하는 간단한 수학. 적·아이템·벽 모두 똑같은 원리.
3
게임 상태 머신
시작 화면 → 플레이 → 끝 화면 → 다시 시작. 모든 게임이 이 구조.
4
Phase 1 마무리
기본 게임 로직 완성. 다음 주부터 진짜 비행기 게임 만들기 시작!
03 / Concept⏱ 10분

게임은 상태의 모음이다

포켓몬을 켜면 "시작" 화면, 게임하면 "플레이" 화면, 죽으면 "게임 오버" 화면. 세 가지 모드가 전환되는 거예요. 이걸 상태 머신이라 합니다.

🎬
START
시작 화면
"스페이스 눌러"
🎮
PLAY
실제 조종
충돌 검사
💀
END
게임 오버
"R로 재시작"
state라는 변수 하나로 세 화면을 전환합니다. update()는 항상 돌지만, 현재 state에 맞는 화면만 그려요.
04 / Prompt Engineering⏱ 12분

충돌·입력 전문 용어 알기

❌ 막연한 요청
"부딪히면 멈추게"
왜 안 좋나? 어떤 부딪힘? 벽? 적? 아이템? AI가 멋대로 추측함. 결과: 의도와 다른 게임.
✓ 정확한 요청
"플레이어 사각형(파랑)과
장애물 사각형(빨강)이
AABB 충돌 감지되면
플레이어를 그 자리에서
못 움직이게(속도=0)."
왜 좋나? AABB라는 정확한 용어 + 어떤 도형끼리 + 결과 행동까지. 결과: 정확한 결과.
💡 오늘의 전문 용어: "keydown · keyup · AABB · state · 게임 루프" 다섯 개. AI랑 대화할 때 이 단어 쓰면 한 번에 통함.
05 / Live Build · Step 1⏱ 6분

Step 1 — 키 입력 받기

키보드의 어떤 키가 지금 눌려있는지 추적한다. "눌렀나 안 눌렀나"만 알면 캐릭터 조종 끝.

1
Claude에게 보낼 요청
"키보드 입력을 추적하는 코드 추가해줘. keys 객체를 만들어서 화살표 키 4개의 누름/뗌 상태를 저장. keydown 이벤트로 true, keyup으로 false 만들어. 콘솔에 'ArrowRight pressed' 같은 로그도 찍어줘 (확인용)."
예상 결과 — 키 상태 추적
const keys = {}; // 빈 객체로 시작 addEventListener('keydown', e => { keys[e.key] = true; // 누르면 true console.log(e.key + ' pressed'); }); addEventListener('keyup', e => { keys[e.key] = false; // 떼면 false }); // 이제 keys['ArrowRight'] 가 true/false 로 알려줌!
🎙
핵심 가르침 "keydown 이벤트가 키를 누르는 순간 한 번 발생할 줄 알지만, 실제로는 꾹 누르고 있으면 계속 발생해요. 그래서 keys 객체에 '지금 누른 상태'를 저장해두면 매 프레임 깔끔하게 확인 가능."
05 / Live Build · Step 2⏱ 7분

Step 2 — 캐릭터 움직이기

키 상태를 게임 루프에서 매 프레임 확인해서 위치를 갱신한다. "눌렸으면 옮긴다" — 이게 핵심.

2
Claude에게 보낼 요청
"파란 사각형(50×50)을 캔버스 가운데에 놓고 update 함수에서 keys 객체를 확인해 화살표 키 4방향으로 움직이게. 속도는 1프레임에 4픽셀. 지난주 캔버스 그대로 쓰면 됨."
예상 결과 — 매 프레임 키 검사
let player = { x: 375, y: 275, w: 50, h: 50 }; const SPEED = 4; function update() { ctx.clearRect(0, 0, 800, 600); // 매 프레임 키 상태 검사 if (keys['ArrowRight']) player.x += SPEED; if (keys['ArrowLeft']) player.x -= SPEED; if (keys['ArrowDown']) player.y += SPEED; if (keys['ArrowUp']) player.y -= SPEED; ctx.fillStyle = 'blue'; ctx.fillRect(player.x, player.y, player.w, player.h); requestAnimationFrame(update); }
🎮
학생 액션 파란 캐릭터를 화살표로 움직여보기. 대각선 이동(양쪽 키 동시 누름)도 가능한지 확인. 안 되면 왜 안 되는지 추측해보기.
05 / Live Build · Step 3⏱ 7분

Step 3 — AABB 충돌 감지

두 사각형이 겹쳤는지 어떻게 알아볼까? 네 변의 위치 비교만으로 끝. 모든 게임이 이 한 가지 수식 위에 돌아갑니다.

3
Claude에게 보낼 요청
"빨간 장애물 사각형(100×100)을 캔버스 (500, 250)에 그려. 플레이어와 장애물 사이 AABB 충돌 감지하는 함수 만들어줘. 충돌 시 콘솔에 'COLLIDE!' 찍어줘."
예상 결과 — AABB 한 줄 수식
const wall = { x: 500, y: 250, w: 100, h: 100 }; function hit(a, b) { // 네 변의 위치 비교 — 한 줄 마법 return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y; } // update() 안에서 if (hit(player, wall)) console.log('COLLIDE!');
🎙
AABB의 의미 "AABB = Axis-Aligned Bounding Box. 축에 평행한 사각형이라는 뜻. 회전 없는 사각형끼리 겹침 검사하는 가장 빠른 방법이에요. 비행기 게임, 마리오, 다 똑같은 4줄 코드."
🔍
학생 액션 캐릭터를 빨간 벽에 부딪혀보기. 콘솔에 COLLIDE 찍히는지 확인. 살짝 스쳤을 때도 감지되는지 테스트.
05 / Live Build · Step 4⏱ 8분

Step 4 — 게임 상태 변수

"지금 시작 화면인가 플레이 중인가 끝났나" — state 변수 하나로 모든 화면을 관리한다.

4
Claude에게 보낼 요청
"게임 상태 변수 state를 만들어줘. 3개 상태: 'start' / 'play' / 'end'. update 함수가 state에 따라 다르게 동작: · start: 화면 안 그리고 키 입력만 대기 · play: 지금처럼 플레이어 그리고 움직임 · end: 멈춤 그리고 벽에 부딪히면 state를 'end'로 바꿔."
예상 결과 — 상태 머신 구조
let state = 'start'; // 처음엔 시작 화면 function update() { ctx.clearRect(0, 0, 800, 600); if (state === 'play') { // 화살표 키 처리, 충돌 검사 if (hit(player, wall)) state = 'end'; drawPlayer(); drawWall(); } requestAnimationFrame(update); }
🎙
핵심 깨달음 "게임이 복잡해 보여도 사실 'state'라는 변수 하나가 모든 화면을 결정해요. 마리오 시작 화면도, 보스전도, 죽었을 때도 — 다 state 값만 다른 거예요."
05 / Live Build · Step 5⏱ 8분

Step 5 — 시작·끝 화면 그리기

이제 진짜 게임 같은 모습. "스페이스 눌러 시작", "GAME OVER · R로 재시작" 같은 안내 화면을 그린다.

5
Claude에게 보낼 요청
"start 상태일 때 캔버스 가운데에 'PRESS SPACE TO START' 큰 글씨로 그려. 스페이스 누르면 state = 'play'로 바꿈. end 상태일 때 'GAME OVER' 빨간색 큰 글씨 + 밑에 'PRESS R TO RESTART' 작은 글씨. R 누르면 player 위치 리셋 + state = 'play'."
예상 결과 — 텍스트 그리기 + 키 전환
if (state === 'start') { ctx.fillStyle = 'white'; ctx.font = '40px sans-serif'; ctx.fillText('PRESS SPACE', 280, 300); } if (state === 'end') { ctx.fillStyle = 'red'; ctx.font = '60px sans-serif'; ctx.fillText('GAME OVER', 220, 300); } // 키 처리 if (keys[' '] && state === 'start') state = 'play'; if (keys['r'] && state === 'end') { player.x = 375; player.y = 275; state = 'play'; }
🎙
오늘의 마무리 · Phase 1 완성 "이제 진짜 게임 구조가 완성됐어요. 시작 화면 → 플레이 → 끝 화면 → 재시작. 다음 주부터는 이 구조 위에 비행기 게임을 쌓아 올립니다. Phase 2 시작!"
10 / Checkpoint⏱ 5분

여기까지 됐나? 확인하기

잘 됐다면
  • 시작 화면에 "PRESS SPACE" 글씨
  • 스페이스 누르면 플레이 시작
  • 화살표 키 4방향으로 캐릭터 이동
  • 빨간 벽에 부딪치면 GAME OVER 표시
  • R 키로 처음 위치로 재시작
⚠️자주 막히는 부분
  • 키 입력 안 됨 → 브라우저 창 클릭 후 다시
  • 대각선 너무 빠름 → 정상! (대각선 보정은 나중)
  • 충돌 안 됨 → 콘솔에서 player·wall 값 확인
  • 글씨 안 보임 → fillStyle을 흰색·빨강 정확히
  • R 안 됨 → 'r' 소문자인지 'R' 대문자인지
11 / Challenge⏱ 10분

더 해보고 싶다면 도전

🧱
벽 여러 개로 미로 만들기. 벽 배열 walls = [...]에 5~10개 사각형 넣고 모두 충돌 검사.
난이도 ★
아이템 먹기 게임. 노란 별 5개 캔버스에 흩뿌리고, 캐릭터가 닿으면 별이 사라지고 점수 +1. 5개 다 먹으면 WIN 화면.
난이도 ★★
⏱️
제한 시간 추가. 10초 카운트다운 표시. 0이 되면 GAME OVER. 별 5개를 시간 안에 다 먹으면 WIN.
난이도 ★★★
12 / Student Gallery⏱ 7분

작년 친구들 작품

13 / Next Week⏱ 5분

다음 시간 예고

WEEK 04 · COMING UP · PHASE 2

비행기와 부드러운 움직임 —
가속도와 관성

드디어 비행기 게임 시작! 사각형이 아니라 진짜 비행기 모양을 그리고, 가속도와 관성으로 부드럽게 움직이는 기술을 배웁니다. 진짜 비행 시뮬레이터 같은 느낌!

PREPARE · 준비물
  • 이번 주 게임 상태 머신 파일 가져오기
  • 좋아하는 슈팅 게임 5분 관찰 (비행기가 어떻게 움직이는지)
  • "부드럽게 움직인다"는 게 뭔지 직접 느껴보기