Files
maplecontest/docs/superpowers/specs/2026-06-06-ten-maps-design.md
2026-06-06 12:10:56 +09:00

4.6 KiB

맵 10개 생성 (랜덤 배경 + 몬스터 2마리) 설계

  • 날짜: 2026-06-06
  • 브랜치: feature/maps-batch (신규)
  • 대상: map/map02.map~map11.map(신규), Global/SectorConfig.config, tools/gen-maps.mjs(신규)

목표

map01을 템플릿으로 독립 맵 10개(map02~map11) 를 생성한다. 각 맵은 서로 다른 공식 배경을 갖고, 몬스터 2마리가 랜덤 위치에 배치된다.

범위

포함

  • map02~map11 (신규 10개 맵 파일)
  • 맵마다 다른 배경(BackgroundComponent.TemplateRUID) — 공식 MapleStory 배경 라이브러리에서 10개 서로 다르게
  • 맵마다 몬스터 2마리, x 위치 랜덤(바닥 위), y는 바닥 높이 고정
  • SectorConfig.configmap://map02~map://map11 등록
  • 재현용 생성기 tools/gen-maps.mjs

제외 (YAGNI)

  • 맵 간 포털/이동 연결 (독립 맵)
  • 맵별 다른 타일맵/지형 (map01 타일·바닥 그대로 복제)
  • 카드-전투 로직 연동
  • map01 변경

몬스터 전략 (스파이크 게이트)

사용자 선택: 라이브러리에서 다양한 몬스터. 단, 리소스 검색이 RUID만 반환하고 action(stand/hit/die) 그룹핑·이름을 주지 않아 "완결된 몬스터" 조립이 불확실하다. 따라서:

  • A. 라이브러리 다양 몬스터 (1차 시도): 라이브러리에서 완결된 몬스터 2~3종(스프라이트 + stand/hit/die 애니메이션 RUID 세트)을 조립한다. 먼저 1개 맵으로 스파이크 → Maker Play에서 로드·렌더 검증.
  • 게이트: 스파이크에서 라이브러리 몬스터가 정상 렌더되면 → 10개 맵에 A로 확대. 조립/로드 실패 시 → B로 폴백.
  • B. 폴백 — 기존 몬스터 변형: 이미 정상 로딩되는 기존 템플릿(StaticMonster/MoveMonster/ChaseMonster/monster-43)의 검증된 RUID 세트에서 맵당 랜덤 2종 + 랜덤 위치. 다양성은 ~4종으로 제한되지만 확실히 동작.

핵심 리스크: 이전에 사용자 업로드(계정) 리소스는 로컬 워크스페이스 플레이에서 로드 실패했다. 공식 라이브러리 리소스(배경/몬스터)는 shipped 콘텐츠라 로드될 것으로 보지만(기존 배경·몬스터 RUID가 정상 로딩 중), 확정 전 스파이크로 검증한다.

구현 방식

생성기 tools/gen-maps.mjs

  1. map/map01.map을 텍스트로 읽어 JSON 파싱(템플릿)
  2. 배경 RUID 풀(10개, 공식 라이브러리에서 확보), 몬스터 정의 풀(A: 라이브러리 세트 / B: 기존 템플릿 세트)을 데이터로 보유
  3. NN = 02..11 각각:
    • 엔티티 deep-copy, 모든 엔티티 id GUID 재발급(oldId→newId 매핑). root_entity_id/sub_entity_id가 엔티티 id를 가리키면 함께 치환. (component 안의 리소스 RUID — SpriteRUID, ActionSheet, TemplateRUID, CollisionGroup.Id, DamageSkinId, 타일셋 id — 는 엔티티 id가 아니므로 유지)
    • EntryKeymap://mapNN, 모든 path/maps/map01/maps/mapNN, namemapNN로 치환
    • Background 엔티티의 TemplateRUIDbackgrounds[NN]로 설정
    • 기존 몬스터 엔티티들을 제거하고, 선택된 몬스터 2종을 랜덤 x 위치로 추가(각 몬스터는 템플릿 몬스터 엔티티를 복제하고 SpriteRUID/ActionSheet[A] 또는 그대로[B] + Position.x 랜덤)
    • map/mapNN.map로 기록(원본 줄바꿈/포맷 보존 방식은 가능하면, 아니면 표준 JSON 직렬화)
  4. Global/SectorConfig.configSectors[0].entriesmap://map02~map11 추가(중복 방지)

랜덤은 결정론을 위해 인덱스 기반 시드(맵 번호로 위치/선택 산출) 사용 — 재실행 시 동일 결과.

GUID 재발급 주의

  • 엔티티 id 충돌 방지를 위해 맵마다 고유 GUID 필요. 자기참조(root_entity_id==자기 id)는 매핑으로 일관되게 치환.

검증

  1. 스파이크(A): map02 1개만 생성 → reload→play→screenshot + Lua로 몬스터 엔티티/스프라이트 로드 확인. 실패 시 B로 전환.
  2. 전체 생성 후: 각 맵(또는 표본)에서 reload→play(해당 맵)→screenshot으로 배경 상이·몬스터 2마리 확인. 맵 전환은 Maker에서 해당 맵을 열거나 sector 이동으로.
  3. JSON 유효성(JSON.parse) + SectorConfig 10개 등록 확인 + 엔티티 id 중복 없음 확인.

산출물/형상관리

  • 신규 파일 map/map02.map~map11.map, tools/gen-maps.mjs, SectorConfig.config 변경을 커밋.
  • 배경/몬스터는 공식 라이브러리 RUID(문자열)만 참조 — 별도 리소스 파일 불필요(공식 콘텐츠). (단 A가 로컬 임포트를 요구하면 그 리소스 파일도 포함)