Files
maplecontest/docs/superpowers/specs/2026-06-11-card-visuals-design.md
gahusb 18729a2047 docs(card-visuals): 메이플 스킬 카드 비주얼 설계 (P2)
공식 RUID 렌더 타당성 실측 완료. 카드→전사 스킬 매핑(파워 스트라이크/슬래시 블러스트/아이언 바디),
RUID 수확 워크플로, 카드 프레임(Art/NamePlate/Cost), ApplyCardFace 렌더 일원화(5표면).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 02:35:51 +09:00

78 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 메이플 스킬 카드 비주얼 (P2) — 설계
- 날짜: 2026-06-11
- 대상: `data/cards.json`, `tools/deck/gen-slaydeck.mjs`(카드 엔티티 구조·ApplyCardVisual류), 생성물
- 상태: 승인됨 (배포 퀄리티 로드맵 P2/5 — P1 UI 정비 머지됨 #34)
## 1. 배경 / 타당성 (검증 완료)
카드가 단색 사각형+텍스트(코스트/이름/설명)뿐이라 게임 정체성이 약하다. 메이플 스킬 이미지를 카드에 넣는다.
**타당성 검증 완료(메이커 실측)**: `asset_search_resources`(source=maplestory, cat=sprite)로 "파워 스트라이크" 검색 → 공식 RUID 10+개. 그중 `37ed94ffd1a64a22ad91a6ae14774718`를 Play 중 `SpriteGUIRendererComponent.ImageRUID`(Type=0)에 주입 → **로컬 워크스페이스에서 정상 렌더 확인**(흰 박스 아님 — 흰 박스 문제는 클라우드 '계정' 리소스에만 해당, 공식 리소스는 OK).
주의: 검색 결과는 아이콘이 아니라 **스킬 이펙트 컷**일 수 있음 → 후보 중 선별 단계 필요.
## 2. 카드 → 메이플 스킬 매핑 (데이터)
`data/cards.json`의 각 카드에 선택 필드 추가:
- `image`: 공식 스프라이트 RUID(string). 없으면 현행 단색 폴백.
- 카드 `name`을 메이플 스킬명으로 변경(효과·코스트·밸런스 불변):
| 카드 id | 기존 이름 | 새 이름(전사 스킬) | 효과 |
|---|---|---|---|
| Strike | 타격 | 파워 스트라이크 | 피해 6 |
| Bash | 강타 | 슬래시 블러스트 | 피해 10 |
| Defend | 방어 | 아이언 바디 | 방어도 5 |
(id는 기존 유지 — RunDeck/starterDeck 호환. 표시명만 변경.)
## 3. RUID 수확 워크플로 (구현 선행 태스크)
1. `asset_search_resources`(source=maplestory)로 스킬별 후보 수집: "파워 스트라이크", "슬래시 블러스트", "아이언 바디" (+필요시 "워리어", "스킬" 등 보조 질의).
2. 메이커 Play에서 후보 RUID를 카드 Art에 순회 주입 + 스크린샷으로 선별(§1에서 검증한 방법). 카드 일러스트로 보기 좋은 컷 1개/스킬 확정.
3. 확정 RUID를 `data/cards.json`에 기록. (RUID 문자열만 저장 — 공식 콘텐츠 정책 기존 관행과 동일)
4. 적합 컷이 없으면 폴백: 그 카드들은 이펙트 컷 중 베스트, 그래도 없으면 image 필드 생략(단색 유지).
## 4. 카드 프레임 구조 (upsertUi — 손패 Card1~5 기준)
기존: 루트(단색 패널) + Cost/Name/Desc 텍스트 3개.
변경(카드 180×250 기준):
```
Card{i} (루트: 종류색 패널 — 테두리 역할, 기존 ATTACK/DEFEND/SKILL 색 유지)
├─ Art 96×96 중앙상단(pos 0, 52): ImageRUID, Type=0, 흰색
├─ NamePlate 168×34 (pos 0, -8): 어두운 띠 {0.07,0.08,0.1,0.92}
│ └─ (Name 텍스트를 NamePlate 위치로 이동, fontSize 20)
├─ Cost 44×44 좌상(pos -68, 103): 어두운 원판 패널 + 숫자 26 (기존 위치 강조형)
└─ Desc (pos 0, -62, fontSize 18) 하단 효과 텍스트
```
- 구현은 기존 자식 텍스트(Cost/Name/Desc) 위치·크기 조정 + 신규 Art/NamePlate/CostPlate 스프라이트 추가.
- 동일 구조를 **RewardHud/Reward{1~3}**, **ShopHud/Card{1~3}**, **DeckInspectHud/Grid/Card{n}**, **DeckAllHud/Grid/Card{n}** 카드에도 적용(폭이 다른 그리드 카드(158×214)는 비례 축소 좌표).
## 5. 런타임 렌더 일원화
- 신규 헬퍼 `ApplyCardFace(basePath, cardId)`(Lua): Cards[cardId]에서 name/cost/desc/kind/image를 읽어 — 루트 색(kind), Art ImageRUID(있으면 표시·없으면 Art 숨김), Name/Cost/Desc 텍스트 설정.
- 기존 `ApplyCardVisual`(손패)·`ApplyRewardVisual`(보상)·상점 렌더(`RenderShop` 내 카드부)·`ApplyInspectCardVisual`(인스펙터)·모든덱 렌더가 **ApplyCardFace를 호출**하도록 통일(경로만 다름).
- Lua 카드 테이블(`luaCardsTable`)에 `image` 필드 직렬화 추가(없으면 생략).
## 6. 변경 파일
| 파일 | 변경 |
|---|---|
| `data/cards.json` | name 3종 변경 + image RUID 3종 추가 |
| `tools/deck/gen-slaydeck.mjs` | luaCardsTable image, 카드 엔티티 프레임(5표면), ApplyCardFace + 호출부 통일 |
| 생성물 | `ui/DefaultGroup.ui`·`SlayDeckController.codeblock` 재생성 |
| `tools/balance/sim-balance.mjs` | 불변(이름 표시는 data에서 읽음 — 리포트에 새 이름 자동 반영) |
## 7. 범위 제외 (후속)
의도 아이콘(P3), 카드 호버 확대·사용 연출(P3), 희귀도 프레임 색(P5), 도적/마법사 카드(후속 콘텐츠).
## 8. 검증
- 생성 결정성·dup id 0·sim 14/14(이름 변경이 테스트에 영향 없는지 확인 — 테스트는 자체 fixture 사용이라 무관).
- 메이커: 손패/보상/상점/덱보기 4표면 스크린샷 — 스킬 이미지·프레임·이름 일관 표시, image 누락 카드 폴백 정상.
## 9. 리스크
- 후보 RUID가 멀티프레임 애니 시트일 수 있음 → SpriteGUIRenderer가 첫 프레임 표시(기존 옵션 FrameColumn/Row 1) — 선별 단계에서 확인.
- 그리드 카드(인스펙터/모든덱)는 ScrollLayoutGroup 셀 — 자식 추가가 셀 레이아웃에 영향 없는지 메이커 확인.