관리자 인증 확인 중...
B 또는 Space 로 복귀
LUNA CODE LAB · CLASS I Week 8 — 자동 공격 시스템 초4 · 중3 / 90분
1 / 9 📄 워크시트
WEEK 08 · 2026

캐릭터는 가만히,
무기는 자동으로

뱀파이어 서바이벌 게임의 핵심 — 가만히 있어도 무기가 알아서 적을 향해 발사된다. 오늘 끝나면 화면 위에 내 캐릭터가 서 있고, 가장 가까운 적을 향해 자동으로 무기가 날아갑니다.

Duration90 minutes
ToolClaude Code
Output자동 공격 캐릭터
Phase2D 뱀파이어 서바이벌 (1/5)
02 / Learning Goals⏱ 5분

오늘의 학습 목표

1
자동 무기 시스템
시간이 지나면 알아서 발사되는 무기. 쿨다운(딜레이)이 뭔지 안다.
2
가장 가까운 적 찾기
거리 계산으로 화면 위 모든 적 중 누가 제일 가까운지 고른다.
3
360도 공격 방향
위·아래·왼·오만이 아닌, 어디든 자유롭게 날아간다. 각도(angle)의 등장.
4
데미지 · 쿨다운 변수
무기 세기·속도·발사 간격을 숫자 한 줄로 바꾼다. 게임 밸런스의 시작.
03 / Concept⏱ 10분

자동 무기 = 알람 + 레이더

스마트폰 알람이 7시 되면 자동으로 울리듯, 무기도 0.5초마다 알아서 발사된다. 그리고 레이더가 가장 가까운 비행기를 찾듯, 무기는 가장 가까운 적을 향해 날아간다.

쿨다운
0.5초마다
자동 발사
+
📡
레이더
가장 가까운
적 탐지
=
🎯
자동 공격
캐릭터는 가만,
무기는 알아서
뱀파이어 서바이벌의 핵심 — 플레이어는 이동만, 공격은 게임이 한다. 그래서 손가락이 안 아파.
04 / Prompt Engineering⏱ 10분

자동 공격 — 프롬프트 만드는 법

❌ 나쁜 예
"무기가 자동으로 나가게 해줘"
왜 안 좋나? 어떤 무기? 얼마나 자주? 어디로? AI가 멋대로 만들면 매번 다른 결과. 게임 밸런스 잡기 불가능.
✓ 좋은 예
"캐릭터가 0.5초마다,
가장 가까운 적 방향으로,
속도 6, 데미지 10
노란색 마법구슬을 발사."
왜 좋나? 주기·방향·속도·데미지·외모 다 명시. 게임 밸런스를 숫자로 조절 가능.
💡 자동 무기 5요소: 주기(쿨다운) · 방향 · 속도 · 데미지 · 외모(색·모양). 이 다섯 개만 정해주면 AI가 알아서 만든다.
05 / Live Build · Step 1⏱ 12분

Step 1 — 캐릭터와 WASD 이동

먼저 주인공이 화면에 있어야 한다. WASD 키로 자유롭게 움직이는 동그라미 캐릭터부터.

1
Claude에게 보낼 요청
"survivor.html 파일 하나 만들어줘. 800×600 검은 캔버스 가운데에 반지름 20짜리 하늘색 동그라미 주인공. WASD 키로 위·아래·좌·우 이동. 이동 속도는 3. 캔버스 밖으로 안 나가게."
예상 결과 — 핵심 코드
const player = { x:400, y:300, r:20, speed:3 }; const keys = {}; addEventListener('keydown', e => keys[e.key.toLowerCase()] = true); addEventListener('keyup', e => keys[e.key.toLowerCase()] = false); function update(){ if(keys['w']) player.y -= player.speed; if(keys['s']) player.y += player.speed; if(keys['a']) player.x -= player.speed; if(keys['d']) player.x += player.speed; }
🎙
멘토 멘트 "키가 눌렸을 때 'true'를 저장해 놨다가, 매 프레임에 좌표를 바꿔요. 화살표키 말고 WASD를 쓰는 이유? 오른손은 마우스 잡고, 왼손으로 이동하려고."
학생 액션 캐릭터 색·반지름·속도를 본인 취향대로 바꿔보기. "내가 좋아하는 색의 큼직한 캐릭터" — 게임의 첫 자아.
05 / Live Build · Step 2⏱ 15분

