arena/context/arena.md

59 lines
7.5 KiB
Markdown

# Update: Special Effect Camera Focus
- `ArenaScene` preloads and creates special-effect animations beside the existing fighter and world-effect assets, then starts `startSpecialEffects()` for live matches only.
- During a special cast, `beginSpecialEffectCameraFocus()` zooms toward the caster, `zoomOutSpecialEffectCameraFocus()` zooms back out in place when the projectile starts moving, and `clearSpecialEffectCameraFocus()` restores the previous camera after the configured hold/outro timing.
- Special focus temporarily takes priority over selected-fighter, spectator, and meteor focus so the Hurt-frame pose and projectile launch are visible.
- When `SPECIAL_EFFECT.CAMERA.CENTER_ON_CASTER_AT_START` is enabled, special focus centers the main camera on the caster's location immediately and keeps it snapped there until projectile handoff, then continues the slower follow motion.
- The Hurt-frame preparation window sets `scene.specialEffectPreparationPaused`, pauses the scene clock and Arcade Physics, freezes living fighter animations, pauses active combat-object tweens/animations/velocities, and places a blurred battlefield snapshot plus dim layer beneath the raised caster. Camera focus tweening stays active so the zoom-in can complete while combat and world-effect progression are stopped.
- The projectile is not used as a camera target. Special camera targets are still clamped against the current zoom viewport so the focus stack cannot drag the camera outside the arena bounds.
- Match restart and match finish both call `clearSpecialEffects()` so pending timers, projectile objects, caster locks, and special camera tweens do not leak into the next battle.
# Update: Elite-Weighted Scene Counts
- `ArenaScene.recordDeath()` records an elite death as its represented `stackCount`, keeping persisted species death totals aligned with the displayed army size.
- `arenaSpectatorCamera.js` uses summed `stackCount` for late/final thresholds, underdog comparison, and weighted team center positions. A match containing two large compressed armies therefore does not enter final-combat camera mode at match start.
- Minimap dots remain physical fighter markers; an elite is visible as its single large battlefield representative while numeric population remains in the scoreboard.
# Update: Graphics Minimap And HUD Candidates
- The minimap is drawn during live matches by `ArenaScene` as a lightweight `Graphics` overlay through a dedicated `minimap-hud` camera instead of reusing the field camera. Presentation/waiting mode hides it.
- The main camera ignores the minimap graphics object, and the HUD camera ignores field objects as they are added to the scene. Minimap rendering uses team-colored living fighter dots and the main camera viewport rectangle, so the minimap frame stays fixed while the main camera follows combat or meteor focus.
- `ArenaScene` refreshes HUD candidates on an interval, choosing selected fighters plus nearby visible fighters when zoomed in, then releases unused health-bar HUD pool slots. Battlefield name text is not shown.
# 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) * CAMERA.SPECTATOR_LERP;
```
자동 관전은 월드 이펙트 임시 시점, 후반 진입과 최종교전 세부 포커싱으로 나뉩니다.
- **메테오 임시 포커싱**: 자동 관전 진입 전 화염 또는 냉기 포격이 시작되면 가장 밀집한 큰 경고 구역의 중심을 임시로 확대 추적합니다. 큰 경고 표시 자체는 `WORLD_EFFECT.WARNING_DURATION_MS` 이후 사라지며, 카메라는 내부 소형 탄착들이 종료된 뒤 `CAMERA.METEOR_FOCUS_HOLD_DURATION`만큼 유지한 다음 이전 시점으로 복귀합니다. `CAMERA.METEOR_FOCUS_ENABLED``false`로 설정하면 끌 수 있으며, 수동 선택 시점과 아래 자동 관전 시점이 우선합니다.
- **후반 자동 관전 진입**: 생존 캐릭터가 30명 미만(`CAMERA.SPECTATOR_LATE_FIGHTER_THRESHOLD`)이 되면 교전 중심(가장 가까운 적 대항쌍)을 포커싱하는 후반 줌을 적용합니다. (2팀만 남았더라도 인원이 많으면 어지러움을 방지하기 위해 자동 관전으로 바로 진입하지 않습니다.)
- **생존 4명 이하**: `CAMERA.SPECTATOR_RANDOM_FOCUS_INTERVAL`마다 생존 캐릭터 중 한 명을 무작위로 포커싱합니다.
- **2팀 잔여 & 합계 8명 이하**: 더 적은 생존 수를 가진 팀의 중앙을 포커싱하며, 동률이면 기존 교전쌍 중심 포커싱으로 되돌아갑니다.
### 미니맵 가이드라인
미니맵은 전장 전체를 축소하여 보여주는 독립된 카메라입니다. 주 카메라가 비추는 영역을 계산하여 미니맵 위에 사각형(`graphics`)을 그려줍니다.
- `camera.displayWidth / zoom` 등을 이용하여 현재 월드에서 보이는 실제 영역 크기를 계산합니다.
- 뷰포트 사각형 좌표는 미니맵 픽셀 격자에 맞춰 반올림하고, 외곽 stroke가 겹쳐 검게 깨지지 않도록 노란 내부 선을 채운 직사각형으로 렌더링합니다.
### 스타팅 영역 오버레이
`스타팅 지점 배치` 매치에서는 `matchSetup.js`가 전장 그리드에서 팀별 중심 셀을 무작위로 뽑아 만든 영역을 `ArenaScene``arenaRenderer.js`에 전달합니다. 렌더러는 각 팀 색상을 낮은 투명도로 채우고 얇게 둘러 실제 스폰 후보 영역을 표시하며, 이 오버레이는 매치 시작 후 5초 동안만 보입니다. 숨김 예약은 Phaser 씬 타이머를 사용하므로 일시정지 시간은 표시 시간에 포함되지 않고, 새 매치가 시작되면 이전 예약을 취소합니다.
### 씬 상태 관리
- **프리뷰 모드 (`presentationMode`)**: 최초 로드 시 조용히 실행되는 배경 전투입니다. 로컬 저장 옵션과 무관하게 10팀 x 5명 고정 규모로 동작합니다.
- **일시정지 (`setPaused`)**: 실제 전투에서 물리, Phaser 타이머, tween, 스프라이트 애니메이션을 함께 제어합니다. 프리뷰 및 종료된 전투는 제외됩니다.
- **월드 이펙트 주기**: 실제 전투 생성 시 `startWorldEffects()`를 시작하고, 첫 포격은 `WORLD_EFFECT.INTERVAL`, 이후 일반 포격은 `WORLD_EFFECT.REPEAT_INTERVAL`을 사용합니다. 새 매치/종료 때 `clearWorldEffects()`로 주기 타이머, 잔여 냉각 구역, 메테오 임시 포커스, 캐릭터 감속 배율을 정리합니다. Phaser 타이머를 사용하므로 일시정지 시간은 이 간격과 냉각 지속시간에 포함되지 않습니다.