CharacterSelectHud 단색 박스 → 캐릭터 이미지 카드(이름 하단 배너·선택 금색 테두리), 뒤로가기→로비. data/characters.json 단일 소스(메이커 임포트 RUID). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
8.0 KiB
8.0 KiB
직업 선택 — 캐릭터 이미지 + 뒤로가기 설계
작성일: 2026-06-16
브랜치: feature/charselect-images
목표
런 시작 시 띄우는 캐릭터(직업) 선택 화면(CharacterSelectHud)을 두 가지로 개선한다:
- 직업 3종(전사/도적/마법사)을 지금의 단색 네모 박스 → 각 직업 캐릭터 이미지 카드로. 이미지를 선택하면 그 직업으로 런 진행(기존 연결 유지).
- 직업 선택 화면에 뒤로가기 버튼 추가 → 로비로 복귀.
요청 원문: "런 시작 시, 직업 선택 창을 뒤로가기도 가능하게 추가. 각 직업별로 지금은 네모 박스인데 각각 이미지(warrior/mage/bandit.png) 추가해서 적용하고, 선택했을 때 그 캐릭터로 진행하도록 연결."
확정된 결정 (브레인스토밍)
| 항목 | 결정 |
|---|---|
| 이미지 RUID 확보 | 사용자가 메이커에서 3 PNG 로컬 임포트 → .sprite+RUID(P13 카드프레임과 동일). MCP/계정 업로드는 흰박스라 불가 |
| 이미지 배치 | 카드 전체를 이미지로, 이름은 하단 배너, 선택 시 금색 테두리 |
| 뒤로가기 대상 | 로비로 (ShowLobby()) — 로비 NPC에서 진입하므로 |
소스 이미지 (사용자 임포트 대상)
- 전사:
C:\Users\jaeoh\Desktop\workspace\source\images\maple\character\warrior.png(~1.05MB) - 법사:
…\mage.png(~1.28MB) - 도적:
…\bandit.png(~1.0MB)
세 PNG는 현재 워크스페이스 미임포트(코드 미참조). 기존 RootDesk/MyDesk/*_normal|unique|legend.sprite는 P13 카드 프레임이지 캐릭터 초상화가 아니다.
현재 구조 (조사 결과)
- CLASSES 상수
gen-slaydeck.mjs:7-11—warrior{label,maxHp},bandit,magician. - CharacterSelectHud emit
:2432-2598.classCards배열:2482-2486(key Warrior/Thief/Mage, classId warrior/bandit/magician, x −360/0/360, tint). 각 카드(270×330)의 자식:Name(상단, 108),Portrait(142×142 색상 tint,:2524-2525부근),Desc(하단 −105),LockBody/LockShackle(비활성 직업용). 별도…DeckButton(덱 보기)·StartButton. - 선택 로직: 클릭 바인딩
BindMenuButtons내:3100/3108/3116→SelectClass(classId):3358-3361(=self.SelectedClass=…+RenderCharacterSelect()). 시작:3151-3157→StartNewGame:3395-3399(미선택 가드 후StartRun()). - RenderCharacterSelect
:3362-3394— 선택 카드 밝게/미선택 어둡게 + Status 텍스트. - 진입/전환:
ShowState:3062-3078가 HUD 토글. 진입 = 로비 NPCOnLobbyNpcInteract:3199-3203(런 비활성 시ShowCharacterSelect():3355-3357) 및 (사실상 미사용) MainMenu:3092.ShowLobby:3175. 게임은 OnBeginPlay→ShowLobby로 부팅(로비 허브). - emit 헬퍼:
entity():466,transform():286,sprite():311(dataId로 ImageRUID 주입 가능),button():347,text():372,guid(). - 이미지 외부화 패턴: 카드프레임은
data/cardframes.json→luaFramesTable()(:72부근) →self.CardFramesLua 테이블 + 런타임ApplyCardFace:4167-4202가e.SpriteGUIRendererComponent.ImageRUID=ruid주입. 생성 시 주입은sprite({dataId}).
상세 설계
1) data/characters.json (신설 — 단일 소스)
{
"portraits": {
"warrior": "<32hex RUID>",
"magician": "<32hex RUID>",
"bandit": "<32hex RUID>"
}
}
- 사용자 임포트 후
RootDesk/MyDesk/*.sprite에서 RUID를 읽어 채운다(파일명은 임포트 시 결정 —warrior.sprite등으로 매칭, 모호하면 사용자 확인). - 나중에 이미지 교체 = 이 파일 RUID만 바꿔 재생성.
2) gen-slaydeck.mjs — 로드·검증·주입
- 상단에서
const CHARS = JSON.parse(readFileSync('data/characters.json','utf8'))로드(cardframes 로드 패턴 인접). - fail-fast 검증:
portraits에warrior/magician/bandit3키 존재 + 각 값이 32hex. 누락 시 throw. - 카드 Art 이미지는 생성 시
dataId주입(런타임 테이블 불필요). 즉classCards의 classId로CHARS.portraits[classId]를 조회해 Art 스프라이트dataId에 박는다.
3) CharacterSelectHud — 카드 전체 이미지화 (:2432-2598, classCards emit 루프)
각 직업 카드 구조를 다음으로 변경(엔티티 경로 …/{key}Button·클릭 바인딩은 불변):
{key}Button(270×330): 클릭 가능한 테두리 프레임. sprite Color = 미선택 어둡게(0.16,0.2,0.26,1)/선택 금색(1,0.82,0.3,1). raycast on,button()유지.- 신규 자식
Art(약 258×318, 6px 인셋, center):sprite({ dataId: CHARS.portraits[classId], type:1, raycast:false })— 캐릭터 이미지 풀블리드. (테두리가 이미지 뒤로 6px 보임 → 금색 테두리 효과.) Name(하단 배너): 반투명 어두운 띠 sprite(예:0,0,0,0.55, 270×54, 하단) + 금색 텍스트. 기존Name재배치.- 제거: 기존 색상
Portrait박스,Desc텍스트(선택 레이아웃에 없음). LockBody/LockShackle: 비활성 직업용으로 유지(현재 3직업 모두 enabled라 표시 안 됨).
4) RenderCharacterSelect Lua 변경 (:3362-3394)
- 기존 "박스 밝게/어둡게"를 테두리(=
{key}Buttonsprite Color) 금색/어둡게로 교체. 선택된 classId의 카드만Color(1,0.82,0.3,1), 나머지Color(0.16,0.2,0.26,1). - Art 이미지는 생성 시 고정 주입이라 런타임 변경 없음. Status 텍스트 로직은 유지.
5) 뒤로가기 버튼
- 신규
CharacterSelectHud/BackButton(ShopHudLeave패턴 재사용:2020-2031): 좌상단(예:pos {x:-820,y:430}, 180×56), text "← 뒤로", DARK sprite +button(). BindMenuButtons에 바인딩 추가(ShopHud Leave 바인딩 패턴:3715-3717):back:ConnectEvent(ButtonClickEvent, function() self:ShowLobby() end). 핸들러 prop 저장(재바인딩 시 해제).ShowCharacterSelect/SelectClass/StartNewGame/StartRun로직 불변.
6) GUID 네임스페이스
- 신규 엔티티(Art·NameBanner·BackButton)는 CharacterSelect용 기존 prefix에 번호 추가. 미등록 prefix면 ns 바이트 등록(생성기 끝 id 유일성 검증이 충돌 잡음).
흐름
로비(맵) ──NPC 상호작용──> ShowCharacterSelect (HUD 오버레이)
카드3=캐릭터 이미지, 클릭 → SelectClass → 금색 테두리
[시작] → StartNewGame(가드) → StartRun (그 직업으로)
[← 뒤로] → ShowLobby() → 로비 HUD 복귀
미러/테스트 영향
- 전투규칙·맵생성 미변경 →
sim-balance/rogue-map미러 동기화 불필요. - 카운트 검증:
CharacterSelectHud/.../ArtImageRUID 3개,BackButton1개, characters.json 3 RUID 등장(tools/verify/count.mjs또는grep -c). - 메이커 플레이테스트: 로비 NPC→3 이미지 표시→클릭 금색 테두리→시작 그 직업으로 진행→뒤로 로비 복귀.
리스크
- 이미지 임포트 선행 의존: RUID가 있어야 생성기 실행 가능. 사용자 임포트 완료 후 진행(임포트 무관한 코드 골격은 먼저 작성 가능).
- 이미지 비율: PNG가 세로 초상화면 258×318(≈0.81 비율)에서 잘리거나 여백 — 임포트 후 스크린샷으로 인셋/사이즈 조정.
ShowLobby()재텔레포트: 이미 로비 맵 위라GoLobbyMap재호출 시 위치/카메라 jolt 가능 → 보이면 뒤로가기를ShowState("lobby")로 축소(플레이테스트 확인).- 흰박스: 공식 절차(로컬 임포트)면 렌더됨. reload 필수.
변경 파일 요약
| 파일 | 변경 |
|---|---|
data/characters.json |
신설 — 직업 3종 초상화 RUID(단일 소스) |
tools/deck/gen-slaydeck.mjs |
characters.json 로드·검증, CharacterSelectHud 카드 이미지화(Art/NameBanner), RenderCharacterSelect 테두리 선택표시, BackButton emit+바인딩 |
RootDesk/MyDesk/*.sprite (×3) |
사용자 임포트 산출물(커밋) |
ui/DefaultGroup.ui·SlayDeckController.codeblock |
재생성 산출물 |