Step 2 — 자동 무기 한 종류

캐릭터 옆에 0.5초마다 발사되는 마법구슬. 이게 뱀파이어 서바이벌의 진짜 시작이다.

2
Claude에게 보낼 요청
"캐릭터가 0.5초마다 자동으로 노란색 마법구슬(반지름 6)을 발사하게 해줘. 일단 방향은 위쪽(아래에서 위로)으로. 속도는 7. 화면 밖으로 나가면 사라지게."
예상 결과 — 쿨다운 로직
const bullets = []; let cooldown = 0; const FIRE_RATE = 30; // 60fps 기준 30프레임 = 0.5초 function update(){ cooldown--; if(cooldown <= 0){ bullets.push({ x:player.x, y:player.y, vx:0, vy:-7, r:6 }); cooldown = FIRE_RATE; // 쿨다운 리셋 } // 모든 총알 이동 bullets.forEach(b => { b.x += b.vx; b.y += b.vy; }); // 화면 밖 제거 for(let i = bullets.length-1; i >= 0; i--){ if(bullets[i].y < 0) bullets.splice(i, 1); } }
🎙
멘토 강조 포인트 "cooldown 숫자가 바로 게임의 핵심이에요. 30이면 0.5초마다, 10이면 0.16초마다 발사. 이 숫자 하나로 게임이 쉬워지고 어려워져요."
05 / Live Build · Step 3⏱ 15분

Step 3 — 가장 가까운 적을 향해

위쪽으로만 쏘면 재미없다. 가장 가까운 적을 자동으로 조준 — 이게 360도 공격 방향.

