12 보병 - kyhsa93/karda GitHub Wiki
12. 보병
D1(풀 배틀필드)의 가장 새로운 부분이다. 지금 코드에는 "사람이 걷는" 것이 하나도 없다. 이 장은 플레이어 보병의 시점·이동·병과·무기·피해·조작과, 봇 보병을 보여 줄 코드 저폴리 인형을 정한다.
12.1 목표
- 보병은 전장의 기본 단위다. 탈것이 없어도 보병만으로 한 판을 즐길 수 있어야 한다(B2 배포 기준).
- 손맛 기준(플레이어 역할 2.4): 자세·이동이 발견과 명중을 가르고, 반동·재장전이 리듬을 만들고, 엄폐물 뒤에서 살아남는다(P2).
12.2 시점 — 1인칭으로 결정
|
1인칭 (채택) |
3인칭 (제외) |
| 필요한 것 |
무기·손 뷰모델(코드 도형 두 덩이) |
플레이어 몸 전체의 애니메이션(걷기·달리기·앉기·엎드리기·조준·재장전·사망) + 카메라 충돌 |
| 에셋 |
없어도 됨 |
애니메이션 보병 에셋 필수(채택 목록에 없음) |
| 조준 |
조준선 = 시선, 모바일 드래그와 바로 맞물림 |
어깨 너머 오프셋·벽 모서리 엿보기 악용 문제 |
| 비용 (추정) |
약 300줄 |
약 900줄 + 에셋 |
| 기존 게임과 |
아파치 조종석 1인칭과 같은 감각 |
— |
- 결론: 보병은 1인칭만. 탈것은 1인칭(조종석·조준경)과 3인칭 추적(기존
chase 카메라)을 V로 전환한다.
- 봇 보병은 플레이어 눈에 3인칭으로 보이므로 인형과 애니메이션은 필요하다(12.7).
12.3 이동과 충돌
src/sim/infantry/soldier.ts — sim 층, 120Hz 고정 스텝, 결정론.
| 동작 |
속도 (m/s) |
눈 높이 |
발견 배율 (봇 AI 5.6) |
비고 |
| 조준하며 걷기 |
2.8 |
1.65m |
1.0 |
|
| 달리기 |
5.0 |
1.65m |
1.0 |
가속 0→5m/s 0.25초 |
| 질주 |
7.0 |
1.6m |
1.3 |
지구력 8초, 회복은 쓴 시간 × 1.5. 사격 불가 |
| 앉아 이동 |
2.0 |
1.1m |
0.63 |
|
| 엎드려 기기 |
0.8 |
0.35m |
0.3 |
엎드리는 데 0.8초, 일어나는 데 0.6초 |
| 넘기 |
— |
— |
— |
높이 1.1m 이하 장애물 앞에서 점프 키 → 0.6초에 넘음(모래주머니·담장). 그 외 점프 높이 0.5m |
- 지형: 발은
terrain.surfaceAt. 경사 45° 넘으면 올라가지 못한다(#187, 결정 O6). 판정은 footStep·climbable 하나이고 흐름장·대리 조향·실제 이동이 같이 쓴다. 못 오르는 비탈은 지형 색이 바위색이 되어 화면과 통행 규칙이 같다. 봇 분대의 경사 규칙(ai/movement.ts, 35°)은 B4에서 맞춘다(그때까지 공정성 부채). 물 깊이 1.2m까지 속도 50%, 더 깊으면 못 들어간다(수영 없음).
- 충돌체: 플레이어 캡슐(반지름 0.35m) vs 나무(
terrain.treesNear 원기둥) · 민가(buildings 상자) · 교량 상판 · 엄폐 소품(모래주머니·상자·막사 — 채택 CC0 모델의 경계 상자) · 탈것(방향 있는 상자). 봇 인형과는 겹쳐도 밀어내기만(막지 않음).
- 엄폐 소품: 12.5m 지형 격자는 보병 엄폐로 너무 거칠다. 거점마다 소품 ≥ 10개를 배치하고(전장 맵 6.2 원칙 5), 소품은 가시선도 막는다(
LosCache에 소품 상자 검사 추가 — 거점 100m 안 가시선만, 비용 제한).
- 낙하 피해: 착지 속도 9m/s 넘으면
(v − 9) × 15 피해.
- 탈것에 치임: 3m/s 넘는 탈것(봇·플레이어)과 부딪히면 사망. 플레이어 탈것은 봇 인형도 친다(분대원 1명 사망, 오사면 감점).
12.4 병과와 장비
각 병과는 주무기 1 + 장비 2~3. 수치는 모두 (추정), B3-8 교전 표 측정으로 확정한다. 장비 선택지는 모두 처음부터 열려 있다(A6) — 목록은 진행과 보상 7.5.
| 병과 |
역할 |
주무기 |
장비 |
| 돌격 |
거점 점령·보병 교전, 아군 분대 유지 |
돌격소총 |
유탄 발사기 6발 · 구급 상자 1 · 연막탄 2 |
| 공병 |
탈것 파괴·수리 |
카빈 |
대전차 로켓 3 · 수리 도구 · 대전차 지뢰 2 |
| 지원 |
제압·재보급·대공 |
경기관총 |
탄약 상자 1 · 휴대용 대공 미사일 2 |
| 정찰 |
원거리 제거·발견·유도 |
저격소총 |
쌍안경 · 레이저 지시기 · 스폰 비콘 1 |
무기 수치
| 무기 |
탄창 / 예비 |
발사율 |
탄속 |
피해 (가까이 → 멀리) |
퍼짐 (지향 / 조준경) |
기타 |
| 돌격소총 |
30 / 150 |
10/s |
850m/s |
25 (≤ 50m) → 18 (≥ 300m) |
2.5° / 0.3° + 반동 |
재장전 2.2초 |
| 카빈 |
30 / 150 |
11/s |
800m/s |
22 → 14 |
2.2° / 0.4° |
재장전 2.0초 |
| 경기관총 |
100 / 200 |
13/s |
850m/s |
22 → 16 |
3.5° / 0.6°, 엎드리면 절반 |
재장전 5초 |
| 저격소총 |
5 / 25 |
1발/1.3초 |
900m/s(공기 저항) |
90 (머리 ×2) |
6° / 0°, 조준경 흔들림(숨 참기 5초) |
조준경 8× |
| 유탄 |
6 |
1발 |
75m/s 포물선 |
폭심 100, 반경 5m 선형 감소 |
— |
경차량에 60(관통 2) |
| 대전차 로켓 |
3 |
1발 |
150m/s 포물선 |
탈것 120(관통 4), 폭발 반경 3m 인형 100 |
— |
전차 정면 3발·후면 2발 |
| 대전차 지뢰 |
2 |
설치 |
— |
200(관통 5) |
— |
아군·빈 차량엔 안 터짐, 플레이어 사망 뒤 60초 유지 |
| 휴대용 대공 미사일 |
2 |
잠금 1.5초 |
기존 stinger |
260 |
— |
기존 stinger.ts 시커·missile.ts 유도 재사용, 잠금음 |
- 피해 원칙: 플레이어 보병 무기는 실제 발사체(기존
projectile.ts 적분·지형/유닛 충돌). 인형 판정은 분대원 캡슐(12.7), 머리는 캡슐 위 구(반지름 0.13m).
- 탈것에 대한 피해는 기존 관통 vs 장갑 배율 + 측면 ×1.2·후면 ×1.5(발사체가 탈것 뒤 60° 안으로 맞으면, 신규) — 플레이어가 관여하는 사격에만(봇 대 봇은 통계).
장비 동작
| 장비 |
동작 |
재사용 |
| 구급 상자 |
놓으면 반경 5m: 플레이어 +10HP/s, 봇 분대의 쓰러진 인원 15초마다 1명 복귀(분대 HP +8). 60초 유지, 재배치 30초 |
신규 |
| 연막탄 |
투척, 반경 8m 연막 20초. 봇 가시선을 막는다(연막 구를 LosCache 검사에 추가) |
기존 연막 효과 풀 |
| 수리 도구 |
누르는 동안 아군 탈것 +20HP/s, 5초 쓰면 과열 3초 |
신규 |
| 탄약 상자 |
놓으면 반경 5m: 플레이어 3초마다 탄창 1, 봇 분대 "탄약 부족"(발사율 ×0.5, 교전 3분 뒤 생김) 해제 |
신규 |
| 쌍안경 |
4× 확대, 조준 중 적에 1초 → 스폿 20초(봇 공유) |
UI/UX 8.5 |
| 레이저 지시기 |
누르는 동안 레이저 점(사거리 5km). 아군 봇 공격 헬기·전투기가 20초 안에 그 표적을 1순위로. 플레이어가 아파치에 타고 있지 않을 때 봇의 헬파이어·레이저 유도 폭탄이 이 점을 쓴다 |
기존 laser.ts·remoteLasers·헬파이어 레이저 유도 |
| 스폰 비콘 |
설치 1개, 거기서 보병 스폰(적 30m 안이면 불가) |
신규 |
12.5 체력과 교전 기준
- 플레이어 보병 HP 100. 피해 없이 8초 지나면 초당 5 회복(100까지).
- 환산: 봇 분대원 1명 = 플레이어 기준 HP 100 = 봇 기준 HP 8(분대 HP 40 = 5명). 플레이어가 분대원 한 명을 쓰러뜨리면 분대 HP −8, 인형 하나가 쓰러진다.
- 봇 → 플레이어 보병 사격(분대원마다, 통계 판정 + 예광탄, 실제 발사체는 쓰지 않음):
- 살아 있고 가시선이 있는 분대원이 초당 1발(기관총 분대원 2발, 저격조 4초에 1발).
- 명중 확률
p = 0.25 × (1 − (d / 400)²) × 자세 × 이동 × 엄폐 × 난이도
- 자세: 선 1.0 / 앉음 0.7 / 엎드림 0.45 · 이동: 정지 1.0 / 걷기 0.8 / 질주 0.6 · 엄폐(부분 가림) 0.5 · 난이도 0.6 / 1.0 / 1.3
- 저격조:
0.35 × (1 − (d / 800)²), 피해 80.
- 피해 20(소총·기관총). 탈것 무기가 플레이어 보병을 쏘면 탈것 무기 표의 피해를 플레이어 기준으로 환산(× 12.5, 봇 HP 8 ↔ 플레이어 100).
| 교전 (보통 난이도, 추정) |
계산 |
기대 시간 |
| 플레이어 돌격소총 vs 봇 분대원, 100m, 조준경 |
25 × 4발, 명중 약 70% |
약 0.6초 |
| 봇 소총 분대(5명) vs 서 있는 플레이어, 100m |
5 × 0.23 × 20 = 23 HP/s |
약 4.3초 |
| 같은 분대 vs 앉아 엄폐 뒤 플레이어 |
× 0.7 × 0.5 → 8 HP/s |
약 12초 |
| 봇 저격조(2명) vs 서 있는 플레이어, 400m |
명중 0.26 × 0.25/s × 2명 = 0.13회/s, 피해 80이라 2발에 사망 |
약 15초 |
| 봇 전차 기관총 vs 플레이어, 300m |
5/s × 0.13 × 20 = 13 HP/s |
약 8초 |
| 플레이어 대전차 로켓 vs 봇 전차 |
정면 120·후면 180, HP 300 |
정면 3발 / 후면 2발 |
- 측정 (B2-8, 20시드,
sim/infantry/combat.test.ts): 소총 분대 대 선 플레이어 100m 4.3초 · 앉은 플레이어 5.0초 · 저격조 400m 17.7초 · 전차 기관총 300m 6.4초 — 모두 ±40% 안. 탈것 무기 → 플레이어 보병 환산은 표의 예(기관총 피해 2 → 20)에 맞춰 ×10으로 했다(본문의 ×12.5는 소총 1.5 → 18.75처럼 분대 무기용). 난이도는 명중 배율로만 들어가고 받는 피해 배율은 보병에 쓰지 않는다. 발견: 거리 = 자세별 기준 × 이동(정지 0.7·걷기 1·질주 1.3) × 부분 가림 0.5, 가시선 안이면 약 0.5초 만에 확정, 600m 안에서 1초 안에 쏘면 즉시 발견. 플레이어 체력은 피해 없이 8초 뒤 초당 5 회복.
- 의도: 탁 트인 곳에 선 보병은 몇 초 만에 죽고, 엄폐·자세를 쓰면 세 배 오래 산다(1.3 P2 기준 "2배 이상"을 여유 있게).
12.6 조준·카메라
- 시야각 80°(설정 70~95°), 조준경(ADS) 55°, 4× 조준경 20°, 저격 8× 10°. 조준경 전환 0.2초.
- 반동: 발사마다 위로 0.4°(돌격소총, 조준경이면 0.25°) + 좌우 무작위(
world.rng) ±0.15°, 사격을 멈추면 0.3초에 70% 복귀. 연사할수록 퍼짐이 커진다(최대 지향 퍼짐 × 1.8).
- 조준선: 십자, 네 막대 간격 = 현재 퍼짐. 명중
×, 처치 굵은 ×.
- 뷰모델: 코드 도형 소총·손(병과별 무기 모양 4종), 별도 장면·깊이 초기화로 그려 벽을 뚫지 않게(드로우콜 +2). 걸을 때 흔들림 최소(설정에서 끔).
- 카메라 근거리 평면 0.05m(기존), 원거리 평면: 보병일 때 3km(안개), 탈것·헬기 7km(기존), 전투기 12km(15장).
12.7 코드 저폴리 인형 (기본)
채택된 soldier.glb는 애니메이션·스킨이 제거된 정지 모델(1,077폴리곤)이라 걷는 보병을 표현하지 못한다. 외부 애니메이션 에셋 없이도 동작하는 코드 인형을 기본으로 만들고, 외부 에셋은 후보 조사 후 소유자가 채택하면 근거리 LOD만 교체한다(외부 에셋).
형상
- 강체 부위 7개: 머리(깎은 상자, 헬멧 모양이 진영마다 다름 — 연합 둥근 헬멧, VPA 챙 있는 모자) · 몸통 · 위팔 2 · 다리 2 · 무기(병과별 길이). 부위마다 12~24 삼각형 → 인형 하나 약 150 삼각형.
- 부위마다
InstancedMesh 1개(인스턴스 색으로 진영·병과 구분) → 모든 인형이 드로우콜 7개(진영 수와 무관).
- 진영 구분은 색 + 모양(헬멧 형태, 어깨 표식 사각/삼각) — 색만으로 구분하지 않는다.
애니메이션 (절차적, 렌더 층)
| 상태 |
움직임 |
| 서기·조준 |
무기 들어 올림, 호흡 흔들림 0.5° |
| 걷기·달리기 |
다리 사인 스윙(진폭 25°/40°, 주기 = 보폭 / 속도), 팔 반대 위상 |
| 앉기 |
다리 접힘, 몸통 높이 0.65 |
| 엎드리기 |
몸 전체 90° 앞으로, 다리 교차 기기 |
| 사격 |
무기 반동 킥 3cm, 총구 섬광(기존 효과 풀) |
| 쓰러짐 |
0.8초 동안 뒤·옆으로 넘어짐(부위 회전 보간) → 잔해로 30초 뒤 사라짐 |
- 위치는 sim(분대 위치 + 슬롯 오프셋), 자세·걸음 위상은 렌더가 보간한다(sim 결정론과 무관).
인형 LOD (기술 설계 9.3)
| 카메라 거리 |
표현 |
갱신 |
| < 120m |
부위 7개 전체 애니메이션 |
매 프레임 |
| 120~500m |
부위 3개(머리·몸통+팔·다리 병합) |
15Hz |
| 500~1,500m |
한 덩이 상자(12 삼각형) |
5Hz |
| > 1,500m |
그리지 않음 (조준경·TADS·쌍안경 협각이면 그 카메라 기준으로 다시 판단) |
— |
- 판정 캡슐: 선 반지름 0.3m·높이 1.8m, 앉음 1.2m, 엎드림 가로 1.8m·높이 0.4m.
12.8 조작
키보드·마우스
| 동작 |
키 |
| 이동 / 질주 |
WASD / Shift(누르는 동안) |
| 앉기 / 엎드리기 |
C / Z |
| 점프·넘기 |
Space |
| 사격 / 조준경 |
좌클릭 / 우클릭 |
| 재장전 |
R |
| 주무기 / 장비 1·2·3 |
1 / 2 · 3 · 4 (휠로 순환) |
| 숨 참기(저격 조준 중) |
Shift |
| 스폿 |
Q |
| 탑승 |
E |
| 공통 |
Tab 전황 · G 무전 · Esc 일시정지 · M 소리 |
게임패드
왼쪽 스틱 이동(누르면 질주) · 오른쪽 스틱 시선 · RT 사격 · LT 조준경 · A 점프 · B 앉기(누름 유지 엎드리기) · X 재장전 · Y 탑승(누름 유지) · 십자키 좌/우 장비 · 십자키 위 주무기 · LB 두 번 스폿 · Back 전황 · Start 일시정지.
터치 (가로)
┌──────────────────────────────────────────────────────────┐
│ [≡][미니맵] 612 ▓▓░ 587 A■ D⊘ G▲ [무전] │
│ [장비1][장비2] │
│ ┼ [재장전] │
│ [탑승] ← 가까울 때 │
│ ( 이동 스틱 ) [자세] [조준] [발사●] │
│ 끝까지 밀면 질주 (오른쪽 절반 드래그 = 시선) │
└──────────────────────────────────────────────────────────┘
- 버튼 6~7개(발사·조준·재장전·자세·장비1·장비2·탑승), 모두 48px 이상, 발사 64px. 발사 버튼을 누른 채 끌면 시선도 돈다.
- 자세: 탭 = 앉기/서기, 길게 = 엎드리기. 넘기는 질주 중 낮은 장애물에 닿으면 자동. 스폿은 조준경을 켠 채 적에 0.5초 두면 자동.
- 조준 보조(모바일·패드, 기본 켬): UI/UX 8.9.
12.9 재사용과 새 모듈
| 필요 |
재사용 |
신규 |
| 발사체·충돌 |
sim/weapons/projectile.ts(적분·지형/유닛 충돌) |
인형 캡슐 충돌 segmentHitsMember |
| 휴대용 대공 |
stinger.ts 시커, missile.ts 유도, 잠금음 |
보병 발사 위치 |
| 레이저 지시 |
sensors/laser.ts, world.remoteLasers |
보병 레이저 원점 |
| 피해 배율 |
weapons/damage.ts |
측·후면 배율 |
| 지형·나무·건물 |
terrain.ts(surfaceAt, treesNear, buildings) |
소품 충돌 목록 |
| 입력 |
input/input.ts(FlightInput 구조), pinch.ts |
역할별 바인딩 세트 input/roles.ts, 포인터 잠금 |
| 렌더 |
효과 풀(총구 섬광·연막), 소품 모델 |
render/battle/puppets.ts, 뷰모델 |
| sim |
— |
sim/infantry/soldier.ts(이동·자세·체력), sim/infantry/weapons.ts(무기·장비), sim/battle/squad.ts(분대원) |
예상 코드 (추정): sim 약 1,200줄, render 약 700줄, ui 약 400줄.