실시간 전투 엔진(games/battle.html)은 데이터 → 전투 알고리즘 → UI(렌더)로 3계층 분리되어 있습니다.
데이터·알고리즘은 캔버스를 전혀 참조하지 않으므로, 병종 스킨·총알/미사일·이펙트·액션 이미지를 받아 UI 레이어에만 꽂으면 밸런스 로직을 건드리지 않고 비주얼을 교체할 수 있습니다.
아래는 각 계층의 실제 함수와 🖼 이미지 주입 슬롯 지도입니다. (라인 번호 = battle.html 기준)
ctx는 이 계층에서만 등장. 상태(G.units, G.projectiles)를 읽기만 하고 좌표에 그림. 벡터 드로잉을 drawImage(sprite,…)로 바꾸면 끝.fireWeapon은 발사체의 종류(kind)와 payload만 정하고, 어떻게 보이는지는 UI에 위임. 이미지 교체가 이 계층을 절대 건드리지 않음.sprite 필드 하나만 추가하면(UNIT_TYPES[k].sprite='...') 자산 경로가 데이터로 관리됩니다. 밸런스 수치(atk/hp/range…)와 자산을 한 곳에서 매핑.drawUnitBody()(1038)의 if(t.key===…) 분기에서 벡터로 그립니다. 각 병종당 좌향/우향 1장(facing으로 좌우반전 처리 가능) 스프라이트를 받으면 됩니다. 권장 크기는 유닛 반경 r 기준.fireWeapon()가 무기별로 spawn*()를 호출해 발사체의 kind를 심고, drawProjectile()(1169)의 if(p.kind===…) 분기가 그립니다. 회전은 속도벡터(atan2(vy,vx))로 자동. 작은 스프라이트 또는 스프라이트시트(불꽃 프레임)로 교체.| 구분 | 현재 함수 (line) | 트리거 | 권장 자산 |
|---|---|---|---|
| 💥 폭발 (착탄) | explosion() · detonate() 867·770 | 발사체 명중/광역 | fx/explosion_[0-7].png (시트) |
| 🔥 총구 화염 | muzzleFlash() 880 | fireWeapon 발사 순간 | fx/muzzle.png |
| 💨 연기·먼지 | smoke() · debris() 853·857 | 포격·격파 | fx/smoke_[0-5].png |
| 🌊 물보라 | splash() 862 | 어뢰·해상 착탄 | fx/splash.png |
| ✨ "효과적!" 상성 | popEffective() 884 | 상성 우세타 | fx/effective.png |
| 🏇 돌격 (액션) | doCharge() 1273 | 지휘 버튼 | 전 아군 전진 버프 연출 |
| 🎯 일제사격 (액션) | doVolley() 1281 | 지휘 버튼 | 동시 발사 + 화면 흔들림 |
UNIT_TYPES 순수 객체. 밸런스 단일 원천. sprite 필드 추가 여지 충분.
캔버스 ctx 완전 미참조. fireWeapon이 kind만 결정, 렌더는 UI에 위임 — 이미지와 독립.
스킨·발사체·이펙트가 각각 독립 함수(kind/key 분기). 자산 주입점이 명확.
drawUnitBody가 한 함수에 7병종 벡터를 몰아둠 → 스프라이트 도입 시 skins[key] 맵으로 분리 권장.