3
Claude에게 보낼 요청
"화면에 빨간 동그라미 적 3개를 랜덤 위치에 만들어줘. 마법구슬이 발사될 때 가장 가까운 적을 찾아서 그 방향으로 날아가게 해줘. 적이 없으면 발사 안 함."
예상 결과 — 거리 계산 + 각도
function findNearest(){ let nearest = null, minDist = Infinity; for(const e of enemies){ const dx = e.x - player.x; const dy = e.y - player.y; const dist = Math.sqrt(dx*dx + dy*dy); // 피타고라스! if(dist < minDist){ minDist = dist; nearest = e; } } return nearest; } // 발사할 때 const target = findNearest(); if(target){ const angle = Math.atan2(target.y - player.y, target.x - player.x); bullets.push({ x:player.x, y:player.y, vx:Math.cos(angle)*7, vy:Math.sin(angle)*7, r:6 }); }
🎙
핵심 개념 한 줄 "Math.atan2(y, x) — 이 함수 하나가 '어디로 쏠지'를 알려줘요. 외울 필요는 없지만, 360도 공격의 비밀이 이거 하나라는 건 알아두세요."
🎯
학생 액션 적의 색·크기·위치를 바꿔보기. 마법구슬이 정말로 그 적을 따라가는지 확인.
05 / Live Build · Step 4⏱ 13분

Step 4 — 데미지 · 쿨다운 변수화

숫자 하나로 게임이 쉬워지고 어려워진다. 모든 게임 밸런스의 본질은 변수다.

4
Claude에게 보낼 요청
"무기 정보를 코드 맨 위에 WEAPON 객체로 정리해줘. - damage: 10 - cooldown: 30 - speed: 7 - color: 노랑 - radius: 6 그리고 적에게 hp를 만들어줘 (기본 30). 마법구슬이 적과 닿으면 hp 감소, hp가 0 이하가 되면 적 사라짐."
예상 결과 — 무기 객체 + 충돌 + HP
const WEAPON = { damage: 10, cooldown: 30, speed: 7, color: '#FFD93D', radius: 6 }; // 충돌 체크 + 데미지 for(let i = bullets.length-1; i >= 0; i--){ for(let j = enemies.length-1; j >= 0; j--){ const b = bullets[i], e = enemies[j]; const dx = b.x - e.x, dy = b.y - e.y; if(Math.sqrt(dx*dx + dy*dy) < b.r + e.r){ e.hp -= WEAPON.damage; bullets.splice(i, 1); if(e.hp <= 0) enemies.splice(j, 1); break; } } }
🎙
오늘의 진짜 가르침 "damage: 10 을 100으로 바꾸면? 적이 한 방. 1로 바꾸면? 30번 맞아야 죽음. 게임 디자이너의 일은 이 숫자 하나하나 정하는 거예요."
⚖️
학생 액션 (밸런스 실험) damage·cooldown·speed 셋 중 하나만 바꿔서 게임이 어떻게 변하는지 옆 친구에게 1줄로 설명.
05 / Live Build · Step 5⏱ 10분

Step 5 — 첫 적의 추적

적도 가만히 안 있는다. 플레이어를 향해 천천히 따라온다 — 진짜 서바이벌의 시작.

5a
적이 플레이어를 추적
매 프레임마다 적이 플레이어 방향으로 속도 1로 다가옴. (마법구슬보다 느려야 함)
for(const e of enemies){ const angle = Math.atan2(player.y - e.y, player.x - e.x); e.x += Math.cos(angle) * 1; e.y += Math.sin(angle) * 1; }
5b
테스트 플레이 (3분)
캐릭터 움직이면서 적이 따라오고, 마법구슬이 자동으로 적을 맞히는지 확인. 적 3마리 다 잡으면 게임 끝(빈 화면).
5c
저장 + 자랑
화면 녹화 10초. "손가락 안 움직였는데 게임이 자동으로 적을 죽임" — 이게 오늘의 자랑거리.
🎙
오늘의 마무리 "오늘 만든 거 = 뱀파이어 서바이벌의 가장 기초. 캐릭터 이동 + 자동 공격 + 추적 적. 다음 주에 적이 100마리로 늘어나면 진짜 게임 같아질 거예요."
10 / Checkpoint⏱ 5분

여기까지 됐나? 확인하기

잘 됐다면
  • WASD로 캐릭터 이동 — 캔버스 밖으로 안 나감
  • 마법구슬이 0.5초마다 자동 발사
  • 가장 가까운 적을 향해 날아감 (360도 어디든)
  • 적이 hp 0 되면 사라짐
  • 적 3마리가 플레이어를 천천히 추적
⚠️자주 막히는 부분
  • 마법구슬이 한 번에 다 발사됨 → 쿨다운 변수 초기화 안 됨
  • 적을 못 따라감 → atan2의 인자 순서 확인 (y, x)
  • 충돌이 안 됨 → 거리 비교에서 두 반지름 합 사용
  • 적이 너무 빠름 → 적 speed를 1보다 작게
  • 마법구슬이 사라지지 않음 → 화면 밖 제거 코드 빠짐
11 / Challenge⏱ 5분

더 해보고 싶다면 도전

🎨
마법구슬에 꼬리 효과를 넣어보기. 지나간 자리에 흐려지는 잔상.
난이도 ★
💥
적이 죽을 때 폭발 애니메이션을 추가. 동그라미가 커지면서 흐려져 사라지게.
난이도 ★★
🎲
적이 한 마리 죽으면 새로운 적이 랜덤 위치에 등장. 무한 적 시스템의 시작.
난이도 ★★★
12 / Student Gallery⏱ 5분

작년 친구들 서바이버

13 / Next Week⏱ 5분

다음 시간 예고

WEEK 09 · COMING UP

적 무리와 웨이브 —
100마리 동시에

오늘은 적 3마리. 다음 주는 한 화면에 100마리가 몰려옵니다. 시간이 갈수록 더 많이, 더 빠르게. 좀비·박쥐·스켈레톤 — 종류도 다양해진다.

PREPARE · 준비물
  • 오늘 만든 survivor.html을 노트북에 저장해 와
  • 좋아하는 좀비 게임 한 장면 스크린샷
  • "적 100마리가 몰려오면 어떨까?" 상상해서 1줄로