From 1668e3c941c909649e31bd73ba3d4cad317871d3 Mon Sep 17 00:00:00 2001 From: Horoli Date: Sun, 24 May 2026 19:16:51 +0900 Subject: [PATCH] feat: implement world effects, role-based stats, and optimized starting zones with refactored constants --- context/arena.md | 14 +- context/combat.md | 17 +- context/core.md | 14 +- context/fighter.md | 8 + index.html | 2 +- public/assets/effects/world_Effect.png | Bin 0 -> 1703 bytes public/assets/effects/world_Effect_2.png | Bin 0 -> 8797 bytes src/constants.js | 342 ++++++++++----------- src/game/arena/ArenaScene.js | 225 ++++++++++---- src/game/arena/arenaRenderer.js | 42 ++- src/game/arena/arenaSpectatorCamera.js | 21 +- src/game/combat/combat.js | 220 ++++++++------ src/game/combat/worldEffects.js | 362 +++++++++++++++++++++++ src/game/fighter/fighterAssets.js | 49 ++- src/game/fighter/fighterFactory.js | 45 ++- src/game/fighter/fighterManifest.js | 2 +- src/game/fighter/fighterStats.js | 52 ++++ src/game/match/arenaMatchRuntime.js | 4 +- src/game/match/matchSetup.js | 142 +++++---- src/main.js | 13 +- src/ui/arenaScoreboard.js | 64 ++-- src/ui/matchForm.js | 8 +- 22 files changed, 1146 insertions(+), 500 deletions(-) create mode 100644 public/assets/effects/world_Effect.png create mode 100644 public/assets/effects/world_Effect_2.png create mode 100644 src/game/combat/worldEffects.js create mode 100644 src/game/fighter/fighterStats.js diff --git a/context/arena.md b/context/arena.md index 9b245b0..b3ed993 100644 --- a/context/arena.md +++ b/context/arena.md @@ -3,7 +3,7 @@ ## 1. 모듈별 상세 역할 (`src/game/arena/`) - **`ArenaScene.js`**: Phaser 씬의 생명주기와 전반적인 오케스트레이션을 담당합니다. `update()` 매 프레임마다 전투원 상태를 체크하고, 카메라 이동 및 UI 모듈 호출을 조율합니다. -- **`arenaRenderer.js`**: 아레나 배경 그래픽 및 타일 렌더링을 담당합니다. +- **`arenaRenderer.js`**: 아레나 배경 그래픽, 타일 및 팀별 스타팅 영역 오버레이 렌더링을 담당합니다. - **`arenaSpectatorCamera.js`**: 관전 모드 시점 계산 및 카메라 포커싱 로직을 담당합니다. 생존 인원에 따른 지능형 카메라 추적 알고리즘이 구현되어 있습니다. ## 2. 주요 로직 구현 세부 사항 @@ -13,11 +13,13 @@ 1. 목표 좌표(`targetX, targetY`)를 `Math.round()`로 정수화합니다. 2. 현재 카메라 위치에서 목표 지점까지 매 프레임 `0.1`의 배율로 거리를 좁혀나가는 `Lerp` 연산을 수행합니다. ```javascript -this.cameras.main.scrollX += (targetX - this.cameras.main.midPoint.x) * SPECTATOR_CAMERA_LERP; +this.cameras.main.scrollX += (targetX - this.cameras.main.midPoint.x) * CAMERA.SPECTATOR_LERP; ``` -최종교전 관전은 두 단계로 나뉩니다. -- **생존 4명 이하**: `SPECTATOR_RANDOM_FOCUS_INTERVAL`마다 생존 캐릭터 중 한 명을 무작위로 포커싱합니다. +자동 관전은 월드 이펙트 임시 시점, 후반 진입과 최종교전 세부 포커싱으로 나뉩니다. +- **메테오 임시 포커싱**: 자동 관전 진입 전 화염 또는 냉기 메테오가 시작되면 착탄 지점을 임시로 확대 추적하고, 착탄 후 `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명 이하**: 더 적은 생존 수를 가진 팀의 중앙을 포커싱하며, 동률이면 기존 교전쌍 중심 포커싱으로 되돌아갑니다. ### 미니맵 가이드라인 @@ -25,6 +27,10 @@ this.cameras.main.scrollX += (targetX - this.cameras.main.midPoint.x) * SPECTATO - `camera.displayWidth / zoom` 등을 이용하여 현재 월드에서 보이는 실제 영역 크기를 계산합니다. - 뷰포트 사각형 좌표는 미니맵 픽셀 격자에 맞춰 반올림하고, 외곽 stroke가 겹쳐 검게 깨지지 않도록 노란 내부 선을 채운 직사각형으로 렌더링합니다. +### 스타팅 영역 오버레이 +`스타팅 지점 배치` 매치에서는 `matchSetup.js`가 전장 그리드에서 팀별 중심 셀을 무작위로 뽑아 만든 영역을 `ArenaScene`이 `arenaRenderer.js`에 전달합니다. 렌더러는 각 팀 색상을 낮은 투명도로 채우고 얇게 둘러 실제 스폰 후보 영역을 표시하며, 이 오버레이는 매치 시작 후 5초 동안만 보입니다. 숨김 예약은 Phaser 씬 타이머를 사용하므로 일시정지 시간은 표시 시간에 포함되지 않고, 새 매치가 시작되면 이전 예약을 취소합니다. + ### 씬 상태 관리 - **프리뷰 모드 (`presentationMode`)**: 최초 로드 시 조용히 실행되는 배경 전투입니다. 로컬 저장 옵션과 무관하게 10팀 x 5명 고정 규모로 동작합니다. - **일시정지 (`setPaused`)**: 실제 전투에서 물리, Phaser 타이머, tween, 스프라이트 애니메이션을 함께 제어합니다. 프리뷰 및 종료된 전투는 제외됩니다. +- **월드 이펙트 주기**: 실제 전투 생성 시 `startWorldEffects()`를 시작하고, 새 매치/종료 때 `clearWorldEffects()`로 주기 타이머, 잔여 냉각 구역, 메테오 임시 포커스, 캐릭터 감속 배율을 정리합니다. Phaser 타이머를 사용하므로 일시정지 시간은 4초 발동 간격과 냉각 지속시간에 포함되지 않습니다. diff --git a/context/combat.md b/context/combat.md index 49dc934..9412c36 100644 --- a/context/combat.md +++ b/context/combat.md @@ -2,28 +2,37 @@ ## 1. 모듈별 상세 역할 (`src/game/combat/`) -- **`combat.js`**: 전투 AI, 피해 계산, 처치 보상 등 핵심 전투 로직을 담당합니다. 유닛의 이동, 공격, 투사체 발사 등을 처리합니다. +- **`combat.js`**: 전투 AI, 피해 계산, 처치 보상 등 핵심 전투 로직을 담당합니다. `fighterStats.js`에서 해석한 역할별 수치로 이동, 공격, 투사체 발사 등을 처리합니다. - **`combatSettings.js`**: 전투 속도 배율 등 런타임 전투 설정을 관리합니다. - **`arenaFinalCombatEffects.js`**: 최종 교전 시 슬로우 모션 등 연출 효과를 담당합니다. 수학적인 이징(easing) 함수와 물리 시간 배율 계산을 포함합니다. +- **`worldEffects.js`**: 실제 전투에서 4초마다 발동하는 화염/냉기 메테오 선택, 사분면별 대각선 낙하 연출, 5x5 영역 판정, 냉기 동결과 감속 구역 수명주기를 처리합니다. ## 2. 주요 로직 구현 세부 사항 ### 전투 AI 및 유닛 동작 - **`updateFighter()`**: 가장 가까운 적을 찾아 이동하거나 공격하는 유닛 AI의 핵심입니다. -- **`applyHit()`**: 일반 공격 피해량은 `ATTACK_DAMAGE_MIN/MAX` 범위에서 계산하고, 치명타 적중은 `Critical!` 표기와 즉시 처치/카메라 흔들림을 처리합니다. +- **`applyHit()`**: 일반 공격 피해량은 공격자의 `melee`/`ranged`/`magic` 프로필 피해량 범위에서 계산하고, 치명타 적중은 `Critical!` 표기와 즉시 처치를 처리합니다. +- **역할별 기본값**: `src/constants.js`의 `FIGHTER_TYPE_STATS`에서 체력, 이동속도, 사거리, 공격 쿨다운, 피해량, 치명타 확률, 발동 지연을 독립적으로 조절합니다. 투사체 속도는 `ranged`, 효과 적중 지연은 `magic` 프로필에 포함됩니다. - **`projectilePathHitsDefender()`**: 투사체가 대상을 스쳐 지나가지 않도록 궤적(Line)과 히트박스(Rectangle) 겹침 검사를 수행합니다. ### 처치 보상 및 성장 - **`applyKillReward()`**: 처치한 캐릭터의 체력 회복(현재 체력 30%), 크기 증가, 공격속도/이동속도 배율 증가를 처리합니다. 누적 배율은 `KILL_GROWTH_MAX_MULTIPLIER`로 제한합니다. - **`clampFighterInsideArena()`**: 처치 성장 중 커진 캐릭터가 전장 바깥으로 나가지 않도록 위치를 보정합니다. +### 월드 이펙트 +- **발동 규칙**: 프리뷰가 아닌 실제 전투에서 전투 시간 4초마다 생존 캐릭터 하나를 무작위로 선택하고, 대상의 당시 위치를 중심으로 메테오 또는 냉각지대 중 하나를 무작위 발동합니다. +- **낙하 방향과 크기**: 대상이 전장 좌측 반면(2, 3사분면)이면 화살표가 좌상단에서 우하단으로, 우측 반면(1, 4사분면)이면 좌우 반전되어 우상단에서 좌하단으로 이동합니다. 스프라이트를 45도로 기울이고 전용 시각 배율을 사용해 전역 마법 규모로 표현합니다. +- **화염 메테오**: `world_Effect.png`의 7프레임 애니메이션이 낙하하면 화면 흔들림을 적용하고, 5x5 타일 영역의 생존자에게 고정 피해를 줍니다. 자동 관전 진입 전에는 `CAMERA.METEOR_FOCUS_ENABLED`가 켜져 있을 때 착탄 위치를 임시 포커싱합니다. 환경 피해로 인한 사망은 킬 보상을 지급하지 않지만 사망 통계와 승패 판정에는 반영됩니다. +- **냉기 메테오**: `world_Effect_2.png`의 7프레임 애니메이션으로 착탄을 표시하고, 자동 관전 진입 전에는 같은 설정에 따라 착탄 위치를 임시 포커싱합니다. 착탄 시 별도 조정 가능한 피해를 주며, 생존한 피격 대상은 캐릭터 본체와 실루엣이 얼음색으로 바뀐 채 2초 동안 기절합니다. 이후 남은 5x5 냉각지대 안에서는 공격속도와 이동속도 감속 배율을 적용하며, 영역을 벗어나거나 지속시간이 끝나면 배율을 복구합니다. + ### 최종교전 슬로우모션 -`FINAL_COMBAT_SLOW_MOTION_ENABLED`가 활성화된 경우: +`COMBAT.FINAL_SLOW_MOTION_ENABLED`가 활성화된 경우: - 최종교전 상태에서 공격 모션이 시작될 때 전역 time scale을 낮춥니다. - 진입/유지/복귀 속도 램프(Ease)를 적용합니다. - Arcade Physics는 timeScale 방향이 반대라 물리 이동에는 역수 배율을 적용합니다. ## 3. 유지보수 규칙 - **처치 성장 상한**: `src/constants.js`의 `KILL_GROWTH_MAX_MULTIPLIER`를 수정합니다. -- **공격력 조정**: `src/constants.js`의 `ATTACK_DAMAGE_MIN/MAX`를 수정합니다. +- **공격력 조정**: `src/constants.js`의 `FIGHTER_TYPE_STATS..damageMin/damageMax`를 수정합니다. +- **월드 이펙트 조정**: `src/constants.js`의 `WORLD_EFFECT.METEOR_DAMAGE`와 `WORLD_EFFECT.FROST_DAMAGE`로 두 메테오 피해를 각각 조정하고, `WORLD_EFFECT.FROST_STUN_DURATION`/`FROST_STUN_TINT`로 동결 시간과 표시 색상을 조정합니다. 나머지 `WORLD_EFFECT.*` 값으로 발동 주기, 범위, 냉각 지속시간과 감속 정도를 수정하며, 메테오 착탄 위치 포커싱은 `CAMERA.METEOR_FOCUS_ENABLED`에서 켜고 끕니다. - **특수 규칙**: 캐릭터별 특수 공격 방식은 `fighterManifest.js`의 `combat` 설정을 확인합니다. diff --git a/context/core.md b/context/core.md index c345484..b1e2fdf 100644 --- a/context/core.md +++ b/context/core.md @@ -7,13 +7,16 @@ - `Start` 버튼, 옵션 drawer, 전투 시작 submit 흐름을 제어하며 전투 시작 시 `#app`에 `match-live` 상태 클래스를 부여합니다. - 전투 중 drawer 접기/펼치기(`drawer-collapsed`), 재시작 버튼, 일시정지 버튼 상태(`match-paused`)를 DOM 클래스와 `ArenaScene` 상태에 동기화합니다. - **`src/constants.js`**: 게임 내 모든 튜닝 수치를 관리합니다. - - `ATTACK_DAMAGE_MIN`, `ATTACK_DAMAGE_MAX`: 일반 공격 1회 적중 시 적용되는 랜덤 피해량 범위. + - `FIGHTER_TYPE_STATS`: `melee`, `ranged`, `magic`별 최대 체력, 이동속도, 사거리, 쿨다운, 피해량, 치명타 및 공격 발동 지연 기본값. - `FIGHTER_HITBOX_*`: 100x100 캐릭터 프레임 안에서 실제 충돌 판정이 놓이는 위치와 크기. - `KILL_HEALTH_RECOVERY_RATIO`, `KILL_GROWTH_MULTIPLIER`, `KILL_GROWTH_MAX_MULTIPLIER`: 처치 후 회복량, 크기/공격속도/이동속도 성장 배율, 누적 보상 상한. + - `WORLD_EFFECT.*`: 월드 이펙트 발동 간격, 5x5 범위, 대각선 낙하 거리/시각 배율, 화염/냉기 메테오 피해량, 냉기 동결 시간/실루엣 색상, 냉각지대 지속시간과 감속 배율. - `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, 배율과 속도 램프 시간. + - `CAMERA.SPECTATOR_LERP`: 카메라 추적의 부드러움 정도. + - `CAMERA.METEOR_FOCUS_ENABLED`, `CAMERA.METEOR_FOCUS_ZOOM`, `CAMERA.METEOR_FOCUS_HOLD_DURATION`: 자동 관전 진입 전 화염/냉기 메테오 착탄 위치의 임시 포커싱 on/off, 확대 배율 및 착탄 후 유지 시간. + - `CAMERA.SPECTATOR_LATE_FIGHTER_THRESHOLD`: 생존 인원 임계값에 따른 후반 자동 관전 진입 조건. (2팀만 남았더라도 이 수치보다 인원이 많으면 자동 관전을 유예합니다.) + - `CAMERA.SPECTATOR_FINAL_TEAM_TOTAL_THRESHOLD`, `CAMERA.SPECTATOR_RANDOM_FOCUS_INTERVAL`, `COMBAT.FINAL_SLOW_MOTION_*`: 최종교전 관전 조건, 랜덤 포커싱 간격, 슬로우모션 on/off, 배율과 속도 램프 시간. - `MINIMAP_VIEWPORT_SIZE`: 미니맵의 고정 픽셀 크기. - `ARENA_SIZE`: 경기장 전체 크기 (GRID * TILE). @@ -21,8 +24,9 @@ - **신규 캐릭터 추가**: `public/assets/characters/`에 에셋 배치 후 `fighterManifest.js`에 정의를 추가하면 즉시 게임에 반영됩니다. - **종족값 유지**: 신규 스킨을 추가할 때는 사망 통계가 누락되지 않도록 `species`를 `human`, `orc`, `skeleton`, `slime`, `wolf`, `bear` 중 하나로 지정해야 합니다. -- **물리 수치 조정**: 캐릭터의 속도나 사거리 등은 `src/constants.js` 또는 `fighterManifest.js` 내 개별 설정을 통해 변경하십시오. +- **물리 수치 조정**: 역할별 기본 체력/속도/사거리/공격 수치는 `src/constants.js`의 `FIGHTER_TYPE_STATS`에서 변경하고, 특정 스킨만 다르게 할 때는 `fighterManifest.js`의 `stats` 또는 `combat` 설정을 사용하십시오. - **처치 성장 상한 조정**: 처치 보상으로 캐릭터가 커지는 최대치와 공격/이동 배율 상한은 `src/constants.js`의 `KILL_GROWTH_MAX_MULTIPLIER`를 수정합니다. -- **공격력 조정**: 기본 피해량은 `src/constants.js`의 `ATTACK_DAMAGE_MIN`, `ATTACK_DAMAGE_MAX`를 수정합니다. 캐릭터별 특수 공격 방식은 `fighterManifest.js`의 `combat` 설정을 우선 확인합니다. +- **공격력 조정**: 역할별 기본 피해량은 `src/constants.js`의 `FIGHTER_TYPE_STATS..damageMin/damageMax`를 수정합니다. 캐릭터별 특수 공격 방식은 `fighterManifest.js`의 `combat` 설정을 우선 확인합니다. +- **월드 이펙트 조정**: `src/constants.js`의 `WORLD_EFFECT.INTERVAL`, `WORLD_EFFECT.FALL_TRAVEL_TILES`, `WORLD_EFFECT.VISUAL_SCALE`, `WORLD_EFFECT.METEOR_DAMAGE`, `WORLD_EFFECT.FROST_DAMAGE`, `WORLD_EFFECT.FROST_STUN_DURATION`, `WORLD_EFFECT.FROST_STUN_TINT`, `WORLD_EFFECT.FROST_DURATION`, `WORLD_EFFECT.FROST_SPEED_MULTIPLIER`를 수정합니다. 임시 메테오 카메라는 `CAMERA.METEOR_FOCUS_ENABLED`로 끌 수 있습니다. - **DOM 접근**: 성능을 위해 `ArenaScene`은 좌측 HUD badge 등 필요한 시점에만 최소한으로 DOM에 접근합니다. - **패키지 락 파일**: 이 프로젝트는 `package-lock.json`을 저장소에서 제외합니다. 의존성 변경 시 `package.json`을 기준으로 관리합니다. diff --git a/context/fighter.md b/context/fighter.md index ccc5eea..3d49f3b 100644 --- a/context/fighter.md +++ b/context/fighter.md @@ -5,6 +5,7 @@ - **`fighterAssets.js`**: 캐릭터 스프라이트 로드 및 애니메이션/실루엣 생성을 담당합니다. 원본 이미지로부터 팀 색상 마커용 실루엣을 동적으로 생성합니다. - **`fighterFactory.js`**: 캐릭터 인스턴스화 및 HUD(이름표, 체력바) 관리를 담당합니다. Phaser Sprite와 DOM UI 사이의 가교 역할을 합니다. - **`fighterManifest.js`**: 모든 캐릭터 종족 및 스탯 데이터를 정의합니다. 20여 종의 캐릭터 설정이 포함되어 있습니다. +- **`fighterStats.js`**: 공격 방식으로 `melee`, `ranged`, `magic` 역할을 판별하고 역할별 기본 스탯과 스킨별 오버라이드를 병합합니다. - **`fighterSelection.js`**: 매치 참여 캐릭터를 무작위로 선택하거나 섞는 로직을 담당합니다. ## 2. 주요 로직 구현 세부 사항 @@ -19,12 +20,19 @@ ### 캐릭터 HUD 및 상태 동기화 - **이름표 고정**: 스프라이트 중심이 아닌 실제 히트박스 하단에 고정되어 시각적 일관성을 유지합니다. - **사망자 처리**: 사망 시 HUD와 팀 마커를 숨겨 화면 가독성을 높입니다. 본체 sprite만 낮은 depth와 반투명 상태로 남깁니다. +- **월드 감속 상태**: 생성 시 `worldEffectSpeedMultiplier`를 `1`로 초기화하며, 냉각지대 안에서는 `worldEffects.js`가 해당 배율을 낮춰 공격속도와 이동속도 계산에 반영합니다. +- **냉기 동결 상태**: `isFrostStunned`와 동결 타이머를 캐릭터별로 관리합니다. 냉기 메테오 착탄에 생존하면 캐릭터 본체와 팀 실루엣 마커가 함께 얼음색으로 바뀌고, 동결 종료 시 본체 원본 색상과 저장된 팀 색상으로 복구됩니다. ### 캐릭터별 특성 (예: Slime) - **`spawnMultiplier`**: 배정된 슬롯 1개를 지정된 수만큼 확장하여 스폰합니다. - **`splitOnDeath`**: 사망 시 확률적으로 지정된 수만큼 분열체를 생성합니다. - **스탯 상한**: 처치 보상은 현재 체력을 회복시키지만 `maxHp`를 넘을 수 없습니다. (예: Slime은 항상 1 HP) +### 역할별 전투 스탯 +- `combat.type`이 `projectile`이면 `ranged`, `instant-spell`이면 `magic`, 그 외에는 `melee` 기본 프로필을 사용합니다. +- 새로운 공격 구현이 기본 판별과 다른 역할을 사용해야 할 때는 `combat.fighterType`에 `melee`, `ranged`, `magic` 중 하나를 명시합니다. +- 개별 스킨의 기존 `stats.maxHp`, `combat.range`, `combat.cooldown`, `combat.criticalChance`, `combat.projectile.speed`, `combat.attackEffect.hitDelay` 설정은 역할별 기본값보다 우선합니다. + ## 3. 유지보수 규칙 - **신규 캐릭터**: 에셋 배치 후 `fighterManifest.js`에 정의를 추가합니다. - **종족값**: 사망 통계를 위해 지정된 6개 종족 중 하나를 반드시 선택해야 합니다. diff --git a/index.html b/index.html index 9a4476a..ba63fd1 100644 --- a/index.html +++ b/index.html @@ -215,7 +215,7 @@ Player 10 - 집결 배치 + 스타팅 지점 배치