세계관과 인트로
01 게임
이 문서 안에서
이야기 설정과 첫 실행 6장면 컷씬을 정합니다. 코드 기준.
한 줄 요약 — 첫 실행에 한 번, 6장면 17줄의 독백으로 "왜 여기서 다시 시작하는가"를 말하고 이름을 받는다. 두 번째 실행부터는
introSeen이 전부를 건너뛴다.
1. 이야기
왕국 함락일, 플레이어는 금고의 자금만 챙겨 도망친 마지막 왕족입니다. 폐허로 돌아와 주민을 영입하며 왕국을 다시 세웁니다. 시스템 흔적: 시작 주민 0명(명부와 영입), 골드·인장 이원화(두 재화), 실시각 흐름(코어 루프).
코드 기준 지참금: 골드 120, 인장 0, 가방 빈 상태, 주민 0명.
마지막 시종(The Last Attendant)은 설계안만 존재하며 코드에 없습니다. 가칭 Lyra Swift, 튜토리얼 전용 NPC 예정, 아트 1순위 LPC 합성(아트와 LPC 캐릭터).
2. 6장면 컷씬
장면과 배경
SCENES 배열, INTRO_IMG_BASE = "/intro/". 합계 약 6.36 MB, 시작 시 동시 선로딩.
| 장면 | 파일 | 크기 | 키 | 줄 |
|---|---|---|---|---|
| 1 | night- | 0.77 MB | intro.~1.3 | 3 |
| 2 | ruined- | 0.97 MB | intro.~2.2 | 2 |
| 3 | red- | 0.52 MB | intro.~3.4 | 4 |
| 4 | dying- | 0.98 MB | intro.~4.2 | 2 |
| 5 | crown- | 1.17 MB | intro.~5.3 | 3 |
| 6 | dawn.png | 1.95 MB | intro.~6.2 | 2 |
대사 전문 (한국어)
i18n 키 관리. /는 줄바꿈.
| 키 | 한국어 |
|---|---|
intro. | …정말 아무도 없나? |
intro. | 성문은 부서져 있었고, 병영은 텅 비어 있었다. |
intro. | 예전 같았으면 벌써 누군가 뛰어나와 / "왕자님, 오셨습니까!" 라고 외쳤을 텐데. |
intro. | 그날 밤, 하늘이 붉게 물들었다. |
intro. | 숲에서, 동굴에서, 늪에서, / 이제껏 본 적 없는 것들이 쏟아져 나왔다. |
intro. | 마물이었다. / 수를 셀 수 없을 만큼 많았다. |
intro. | 성벽이 무너지는 데 하룻밤이면 충분했다. |
intro. | 병사들은 끝까지 싸웠지만, / 아침이 왔을 때 서 있는 자는 없었다. |
intro. | 쓰러진 자는 그 자리에 남았고, / 걸을 수 있던 자는 뒤도 안 돌아보고 떠났다. |
intro. | 그리고 나는… 남았다. |
intro. | 왜 나는 괜찮았을까. / 면역인 건가, 아니면 저주를 받은 건가. |
intro. | 아니다. 중요한 건 이유가 아니다. |
intro. | 이 땅에는 아직 희망이 남아 있다. |
intro. | 숲은 여전히 푸르고, / 광산에는 광석이, / 강에는 물고기가 있다. |
intro. | ……다시 시작하면 된다. |
intro. | 이번에는… 지킬 것이다. |
intro. | 내 이름은 {name}. / 이 왕국을, 다시 일으킬 것이다. |
기본 16줄(BASE_FLAT_LEN). 이름 입력 후 intro.closing 덧붙어 17줄.
상태 기계
| 상태 | 탭 입력 |
|---|---|
boot — 첫 배경 대기 | 무시 |
typing — 30ms/글자 | 즉시 완성 |
waiting — ▼ | 다음 줄 |
transition — 전환 중 | 무시 |
name — 이름 모달 | 무시 |
done — 타이틀 카드 | 무시 |
| 값 | 수치 |
|---|---|
| 타자기 | 30 ms/글자, 효과음 볼륨 0.32 |
| 장면 전환 대기 | 950 ms (앞 줄 있음) / 350 ms (첫 줄) |
| 배경 로드 강제 진행 | 2,500 ms |
| 부팅→시작 | 250 ms (준비) / 2,000 ms (상한) |
| 이름 포커스 지연 | 350 ms |
| 이름→마지막 대사 | 350 ms |
| 종료 입력 잠금 | 900 ms |
| 타이틀 등장 | 600 ms |
| 켄번스 | 16s ease-out, 1.0→1.09 |
| 크로스페이드 | 1.1s ease-in-out |
스킵: 마지막 장면으로 건너뛴 뒤 이름 입력을 엽니다. 이름은 건너뛸 수 없습니다.
셸 레이어(.mlk-intro, z-index 9000 내부): 이름 모달 45, 부팅 40, 스킵 30, 타이틀 25, 말풍선 20, 힌트 5, 배경 기본. BGM parchment-dawn.mp3(소리와 에셋 파이프라인).
3. 이름 입력
ui/name-input.ui.json. 검증: sanitizeVisibleText() → checkDisplayName(name, { max: 8 }).
| 키 | 한국어 |
|---|---|
intro. | 이름 입력 |
intro. | 게임에서 사용할 당신의 이름을 입력해주세요 |
intro. | 이름을 입력하세요 |
intro. | 최대 8자 |
intro. | 확인 |
intro. | 화면을 터치하면 진행됩니다 |
intro. | 건너뛰기 ▸▸ |
intro. | — 왕국 재건기 — |
intro. | — {name} 영주의 왕국 재건기 — |
intro. | ▶ 시작하기 |
| 거부 사유 | 문구 |
|---|---|
empty | 이름을 입력해주세요 |
too- | 이름이 너무 짧습니다 |
too- | 이름은 8자까지 쓸 수 있습니다 |
profanity | 사용할 수 없는 단어가 들어 있습니다 |
reserved | 운영자로 오해할 수 있는 이름은 쓸 수 없습니다 |
금칙어: 실시간 방과 채팅 필터 같은 파일, name 스코프. Enter isComposing 가드. 이름 사용처: save.name, 타이틀 부제, 세이브 슬롯, 채팅 표시명.
4. 타이틀 카드와 다이아몬드 와이프
타이틀: MY LITTLE KINGDOM + 부제. 다이아몬드 와이프(playDiamondReveal()): clip-path polygon, 1,500 ms, cubic-bezier(0.25,1,0.30,1), fill-mode:both. buildGame()과 허브 BGM은 클립 직후 콜백에서 실행.
5. introSeen
| 조건 | 결과 |
|---|---|
!loadFailed && !save. | 컷씬 → completeIntro(name) → 와이프 → buildGame() |
| 그 외 | 즉시 buildGame() + BGM |
completeIntro()가 이름 + introSeen:true + 타임스탬프를 한 쓰기로 기록. 되돌리기: 세이브 삭제(resetSave() — 설정 화면에는 버튼이 없습니다).
6. 튜토리얼
첫 실행에 한 번, 인트로의 다이아몬드 와이프가 끝난 뒤 자동으로 시작합니다. 게이트는 GameSave.tutorialSeen. 완주와 건너뛰기 모두 markTutorialSeen() 을 부르므로 다음 실행에 다시 묻지 않습니다. 다시 보기: 설정 → 튜토리얼 → 다시 보기. ?tutorial=demo (또는 =1) 는 세이브와 무관하게 강제 재생합니다.
열두 비트 순서 — 인사 2 → 주민 탭 1 → 가방 게이트 → 왕국 게이트 → 왕국 화면 2 → 미션 게이트 → 설정 게이트 → 설정 화면 1(다시 보기 행) → 마무리 → 영입 게이트. 인장소는 일부러 넣지 않았습니다.
읽어 주는 투어가 아니라 눌러 보는 투어입니다. 소개하는 탭 네 개(가방·왕국·미션·설정)가 모두 gateOnAnchor 입니다: 카드가 멈추고 그 탭의 링만 점멸하며, 그 탭을 누르는 것 외에는 아무 탭도 받지 않습니다. 누름은 진짜 누름입니다 — 스크림 캐처(.tut-catch)가 앵커 자리만 clip-path 로 뚫려 있어 탭의 원래 클릭 핸들러가 그대로 돌고, 스크림 뒤의 화면이 실제로 바뀝니다. 그래서 그다음 비트는 막 열린 화면 안을 짚습니다 (.kd-bar-wrap 명성 바, .kd-level 왕국 레벨, .s-tutorial-row 다시 보기 행). 탭 이름표에 링을 씌워서는 "그건 여기 있습니다"까지만 말할 수 있습니다.
주민 탭만 예외입니다. 투어는 그 탭에서 시작하므로(main.ts:startTutorial 이 activate("villagers")), 눌러도 화면이 바뀌지 않는 누름을 요구하면 링이 거짓말을 한다고 가르치게 됩니다 — 이름만 짚습니다.
화면 안을 짚는 비트는 TourBeat.screen 으로 필요한 탭을 선언하고, 투어는 onStep(엔진이 앵커를 찾기 전에 부릅니다)에서 호스트의 showScreen 을 불러 그 탭을 엽니다. 화면은 제거가 아니라 visibility 로 숨기므로, 이 선언이 없으면 rect 는 멀쩡하고 아무도 볼 수 없는 요소에 링이 씌워집니다. 호스트(main.ts)는 이미 열려 있는 탭이면 아무것도 하지 않습니다: 게이트에서 플레이어가 방금 열어 둔 화면을 다시 세우면 광장의 주민들이 말 도중에 처음부터 걸어오고, 아무도 이동하지 않은 screen_view 가 하나 더 찍힙니다. 마무리 비트는 화면 전체가 어두운 가운데 screen: "villagers" 로 돌아가므로, 마지막 영입 게이트는 보이는 버튼 위에서 열립니다.
명성은 카드 두 장을 씁니다. 다른 탭은 목록이지만 왕국의 숫자는 규칙이고, 그 규칙이 명성입니다 — 쓰이지 않고, 줄지 않고, 광장 칸·왕실 자리·가축 우리를 여는 유일한 값입니다(왕국). 탭 이름만 짚고 지나가던 동안에는 화면 맨 위의 명성 바를 아무도 설명하지 않았고, 탭을 가리키며 바를 설명하던 동안에도 크게 낫지 않았습니다.
진행 탭은 스크림과 말풍선 자체 양쪽에서 받습니다. 카드는 스크림 캐처보다 위에 있고 자기 포인터 이벤트를 먹으므로, 캐처만 듣던 동안에는 카드 위의 탭이 아무 데도 닿지 않았습니다 — '탭하여 계속'이 쓰인 자리가 화면에서 유일한 사각지대였습니다. 그래서 .tut-cardpos 에도 같은 핸들러를 답니다. 타이핑 중 탭은 인트로와 같이 그 줄을 즉시 완성하고, 게이트 비트에서는 말풍선 탭도 넘어가지 않습니다(앵커 전용). 단, 타이핑 중에 앵커를 누른 것은 통과입니다: 그 누름은 이미 게임에서 일어났으므로(탭이 바뀌었습니다) 이미 눌린 버튼을 한 번 더 누르라고 하지 않습니다.
카드 발치의 안내 문구는 비트마다 갱신되고, 게이트에서는 무엇을 누를지 이름으로 말합니다: tutorial.gate.tab = "'가방' 탭을 누르세요", tutorial.gate.button = "'새 주민 영입' 버튼을 누르세요". 이름은 그 대상이 실제로 달고 있는 라벨 키에서 가져옵니다(TAB_LABEL_KEYS, recruit.open — screens/util.ts 한 곳에서 main.ts 와 투어가 같이 씁니다). "반짝이는 곳을 눌러 주세요"는 오버레이를 설명한 것이지 지시가 아니었습니다 — 탭 여섯 개 중 어느 것이 켜졌는지는 플레이어가 알아내야 했습니다. 엔진의 TutorialOptions.gateHint(tutorial.gate_hint)는 자기 대상을 모르는 비트를 위한 대비책이고, 이 게임의 게이트 다섯 개는 모두 자기 이름을 압니다(테스트가 지킵니다). 게이트에서는 '아무 데나 탭' 신호인 ▼(.tut-next)를 켜지 않습니다. ui/tutorial-coach.ui.json 의 힌트 칸에는 tut-hint ref 가 붙어 있습니다 — 없던 동안에는 문서에 적힌 한국어 리터럴이 영어·일본어 빌드에도 그대로 찍혔습니다.
건너뛰기 알약(.tut-skip)은 링이 닿지 않는 모서리로 옮겨 갑니다(오른위 → 왼위 → 오른아래 → 왼아래, 이동한 뒤 실제로 재서 판정). 왕국 레벨(.kd-level)이 화면 오른위에 있어서, 보라고 한 링과 투어에서 나가는 유일한 문이 같은 자리에 겹쳐 그려지고 있었습니다. 네 모서리가 다 막히면 기본 자리로 되돌립니다 — 겹친 건너뛰기는 보기에 나쁜 것이고, 어디로 갔는지 모를 건너뛰기는 없는 출구입니다. z-index: 2 로 카드 아래에 깔리지도 않습니다.
앵커가 사라진 비트는 버립니다. 특히 게이트 비트는 앵커가 없으면 나갈 길이 없으므로 반드시 버립니다.
| 키 | 한국어 |
|---|---|
tutorial. | 집사 바르톨 |
tutorial. | 폐하, 오셨군요! / 저는 왕실 집사 바르톨입니다. / 오늘부터 이 왕국은 폐하의 것이지요. |
tutorial. | 주민들을 돌보고, 물건을 모으고, / 퀘스트를 완료하다 보면 / 왕국은 저절로 자라난답니다. |
tutorial. | 이곳이 주민 탭입니다. / 주민들은 시간이 지나면 주머니를 채우고, / 폐하께서 그것을 거두어 가시면 됩니다. |
tutorial. (게이트) | 거둔 것은 모두 가방에 쌓입니다. / 쓰지 않으실 물건은 팔아 골드로 바꾸시지요. / 가방 탭을 직접 눌러 보십시오. |
tutorial. (게이트) | 왕국 탭에서는 광장에 건물을 세우고 / 행사를 엽니다. / 왕국 탭을 눌러 함께 가 보시지요. |
tutorial. | 이 막대가 명성입니다. / 완성된 건물을 인수하시거나 행사를 여시면 오르고, / 쓰이지도, 줄지도 않습니다. |
tutorial. | 명성이 쌓이면 이 왕국 레벨이 오릅니다. / 레벨은 광장의 빈 칸과 왕실 자리, / 가축 우리를 차례로 열어 줍니다. |
tutorial. (게이트) | 저 아래 미션 탭에는 / 매일 챙기실 일을 정리해 두었습니다. / 한 번 눌러 보십시오. |
tutorial. (게이트) | 설정에서는 소리와 언어를 바꾸실 수 있습니다. / 설정 탭도 직접 눌러 보시지요. |
tutorial. | 이 안내가 다시 필요하시면 / 여기 '튜토리얼 다시 보기'를 누르시면 됩니다. |
tutorial. | 준비는 끝났습니다, 폐하. / 이제 폐하만의 작은 왕국을 / 마음껏 가꿔 보시지요! |
tutorial. (게이트) | 그리고 첫 걸음은 주민을 맞이하는 일이지요. / '새 주민 영입'을 눌러 보십시오. |
tutorial. | 탭하여 계속 |
tutorial. | '{name}' 탭을 누르세요 |
tutorial. | '{name}' 버튼을 누르세요 |
tutorial. | 표시된 곳을 누르세요 (대비책 — 자기 대상을 아는 비트는 위의 둘을 씁니다) |
tutorial. | 건너뛰기 |
NPC steward(집사 바르톨), 초상 96px. 마지막 시종과 별개. 코치 카드: z-index 9999, 32ms/글자, 폭 min(560px, calc(100vw-24px)), Galmuri 테마.
이어서 읽기
- 코어 루프 — 컷씬 후 플레이어가 돌리는 한 바퀴
- 명부와 영입 — 주민 0명에서 첫 영입
- 두 재화 — 시작 골드와 인장
- 화면 구성 — 와이프 후 6개 탭
- 다국어 텍스트 — 대사 i18n 키 규칙
- 구현 상태 — 어긋남과 미구현 항목