Modularize documentation: split CONTEXT.md into functional modules and update agent.md router
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
# Context: Arena & Scene
|
||||
|
||||
## 1. 모듈별 상세 역할 (`src/game/arena/`)
|
||||
|
||||
- **`ArenaScene.js`**: Phaser 씬의 생명주기와 전반적인 오케스트레이션을 담당합니다. `update()` 매 프레임마다 전투원 상태를 체크하고, 카메라 이동 및 UI 모듈 호출을 조율합니다.
|
||||
- **`arenaRenderer.js`**: 아레나 배경 그래픽 및 타일 렌더링을 담당합니다.
|
||||
- **`arenaSpectatorCamera.js`**: 관전 모드 시점 계산 및 카메라 포커싱 로직을 담당합니다. 생존 인원에 따른 지능형 카메라 추적 알고리즘이 구현되어 있습니다.
|
||||
|
||||
## 2. 주요 로직 구현 세부 사항
|
||||
|
||||
### 지능형 카메라 추적 (Lerp & Jittering 방지)
|
||||
카메라가 소수점 단위의 평균 좌표를 즉시 따라가면 화면이 떨려 보일 수 있습니다. 이를 방지하기 위해:
|
||||
1. 목표 좌표(`targetX, targetY`)를 `Math.round()`로 정수화합니다.
|
||||
2. 현재 카메라 위치에서 목표 지점까지 매 프레임 `0.1`의 배율로 거리를 좁혀나가는 `Lerp` 연산을 수행합니다.
|
||||
```javascript
|
||||
this.cameras.main.scrollX += (targetX - this.cameras.main.midPoint.x) * SPECTATOR_CAMERA_LERP;
|
||||
```
|
||||
|
||||
최종교전 관전은 두 단계로 나뉩니다.
|
||||
- **생존 4명 이하**: `SPECTATOR_RANDOM_FOCUS_INTERVAL`마다 생존 캐릭터 중 한 명을 무작위로 포커싱합니다.
|
||||
- **2팀 잔여 & 합계 8명 이하**: 더 적은 생존 수를 가진 팀의 중앙을 포커싱하며, 동률이면 기존 교전쌍 중심 포커싱으로 되돌아갑니다.
|
||||
|
||||
### 미니맵 가이드라인
|
||||
미니맵은 전장 전체를 축소하여 보여주는 독립된 카메라입니다. 주 카메라가 비추는 영역을 계산하여 미니맵 위에 사각형(`graphics`)을 그려줍니다.
|
||||
- `camera.displayWidth / zoom` 등을 이용하여 현재 월드에서 보이는 실제 영역 크기를 계산합니다.
|
||||
- 뷰포트 사각형 좌표는 미니맵 픽셀 격자에 맞춰 반올림하고, 외곽 stroke가 겹쳐 검게 깨지지 않도록 노란 내부 선을 채운 직사각형으로 렌더링합니다.
|
||||
|
||||
### 씬 상태 관리
|
||||
- **프리뷰 모드 (`presentationMode`)**: 최초 로드 시 조용히 실행되는 배경 전투입니다. 로컬 저장 옵션과 무관하게 10팀 x 5명 고정 규모로 동작합니다.
|
||||
- **일시정지 (`setPaused`)**: 실제 전투에서 물리, Phaser 타이머, tween, 스프라이트 애니메이션을 함께 제어합니다. 프리뷰 및 종료된 전투는 제외됩니다.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Context: Combat System
|
||||
|
||||
## 1. 모듈별 상세 역할 (`src/game/combat/`)
|
||||
|
||||
- **`combat.js`**: 전투 AI, 피해 계산, 처치 보상 등 핵심 전투 로직을 담당합니다. 유닛의 이동, 공격, 투사체 발사 등을 처리합니다.
|
||||
- **`combatSettings.js`**: 전투 속도 배율 등 런타임 전투 설정을 관리합니다.
|
||||
- **`arenaFinalCombatEffects.js`**: 최종 교전 시 슬로우 모션 등 연출 효과를 담당합니다. 수학적인 이징(easing) 함수와 물리 시간 배율 계산을 포함합니다.
|
||||
|
||||
## 2. 주요 로직 구현 세부 사항
|
||||
|
||||
### 전투 AI 및 유닛 동작
|
||||
- **`updateFighter()`**: 가장 가까운 적을 찾아 이동하거나 공격하는 유닛 AI의 핵심입니다.
|
||||
- **`applyHit()`**: 일반 공격 피해량은 `ATTACK_DAMAGE_MIN/MAX` 범위에서 계산하고, 치명타 적중은 `Critical!` 표기와 즉시 처치/카메라 흔들림을 처리합니다.
|
||||
- **`projectilePathHitsDefender()`**: 투사체가 대상을 스쳐 지나가지 않도록 궤적(Line)과 히트박스(Rectangle) 겹침 검사를 수행합니다.
|
||||
|
||||
### 처치 보상 및 성장
|
||||
- **`applyKillReward()`**: 처치한 캐릭터의 체력 회복(현재 체력 30%), 크기 증가, 공격속도/이동속도 배율 증가를 처리합니다. 누적 배율은 `KILL_GROWTH_MAX_MULTIPLIER`로 제한합니다.
|
||||
- **`clampFighterInsideArena()`**: 처치 성장 중 커진 캐릭터가 전장 바깥으로 나가지 않도록 위치를 보정합니다.
|
||||
|
||||
### 최종교전 슬로우모션
|
||||
`FINAL_COMBAT_SLOW_MOTION_ENABLED`가 활성화된 경우:
|
||||
- 최종교전 상태에서 공격 모션이 시작될 때 전역 time scale을 낮춥니다.
|
||||
- 진입/유지/복귀 속도 램프(Ease)를 적용합니다.
|
||||
- Arcade Physics는 timeScale 방향이 반대라 물리 이동에는 역수 배율을 적용합니다.
|
||||
|
||||
## 3. 유지보수 규칙
|
||||
- **처치 성장 상한**: `src/constants.js`의 `KILL_GROWTH_MAX_MULTIPLIER`를 수정합니다.
|
||||
- **공격력 조정**: `src/constants.js`의 `ATTACK_DAMAGE_MIN/MAX`를 수정합니다.
|
||||
- **특수 규칙**: 캐릭터별 특수 공격 방식은 `fighterManifest.js`의 `combat` 설정을 확인합니다.
|
||||
@@ -0,0 +1,28 @@
|
||||
# Context: Core & Infrastructure
|
||||
|
||||
## 1. 모듈별 상세 역할
|
||||
|
||||
- **`src/main.js`**: Phaser 게임의 전역 설정(Physics, Scale, Canvas Parent)을 담당하며, `ArenaScene`을 인스턴스화합니다.
|
||||
- 앱 로드 시 `trackVisitor()`를 호출해 방문자 체크 API와 연동합니다.
|
||||
- `Start` 버튼, 옵션 drawer, 전투 시작 submit 흐름을 제어하며 전투 시작 시 `#app`에 `match-live` 상태 클래스를 부여합니다.
|
||||
- 전투 중 drawer 접기/펼치기(`drawer-collapsed`), 재시작 버튼, 일시정지 버튼 상태(`match-paused`)를 DOM 클래스와 `ArenaScene` 상태에 동기화합니다.
|
||||
- **`src/constants.js`**: 게임 내 모든 튜닝 수치를 관리합니다.
|
||||
- `ATTACK_DAMAGE_MIN`, `ATTACK_DAMAGE_MAX`: 일반 공격 1회 적중 시 적용되는 랜덤 피해량 범위.
|
||||
- `FIGHTER_HITBOX_*`: 100x100 캐릭터 프레임 안에서 실제 충돌 판정이 놓이는 위치와 크기.
|
||||
- `KILL_HEALTH_RECOVERY_RATIO`, `KILL_GROWTH_MULTIPLIER`, `KILL_GROWTH_MAX_MULTIPLIER`: 처치 후 회복량, 크기/공격속도/이동속도 성장 배율, 누적 보상 상한.
|
||||
- `SELECTED_FIGHTER_OUTLINE_GAP`, `SELECTED_FIGHTER_OUTLINE_WIDTH`, `SELECTED_FIGHTER_OUTLINE_ALPHA`: 팀 색상 실루엣 마커의 캐릭터 이격 거리, 두께, 투명도.
|
||||
- `TEAM_COLORS`, `getTeamColor()`: 8팀 이하에서는 기본 팔레트를 쓰고, 9팀 이상에서는 팀 수에 맞춰 중복 없는 색상을 동적으로 생성합니다.
|
||||
- `SPECTATOR_CAMERA_LERP`: 카메라 추적의 부드러움 정도.
|
||||
- `SPECTATOR_FINAL_TEAM_TOTAL_THRESHOLD`, `SPECTATOR_RANDOM_FOCUS_INTERVAL`, `FINAL_COMBAT_SLOW_MOTION_*`: 최종교전 관전 조건, 랜덤 포커싱 간격, 슬로우모션 on/off, 배율과 속도 램프 시간.
|
||||
- `MINIMAP_VIEWPORT_SIZE`: 미니맵의 고정 픽셀 크기.
|
||||
- `ARENA_SIZE`: 경기장 전체 크기 (GRID * TILE).
|
||||
|
||||
## 2. 개발 및 유지보수 규칙
|
||||
|
||||
- **신규 캐릭터 추가**: `public/assets/characters/`에 에셋 배치 후 `fighterManifest.js`에 정의를 추가하면 즉시 게임에 반영됩니다.
|
||||
- **종족값 유지**: 신규 스킨을 추가할 때는 사망 통계가 누락되지 않도록 `species`를 `human`, `orc`, `skeleton`, `slime`, `wolf`, `bear` 중 하나로 지정해야 합니다.
|
||||
- **물리 수치 조정**: 캐릭터의 속도나 사거리 등은 `src/constants.js` 또는 `fighterManifest.js` 내 개별 설정을 통해 변경하십시오.
|
||||
- **처치 성장 상한 조정**: 처치 보상으로 캐릭터가 커지는 최대치와 공격/이동 배율 상한은 `src/constants.js`의 `KILL_GROWTH_MAX_MULTIPLIER`를 수정합니다.
|
||||
- **공격력 조정**: 기본 피해량은 `src/constants.js`의 `ATTACK_DAMAGE_MIN`, `ATTACK_DAMAGE_MAX`를 수정합니다. 캐릭터별 특수 공격 방식은 `fighterManifest.js`의 `combat` 설정을 우선 확인합니다.
|
||||
- **DOM 접근**: 성능을 위해 `ArenaScene`은 좌측 HUD badge 등 필요한 시점에만 최소한으로 DOM에 접근합니다.
|
||||
- **패키지 락 파일**: 이 프로젝트는 `package-lock.json`을 저장소에서 제외합니다. 의존성 변경 시 `package.json`을 기준으로 관리합니다.
|
||||
@@ -0,0 +1,31 @@
|
||||
# Context: Fighter & Assets
|
||||
|
||||
## 1. 모듈별 상세 역할 (`src/game/fighter/`)
|
||||
|
||||
- **`fighterAssets.js`**: 캐릭터 스프라이트 로드 및 애니메이션/실루엣 생성을 담당합니다. 원본 이미지로부터 팀 색상 마커용 실루엣을 동적으로 생성합니다.
|
||||
- **`fighterFactory.js`**: 캐릭터 인스턴스화 및 HUD(이름표, 체력바) 관리를 담당합니다. Phaser Sprite와 DOM UI 사이의 가교 역할을 합니다.
|
||||
- **`fighterManifest.js`**: 모든 캐릭터 종족 및 스탯 데이터를 정의합니다. 20여 종의 캐릭터 설정이 포함되어 있습니다.
|
||||
- **`fighterSelection.js`**: 매치 참여 캐릭터를 무작위로 선택하거나 섞는 로직을 담당합니다.
|
||||
|
||||
## 2. 주요 로직 구현 세부 사항
|
||||
|
||||
### 동적 팀 실루엣 생성
|
||||
팀 색상 표시는 캐릭터 모양을 정교하게 따라가는 별도 spritesheet입니다.
|
||||
1. `fighterAssets.js`가 로드된 원본 스프라이트의 alpha 데이터를 캔버스에서 읽습니다.
|
||||
2. 원본 alpha 픽셀 주변 `SELECTED_FIGHTER_OUTLINE_GAP`은 비우고, 그 바깥 `SELECTED_FIGHTER_OUTLINE_WIDTH`에만 흰색 outline을 칠합니다.
|
||||
3. `fighterFactory.js`에서 생성된 캐릭터 뒤에 배치하고 팀 색상으로 tint 처리합니다.
|
||||
4. 캐릭터가 성장하여 커져도 같은 배율로 실루엣이 유지됩니다.
|
||||
|
||||
### 캐릭터 HUD 및 상태 동기화
|
||||
- **이름표 고정**: 스프라이트 중심이 아닌 실제 히트박스 하단에 고정되어 시각적 일관성을 유지합니다.
|
||||
- **사망자 처리**: 사망 시 HUD와 팀 마커를 숨겨 화면 가독성을 높입니다. 본체 sprite만 낮은 depth와 반투명 상태로 남깁니다.
|
||||
|
||||
### 캐릭터별 특성 (예: Slime)
|
||||
- **`spawnMultiplier`**: 배정된 슬롯 1개를 지정된 수만큼 확장하여 스폰합니다.
|
||||
- **`splitOnDeath`**: 사망 시 확률적으로 지정된 수만큼 분열체를 생성합니다.
|
||||
- **스탯 상한**: 처치 보상은 현재 체력을 회복시키지만 `maxHp`를 넘을 수 없습니다. (예: Slime은 항상 1 HP)
|
||||
|
||||
## 3. 유지보수 규칙
|
||||
- **신규 캐릭터**: 에셋 배치 후 `fighterManifest.js`에 정의를 추가합니다.
|
||||
- **종족값**: 사망 통계를 위해 지정된 6개 종족 중 하나를 반드시 선택해야 합니다.
|
||||
- **캐릭터 특성**: 전투 중 새 유닛을 생성하는 특성은 `ArenaScene.js`의 생성 헬퍼를 통해 `this.fighters`와 `team.size`를 함께 갱신해야 합니다.
|
||||
@@ -0,0 +1,30 @@
|
||||
# Context: Match & UI
|
||||
|
||||
## 1. 모듈별 상세 역할
|
||||
|
||||
### 매치 로직 (`src/game/match/`)
|
||||
- **`matchSetup.js`**: 매치 초기화, 팀 구성, 스폰 위치 계산을 담당합니다.
|
||||
- **`arenaMatchRuntime.js`**: 스폰 클러스터 계산 및 팀 크기 동기화 등 매치 진행 중 헬퍼 기능을 제공합니다.
|
||||
|
||||
### UI 컴포넌트 (`src/ui/`)
|
||||
- **`matchForm.js`**: 설정 폼 제어 및 `localStorage` 설정 유지.
|
||||
- **`arenaScoreboard.js`**: 좌측 HUD 레일의 팀 badge 업데이트 및 관전 시점 전환.
|
||||
- **`arenaKillLog.js`**: 좌측 하단 킬로그 표시 및 관리.
|
||||
- **`battleDeathNotice.js`**: 상단 사망 통계 공지 UI.
|
||||
- **`victoryCelebration.js`**: 승리/무승부 축하 연출 (광선, 컨페티, 오디오).
|
||||
|
||||
## 2. 주요 로직 구현 세부 사항
|
||||
|
||||
### 매치 설정 및 스폰 배치
|
||||
- **완전 랜덤 배치**: 전장 전체 스폰 슬롯을 무작위로 섞어 배치합니다.
|
||||
- **스타팅 지점 배치**: 참가자 수에 맞춰 전장을 구역으로 나눈 뒤, 참가자별 구역 배정을 매치마다 섞고 구역 내 무작위 위치에 스폰합니다.
|
||||
- **설정 유지**: 닉네임, 인원, 배치 모드는 `localStorage`에 저장되어 재접속 시 복원됩니다.
|
||||
|
||||
### 전투 화면 레이아웃 (HUD)
|
||||
- **팀 Badge**: 좌측 HUD 레일에 배치되며, 클릭 시 해당 팀의 생존 유닛 중 무작위 1명으로 시점을 고정합니다.
|
||||
- **킬로그**: 처치자와 피처치자를 좌우로 배치하고, 피처치자 아이콘에 빨간 X를 겹쳐 사망 관계를 명확히 표시합니다.
|
||||
- **승리 연출**: 승리 시 Web Audio 기반 팡파르와 CSS 애니메이션(광선, 컨페티)을 결합해 화려하게 연출합니다. 무승부는 더 차분한 톤을 사용합니다.
|
||||
|
||||
## 3. UI 개발 규칙
|
||||
- **DOM 접근 최소화**: 성능 최적화를 위해 필요한 시점에만 최소한으로 DOM을 업데이트합니다.
|
||||
- **반응형 상태**: `#app`의 클래스(`match-live`, `options-open`, `drawer-collapsed`, `match-paused`)를 통해 전반적인 UI 상태를 제어합니다.
|
||||
@@ -0,0 +1,46 @@
|
||||
# Context: Server & API
|
||||
|
||||
## 1. 모듈별 상세 역할
|
||||
|
||||
- **`server/index.js`**:
|
||||
- Fastify 서버 진입점입니다.
|
||||
- 개발 모드에서는 `@fastify/middie`로 Vite 미들웨어를 붙이고, `/api/*` 요청은 Vite SPA fallback이 가로채지 않도록 Fastify 라우트로 통과시킵니다.
|
||||
- 운영 모드(`npm start`)에서는 `@fastify/static`으로 `dist/`를 서빙하고, HTML 요청은 `index.html`로 fallback합니다.
|
||||
- **`server/config.js`**:
|
||||
- `config.json`을 읽어 서버 포트, MongoDB host/port/db/user/pass, 쿠키 보안 옵션을 정규화합니다.
|
||||
- `MONGODB_URI`가 직접 있으면 우선 사용하고, 없으면 `MONGODB_HOST`/`MONGODB_PORT` 기반으로 URI를 조립합니다.
|
||||
- 전투 사망 통계 컬렉션(`MONGODB_DAILY_DEATH_COLLECTION`)과 집계 기준 타임존(`DEATH_STATS_TIME_ZONE`) 기본값을 제공합니다.
|
||||
- **`server/db.js`**:
|
||||
- `MongoClient`를 한 번 생성한 뒤 재사용하여 MongoDB 커넥션 풀을 유지합니다.
|
||||
- 종료 시 `closeMongoConnection()`으로 커넥션을 닫습니다.
|
||||
- **`server/deathStats.js`**:
|
||||
- `GET /api/death-stats/today`: `DEATH_STATS_TIME_ZONE` 기준 오늘 일자의 종족별 사망 집계와 총 사망 수를 반환합니다.
|
||||
- `POST /api/death-stats/today`: 전투 종료 시 전달된 `deathsBySpecies`를 오늘 일자별 누적 문서의 `deathsBySpecies`, `totalDeaths`, `battles`에 바로 더합니다.
|
||||
- 집계 대상 종족은 `human`, `orc`, `skeleton`, `slime`, `wolf`, `bear`로 제한합니다.
|
||||
- **`server/visitors.js`**:
|
||||
- `POST /api/visitors/check`: `arena_visitor_id` `HttpOnly` 쿠키를 확인하고 없으면 UUID를 발급합니다.
|
||||
- MongoDB `visitors` 컬렉션에 `_id = visitorId`로 upsert해 방문자 1명당 1개 문서를 유지합니다.
|
||||
- `GET /api/visitors/stats`: 전체 유니크 방문자 수를 반환합니다.
|
||||
|
||||
## 2. 주요 로직 구현 세부 사항
|
||||
|
||||
### 유니크 방문자 체크
|
||||
브라우저가 직접 MongoDB에 연결하지 않고, Fastify API가 MongoDB 커넥션 풀을 유지합니다.
|
||||
1. 프론트엔드가 앱 로드 시 `POST /api/visitors/check`를 호출합니다.
|
||||
2. 서버가 `arena_visitor_id` 쿠키를 검사합니다.
|
||||
3. 쿠키가 없거나 유효하지 않으면 `crypto.randomUUID()`로 새 방문자 ID를 만들고 `HttpOnly` 쿠키로 내려줍니다.
|
||||
4. MongoDB에는 `_id`, `firstSeenAt`, `lastSeenAt`, `visits`, `firstUserAgent`, `lastUserAgent`를 저장합니다.
|
||||
5. `countDocuments()`로 전체 유니크 방문자 수를 계산해 반환합니다.
|
||||
|
||||
### 전투 사망 통계
|
||||
프리뷰 전투는 통계에서 제외하고, 사용자가 시작한 실제 전투만 저장합니다.
|
||||
1. `fighterManifest.js`의 모든 스킨은 `species`를 가집니다.
|
||||
2. `combat.js`의 처치 흐름이 `ArenaScene.recordKill()`을 호출하면, `ArenaScene`은 피처치자의 `skin.species`를 현재 전투의 `battleDeathCounts`에 누적합니다.
|
||||
3. 전투가 5초 이상 이어지면 `GET /api/death-stats/today`로 가져온 오늘 집계와 현재 전투의 사망 수를 합산해 `#battle-notice`에 표시합니다.
|
||||
4. 전투 종료 시 `POST /api/death-stats/today`로 `deathsBySpecies`만 보냅니다.
|
||||
5. 서버는 `daily_death_stats` 컬렉션에서 오늘 일자의 `battles`, `totalDeaths`, `deathsBySpecies.*` 값을 `$inc`로 갱신합니다.
|
||||
|
||||
## 3. 설정 규칙
|
||||
- **서버 설정**: `.env` 대신 `config.json`을 사용합니다. 로컬 전용 파일이며, 저장소에는 `config.json.sample`만 공유합니다.
|
||||
- **MongoDB 연결**: 접속 정보는 `config.json`의 `MONGODB_HOST`, `MONGODB_PORT`, `MONGODB_DB` 등으로 관리합니다.
|
||||
- **API 변경**: `/api/*` 경로는 Fastify 라우트가 담당하며, 개발 모드에서 Vite 미들웨어보다 우선순위를 가집니다.
|
||||
Reference in New Issue
Block a user