Skip to content

About

A web-based tilemap editor for a custom 2D game engine.

Topics

Resources

Stars

12 stars

Watchers

1 watching

Forks

Latest commit

ย 

History

643 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

LOGO

typescript react tauri

InitialEditor

Initial2D ์—”์ง„์œผ๋กœ ๊ฒŒ์ž„์„ ๋งŒ๋“œ๋Š” ์—๋””ํ„ฐ์ž…๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ(ํด๋”)๋ฅผ ์—ด๊ณ , ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์“ฐ๊ณ , ์”ฌ์— ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋†“๊ณ , ์‹คํ–‰ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์—”์ง„์—์„œ ๊ทธ ๊ฒŒ์ž„์ด ๋•๋‹ˆ๋‹ค. ์—๋””ํ„ฐ ์ฝ”์–ด๋Š” ์žฅ๋ฅด๋ฅผ ๋ชจ๋ฅด๊ณ , ํƒ€์ผ๋งต๊ณผ RPG ์ด๋ฒคํŠธ๋Š” ํ™•์žฅ์ด ๋”ํ•ฉ๋‹ˆ๋‹ค. ๊ณ„ํš๊ณผ ์ง„ํ–‰ ์ƒํ™ฉ์€ docs/plans/index.md์— ์žˆ์Šต๋‹ˆ๋‹ค (E0 ๋ถ€ํ„ฐ E6 ๊นŒ์ง€ ๋งˆ์ณค๊ณ  ํ”„๋ฆฌ๋ฆด๋ฆฌ์Šค๋Š” Releases ์— ์žˆ์Šต๋‹ˆ๋‹ค).

์—๋””ํ„ฐ๋ฅผ ์“ฐ๋Š” ๋ฒ•์€ ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ์— ์žˆ์Šต๋‹ˆ๋‹ค. ์•ฑ์—์„œ๋Š” ๋„์›€๋ง > ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ(F1)๋กœ ์—ฝ๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ์—๋””ํ„ฐ๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ๊ณ ์น˜๋Š” ์‚ฌ๋žŒ์„ ์œ„ํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

๋‘ ๊ฐ€์ง€ ๋ชจ๋“œ๋กœ ๋•๋‹ˆ๋‹ค.

๋ชจ๋“œ ๋ฌด์—‡ ๋กœ์ปฌ ํŒŒ์ผ ์—”์ง„ ์‹คํ–‰
Tauri ์•ฑ (์ œํ’ˆ) macOS, Windows, Linux ๋ฐ์Šคํฌํ†ฑ ์•ฑ ์ง์ ‘ (ํด๋” ์„ ํƒ, ๊ฐ์‹œ, ์›์ž์  ์ €์žฅ) ์—”์ง„ ์‹คํ–‰ ํŒŒ์ผ์„ ๋„์šด๋‹ค (E1). ์„ค์ •์—์„œ ์—๋””ํ„ฐ ์•ˆ(E4)์œผ๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค
๋ธŒ๋ผ์šฐ์ € (๊ฐœ๋ฐœ) Vite dev ์„œ๋ฒ„ + ์—”์ง„ ์ €์žฅ์†Œ์˜ ๋ธŒ๋ฆฌ์ง€ ์„œ๋ฒ„ ๋ธŒ๋ฆฌ์ง€ ์„œ๋ฒ„(127.0.0.1:5960)๋ฅผ ๊ฑฐ์ณ์„œ ์—๋””ํ„ฐ ์•ˆ ๊ฒŒ์ž„ ํƒญ (์›น ์—”์ง„, E4)

๋ธŒ๋ผ์šฐ์ € ๋ชจ๋“œ์—๋Š” ์„œ๋ฒ„ ์—†์ด ๋„๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋“œ(?backend=memory)๋„ ์žˆ์–ด, UI ์ž‘์—…๊ณผ ์Šค๋ชจํฌ ํ…Œ์ŠคํŠธ์— ์”๋‹ˆ๋‹ค.

์‹œ์ž‘ํ•˜๊ธฐ

Node 22 ์ด์ƒ(๋ธŒ๋ผ์šฐ์ € ๋ชจ๋“œ ํ…Œ์ŠคํŠธ๊ฐ€ ์ „์—ญ WebSocket์„ ์“ด๋‹ค), Yarn(์ €์žฅ์†Œ์— ๋“  Berry 4.3.1, .yarn/releases/. ์ „์—ญ yarn ์ด 1.x ์—ฌ๋„ ์ด๊ฒƒ์œผ๋กœ ๋„˜๊น๋‹ˆ๋‹ค), Tauri ์•ฑ์„ ๋นŒ๋“œํ•˜๋ ค๋ฉด Rust ์•ˆ์ •ํŒ๊ณผ ํ”Œ๋žซํผ๋ณ„ ์ค€๋น„๋ฌผ(docs/plans/01-tech-stack.md 7์ ˆ)์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

yarn install

# ๋ธŒ๋ผ์šฐ์ € ๋ชจ๋“œ (์—”์ง„ ์ €์žฅ์†Œ๊ฐ€ ์˜† ํด๋”์— ์žˆ๋‹ค๊ณ  ๊ฐ€์ •)
INITIAL2D_HMR=1 ../Initial2D/build/Initial2D &              # 1. ๊ฒŒ์ž„์„ ํ•ซ ๋ฆฌ๋กœ๋“œ ์ผœ๊ณ  ์‹คํ–‰ (์„ ํƒ)
node ../Initial2D/tools/bridge/server.js --project ../Initial2D  # 2. ๋ธŒ๋ฆฌ์ง€ ์„œ๋ฒ„ (127.0.0.1:5960)
yarn dev                                                     # 3. http://127.0.0.1:5173

# ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋“œ (์„œ๋ฒ„ ์—†์Œ)
VITE_DEFAULT_BACKEND=memory yarn dev      # ๋˜๋Š” http://127.0.0.1:5173/?backend=memory

# Tauri ์•ฑ
yarn tauri dev                            # ๊ฐœ๋ฐœ (Vite dev ์„œ๋ฒ„๋ฅผ ํ•จ๊ป˜ ๋„์šด๋‹ค)
yarn tauri build                          # ๋ฒˆ๋“ค (src-tauri/target/release/bundle/)
INITIAL_EDITOR_OPEN=~/mygame yarn tauri dev   # ์‹œ์ž‘ํ•˜์ž๋งˆ์ž ๊ทธ ํด๋”๋ฅผ ์—ฐ๋‹ค (--open <ํด๋”> ์ธ์ž๋„ ๊ฐ™๋‹ค)

๋ธŒ๋ฆฌ์ง€ ์„œ๋ฒ„๋Š” ์—”์ง„ ์ €์žฅ์†Œ์˜ tools/bridge/server.js(0.2.0 ์ด์ƒ)์ด๋ฉฐ ํ”„๋กœ์ ํŠธ์˜ scripts/, resources/, .initial-editor/์™€ ๋ฃจํŠธ์˜ game.json๋งŒ ์ฝ๊ณ  ์”๋‹ˆ๋‹ค. ์‚ฌ์šฉ๋ฒ•์€ ์—”์ง„ README์˜ "์—๋””ํ„ฐ ๋ธŒ๋ฆฌ์ง€ ์„œ๋ฒ„" ์ ˆ์— ์žˆ์Šต๋‹ˆ๋‹ค.

์Šคํฌ๋ฆฝํŠธ ์“ฐ๊ธฐ์™€ ์‹คํ–‰ (E1)

  • ํ”„๋กœ์ ํŠธ ํŒจ๋„์—์„œ .lua, .rb, .json ์„ ์—ด๋ฉด Monaco ํŽธ์ง‘๊ธฐ๊ฐ€ ๋œน๋‹ˆ๋‹ค. Ctrl+S ๋กœ ์ €์žฅํ•˜๋ฉด (์„ค์ •์ด ์ผœ์ ธ ์žˆ์œผ๋ฉด) ์‹คํ–‰ ์ค‘์ธ ๊ฒŒ์ž„์— ํ•ซ ๋ฆฌ๋กœ๋“œ๊ฐ€ ๊ฐ‘๋‹ˆ๋‹ค. ๋ฐ–์—์„œ ํŒŒ์ผ์ด ๋ฐ”๋€Œ๋ฉด ์ˆ˜์ • ์ค‘์ด ์•„๋‹ ๋•Œ๋Š” ์กฐ์šฉํžˆ ๋‹ค์‹œ ์ฝ๊ณ , ์ˆ˜์ • ์ค‘์ด๋ฉด ๋ฐฐ๋„ˆ๋กœ ๋ฌป์Šต๋‹ˆ๋‹ค. ์ €์žฅํ•  ๋•Œ ๋””์Šคํฌ์˜ ํŒŒ์ผ์ด ์—ฐ ๋•Œ์™€ ๋‹ค๋ฅด๋ฉด(๋ฐฐ๋„ˆ์—์„œ ํŽธ์ง‘ ๋‚ด์šฉ ์œ ์ง€๋ฅผ ๊ณจ๋ž์–ด๋„, ํŒŒ์ผ์ด ์ง€์›Œ์กŒ์–ด๋„) ๋ฎ์–ด์“ฐ๊ธฐ, ๋‹ค์‹œ ์ฝ๊ธฐ, ์ทจ์†Œ๋ฅผ ๋ชจ๋‹ฌ๋กœ ํ•œ ๋ฒˆ ๋” ๋ฌป์Šต๋‹ˆ๋‹ค. ์”ฌ, ๋งต, ๋ชจ๋‘ ์ €์žฅ๋„ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ฝ๊ธฐ๋Š” ์ €์žฅํ•˜์ง€ ์•Š์€ ์ˆ˜์ •์„ ๋ฒ„๋ฆฌ๋ฏ€๋กœ ํ•œ ๋ฒˆ ๋” ํ™•์ธํ•˜๊ณ , ๋””์Šคํฌ์˜ ํŒŒ์ผ์ด ๊นจ์ ธ ๋‹ค์‹œ ์ฝ์ง€ ๋ชปํ•˜๋ฉด "๋‹ค์‹œ ์ฝ์ง€ ๋ชปํ–ˆ๋‹ค"๊ณ  ์•Œ๋ฆฐ ๋’ค ๋‚ด ์ˆ˜์ •๊ณผ ๋ฐฐ๋„ˆ๋ฅผ ๊ทธ๋Œ€๋กœ ๋‘ก๋‹ˆ๋‹ค. ํฐ ๋งต์„ ์“ฐ๋Š” ์ค‘์— ๊ณ ์น˜๊ณ  ๋‹ค์‹œ ์ €์žฅํ•˜๋ฉด ์•ž์˜ ์“ฐ๊ธฐ๊ฐ€ ๋๋‚œ ๋’ค ์ตœ์‹  ๋‚ด์šฉ์œผ๋กœ ํ•œ ๋ฒˆ ๋” ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  • ์ž๋™์™„์„ฑ์€ ํ”„๋กœ์ ํŠธ์˜ resources/api/initial2d-api.json(์—”์ง„ ์ €์žฅ์†Œ๊ฐ€ ๋งŒ๋“ค์–ด ๋‘” API ๋ช…์„ธ)์„ ์ฝ์Šต๋‹ˆ๋‹ค. ์—†์œผ๋ฉด ๋‚ด์žฅ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋™์ž‘ํ•˜๋ฉฐ ์ฝ˜์†”์— ๊ทธ๋ ‡๊ฒŒ ์ ํž™๋‹ˆ๋‹ค. Input. ๋’ค์— ๋ฉค๋ฒ„, ( ๋’ค์— ์‹œ๊ทธ๋‹ˆ์ฒ˜, ๋นˆ ํŒŒ์ผ์—์„œ ์”ฌ ๊ณ„์•ฝ ๋„ค ํ•จ์ˆ˜ ์Šค๋‹ˆํŽซ.
  • ๋ฐ์Šคํฌํ†ฑ ์•ฑ์€ Lua ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์—ด๋ฉด ์•ฑ์— ๋“  ์–ธ์–ด ์„œ๋ฒ„ LuaLS ๋ฅผ ๋„์›๋‹ˆ๋‹ค. ์ง€์—ญ ๋ณ€์ˆ˜, require ํ•œ ๋ชจ๋“ˆ, ์ง์ ‘ ๋งŒ๋“  ํ•จ์ˆ˜๊นŒ์ง€ ์•„๋Š” ์ž๋™ ์™„์„ฑ๊ณผ ํ˜ธ๋ฒ„, ์ง„๋‹จ(๋ฌผ๊ฒฐ ๋ฐ‘์ค„), ์ •์˜๋กœ ์ด๋™(F12, Ctrl+ํด๋ฆญ), ์ฐธ์กฐ(Shift+F12), ์ด๋ฆ„ ๋ฐ”๊พธ๊ธฐ(F2, ์—ฌ๋Ÿฌ ํŒŒ์ผ์ด๋ฉด ๊ทธ ํŒŒ์ผ๋“ค์„ ์—ด์–ด ์ €์žฅํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค), ๊ธฐํ˜ธ๋กœ ์ด๋™(Ctrl+Shift+O)์ด ๋ฉ๋‹ˆ๋‹ค. ์ƒํƒœ ๋ฐ”์— LuaLS 3.19.1 ์ฒ˜๋Ÿผ ๋ณด์ด๊ณ , ๋ฉˆ์ถ”๋ฉด ๋„๊ตฌ > ์–ธ์–ด ์„œ๋ฒ„ ๋‹ค์‹œ ์‹œ์ž‘. ์„œ๋ฒ„๊ฐ€ ๋„๋Š” ๋™์•ˆ ๋ช…์„ธ ์ž๋™์™„์„ฑ์€ ์”ฌ ๊ณ„์•ฝ ์Šค๋‹ˆํŽซ๋งŒ ๋‚จ์Šต๋‹ˆ๋‹ค.
  • Ruby ์Šคํฌ๋ฆฝํŠธ์™€ ๋ธŒ๋ผ์šฐ์ €ํŒ์˜ Lua ๋Š” ์›Œ์ปค ์•ˆ์˜ ๊ตฌ๋ฌธ ๋ถ„์„๊ธฐ(Ruby ๋Š” Prism, Lua ๋Š” luaparse)๊ฐ€ ๋ถ™์Šต๋‹ˆ๋‹ค. ๊ตฌ๋ฌธ ์˜ค๋ฅ˜๋ฅผ ์“ฐ๋Š” ๋™์•ˆ ๋ฐ‘์ค„๋กœ ๋ณด์ด๊ณ , ์ •์˜๋กœ ์ด๋™(F12)๊ณผ ๊ธฐํ˜ธ๋กœ ์ด๋™(Ctrl+Shift+O)์ด ํ”„๋กœ์ ํŠธ์˜ scripts/ ์•ˆ์—์„œ ๋˜๊ณ , ์ž๋™์™„์„ฑ์— ์ง€๊ธˆ ํŒŒ์ผ์˜ ํ•จ์ˆ˜ ์ด๋ฆ„๊ณผ ํ”„๋กœ์ ํŠธ์˜ ํด๋ž˜์Šค, ๋ชจ๋“ˆ, ์ƒ์ˆ˜ ์ด๋ฆ„์ด ๋”ํ•ด์ง‘๋‹ˆ๋‹ค. ์—”์ง„ API ์˜ ์ž๋™์™„์„ฑ์€ ์ง€๊ธˆ์ฒ˜๋Ÿผ ๋ช…์„ธ์—์„œ ์˜ต๋‹ˆ๋‹ค.
  • ์ง„๋‹จ ๊ทœ์น™์€ ํ”„๋กœ์ ํŠธ์˜ .luarc.json ์ž…๋‹ˆ๋‹ค. ์ƒˆ Lua ํ”„๋กœ์ ํŠธ๋Š” ์—”์ง„ ํ…œํ”Œ๋ฆฟ์˜ ๊ฒƒ(ํ˜•์‹ ๊ฒ€์‚ฌ, ์ง€์—ญ ๋ณ€์ˆ˜ ๋‹ค์‹œ ์„ ์–ธ, ์ค„ ๋ ๊ณต๋ฐฑ์„ ๋ˆ LuaLS ๊ธฐ๋ณธ)๊ณผ ์—”์ง„ API ์Šคํ… resources/api/initial2d.lua ๋ฅผ ๋ฐ›๊ณ , VS Code ๊ฐ™์€ ๋‹ค๋ฅธ ์—๋””ํ„ฐ์˜ LuaLS ๋„ ๊ฐ™์€ ํŒŒ์ผ์„ ์ฝ์Šต๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค ์—†๋Š” ์˜› ํ”„๋กœ์ ํŠธ๋Š” ๊ฐ™์€ ๊ทœ์น™๊ณผ ์•ฑ์— ๋“  ์Šคํ…์„ ์”๋‹ˆ๋‹ค. ๋„๊ตฌ > ์„ค์ •์˜ "์ง„๋‹จ ํ‘œ์‹œ"์—์„œ ํ‘œ์‹œ ์•ˆ ํ•จ, ๊ตฌ๋ฌธ ์˜ค๋ฅ˜๋งŒ, ๊ทœ์น™ ์ „์ฒด๋ฅผ ๊ณ ๋ฅด๊ณ , "์–ธ์–ด ์„œ๋ฒ„"๋ฅผ ๋„๋ฉด ๋ช…์„ธ ์ž๋™์™„์„ฑ๋งŒ ์”๋‹ˆ๋‹ค. ๊ณ„ํš๊ณผ ๊ตฌ์กฐ๋Š” docs/plans/language-server.md.
  • ์ฐพ๊ธฐ: ํŽธ์ง‘๊ธฐ ์•ˆ Ctrl+F, ํ”„๋กœ์ ํŠธ ์ „์ฒด Ctrl+Shift+F (๋Œ€์†Œ๋ฌธ์ž, ์ •๊ทœ์‹). ์ƒˆ ์Šคํฌ๋ฆฝํŠธ Ctrl+Alt+N (์”ฌ ํ…œํ”Œ๋ฆฟ ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ ํ…œํ”Œ๋ฆฟ, Lua ๋‚˜ Ruby).
  • ์—”์ง„ ํ”„๋กœ์„ธ์Šค ์‹คํ–‰(F5, ์„ค์ •์˜ ์‹คํ–‰ ๋ฐฉ์‹์ด ํ”„๋กœ์„ธ์Šค์ผ ๋•Œ)์€ Tauri ์•ฑ์—์„œ๋งŒ ๋ฉ๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” F5 ๊ฐ€ ์—๋””ํ„ฐ ์•ˆ ๊ฒŒ์ž„ ํƒญ์—์„œ ๋•๋‹ˆ๋‹ค (์•„๋ž˜ "์—๋””ํ„ฐ ์•ˆ์—์„œ ์‹คํ–‰"). ์—”์ง„์€ ์„ค์ •์˜ ๊ฒฝ๋กœ, ํ”„๋กœ์ ํŠธ์˜ .initial-editor/engine(ํ•œ ์ค„ ๊ฒฝ๋กœ), ํ”„๋กœ์ ํŠธ ์•ˆ build/Initial2D, ์•ฑ์— ๋“  ์—”์ง„(์„ค์น˜๋ณธ), ํ˜•์ œ ํด๋” ../Initial2D/build/Initial2D ์ˆœ์„œ๋กœ ์ฐพ๊ณ  --features ๋กœ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์‹คํ–‰ ํŒŒ์ผ(.initial-editor/engine, build/, ํ˜•์ œ ํด๋”)์€ ์ฒ˜์Œ ํ•œ ๋ฒˆ ๊ฒฝ๋กœ๋ฅผ ๋ณด์—ฌ ์ฃผ๊ณ  ์‹คํ–‰ํ•ด๋„ ๋˜๋Š”์ง€ ๋ฌป์Šต๋‹ˆ๋‹ค. ๋‹ต์€ ํ”„๋กœ์ ํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ ์•ฑ ์„ค์ •์— ๋‚จ๊ณ , ๋„๊ตฌ > ์„ค์ •์˜ "์ฐพ์€ ์—”์ง„" ์ค„์—์„œ ์‹ ๋ขฐ ์ทจ์†Œ๋‚˜ ๋‹ค์‹œ ๋ฌป๊ธฐ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค. ์—”์ง„์„ ๋ชป ์ฐพ์œผ๋ฉด F5 ๋Š” ์—๋””ํ„ฐ ์•ˆ ๊ฒŒ์ž„ ํƒญ์œผ๋กœ ๋„˜์–ด๊ฐ‘๋‹ˆ๋‹ค (Ruby ํ”„๋กœ์ ํŠธ๋Š” ์ด์œ ๋ฅผ ๋„์›๋‹ˆ๋‹ค). ์ •์ง€ Shift+F5, ๋ฆฌ๋กœ๋“œ Ctrl+Shift+R. ์—”์ง„ ์ถœ๋ ฅ์€ ์ฝ˜์†”์— ์˜ค๊ณ  ํŒŒ์ผ:์ค„: ์€ ๋งํฌ๋ผ ๋ˆ„๋ฅด๋ฉด ๊ทธ ์ค„๋กœ ๊ฐ‘๋‹ˆ๋‹ค. ์ €์žฅํ•˜์ง€ ์•Š์€ ๋ฌธ์„œ๊ฐ€ ์žˆ์œผ๋ฉด F5 ์™€ Ctrl+F5, ๋‹ค์‹œ ์‹œ์ž‘์ด ๋จผ์ € ๋ฌป์Šต๋‹ˆ๋‹ค. ๊ฒŒ์ž„์€ ๋””์Šคํฌ์˜ ํŒŒ์ผ์„ ์ฝ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. Enter ๋Š” "๋ชจ๋‘ ์ €์žฅํ•˜๊ณ  ์‹คํ–‰"์ด๊ณ , "์ €์žฅํ•˜์ง€ ์•Š๊ณ  ์‹คํ–‰"๊ณผ "์ทจ์†Œ"๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฐฐํฌ๋œ ํŽ˜์ด์ง€(Cloudflare Pages ๋“ฑ, ๋กœ์ปฌ์ด ์•„๋‹Œ ํ˜ธ์ŠคํŠธ)์—์„œ๋Š” ๋ธŒ๋ฆฌ์ง€์— ๋‹ฟ์„ ์ˆ˜ ์—†์–ด ์›นํŒ(๋ธŒ๋ผ์šฐ์ € ํด๋”)์œผ๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ํด๋” ์—ด๊ธฐ๊ฐ€ ์—†๋Š” ๋ธŒ๋ผ์šฐ์ €๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋“œ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜ "์›นํŒ" ์ ˆ.

์›นํŒ (๋ธŒ๋ผ์šฐ์ €์—์„œ ํด๋” ์—ด๊ธฐ)

๊ฐ™์€ ์•ฑ์„ Cloudflare Pages ์— ์˜ฌ๋ฆฐ ๊ฒƒ์ด ์›นํŒ์ž…๋‹ˆ๋‹ค. ์„ค์น˜ ์—†์ด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋‚ด ์ปดํ“จํ„ฐ์˜ ํ”„๋กœ์ ํŠธ ํด๋”๋ฅผ ์ง์ ‘ ์ฝ๊ณ  ์”๋‹ˆ๋‹ค (File System Access API, ์„œ๋ฒ„ ์—†์Œ). ๊ฒŒ์ž„์€ ๊ฒŒ์ž„ ๋ทฐ์—์„œ ์—”์ง„์˜ WASM ๋นŒ๋“œ๋กœ ํŽ˜์ด์ง€ ์•ˆ์—์„œ ๋•๋‹ˆ๋‹ค.

  • ๋ธŒ๋ผ์šฐ์ €: ํฌ๋กฌ, ์—ฃ์ง€ ๊ฐ™์€ ํฌ๋กœ๋ฏธ์›€ ๊ณ„์—ด ๋ฐ์Šคํฌํ†ฑ ๋ธŒ๋ผ์šฐ์ €. ํŒŒ์ด์–ดํญ์Šค์™€ ์‚ฌํŒŒ๋ฆฌ์—๋Š” ํด๋” ์—ด๊ธฐ๊ฐ€ ์—†์–ด์„œ ์ƒ˜ํ”Œ ํ”„๋กœ์ ํŠธ(๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋“œ)๋กœ ์‹œ์ž‘ํ•˜๊ณ  ์‹œ์ž‘ ํ™”๋ฉด์— ๊ทธ๋ ‡๊ฒŒ ์ ํž™๋‹ˆ๋‹ค.
  • ํด๋” ์—ด๊ธฐ: ์‹œ์ž‘ ํ™”๋ฉด์˜ "ํด๋” ์—ด๊ธฐ"(๋˜๋Š” Ctrl+O, ํŒŒ์ผ > ํ”„๋กœ์ ํŠธ ์—ด๊ธฐ. "์ƒ˜ํ”Œ ํ”„๋กœ์ ํŠธ ์—ด๊ธฐ" ๋’ค์—๋„ ๊ฐ™์Šต๋‹ˆ๋‹ค)๋กœ game.json ์ด ์žˆ๋Š” ํด๋”๋ฅผ ๊ณ ๋ฅด๊ณ , ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ฌป๋Š” ์ˆ˜์ • ๊ถŒํ•œ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์—ฐ ํด๋”๋Š” ๋ธŒ๋ผ์šฐ์ €(IndexedDB)๊ฐ€ ํด๋” ์ด๋ฆ„์œผ๋กœ ๊ธฐ์–ตํ•ด "์ตœ๊ทผ ํด๋”"์™€ ํŒŒ์ผ > ์ตœ๊ทผ ํ”„๋กœ์ ํŠธ์— ๋‚˜์˜ต๋‹ˆ๋‹ค. ๊ฐ™์€ ์ด๋ฆ„์˜ ํด๋”๋ฅผ ๋‹ค์‹œ ๊ณ ๋ฅด๋ฉด ๋ชฉ๋ก์ด ๋Š˜์ง€ ์•Š๊ณ  ๊ทธ ์ž๋ฆฌ๋ฅผ ์ƒˆ๋กœ ๊ณ ๋ฅธ ํด๋”๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๊ถŒํ•œ์„ ๊ธฐ์–ตํ•˜์ง€ ์•Š์•˜์œผ๋ฉด "๋‹ค์‹œ ์—ด๊ธฐ"๋ฅผ ๋ˆ„๋ฅผ ๋•Œ ํ•œ ๋ฒˆ ๋” ๋ฌป์Šต๋‹ˆ๋‹ค.
  • ์—ด๋ฆฐ ํ”„๋กœ์ ํŠธ์— ์ €์žฅํ•˜์ง€ ์•Š์€ ๋ฌธ์„œ๊ฐ€ ์žˆ์œผ๋ฉด ํด๋”๋ฅผ ๊ณ ๋ฅธ ๋’ค ๋‹ซ์„์ง€ ๋จผ์ € ๋ฌป์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ทจ์†Œํ•˜๋ฉด ๊ธฐ์–ตํ•œ ํด๋” ๋ชฉ๋ก๋„ ์ง€๊ธˆ ์—ด๋ฆฐ ํ”„๋กœ์ ํŠธ๋„ ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค.
  • ๋˜๋Š” ๊ฒƒ: ํŒŒ์ผ ํŠธ๋ฆฌ, ์Šคํฌ๋ฆฝํŠธ์™€ ์”ฌ๊ณผ ๋งต ํŽธ์ง‘, ์ €์žฅ(์ž„์‹œ ํŒŒ์ผ์— ์“ฐ๊ณ  ํ•œ ๋ฒˆ์— ๋ฐ”๊พผ๋‹ค), ์ด๋ฆ„ ๋ฐ”๊พธ๊ธฐ์™€ ์ง€์šฐ๊ธฐ, ๋ฐ–์—์„œ ๋ฐ”๋€ ํŒŒ์ผ ๊ฐ์ง€(1.5์ดˆ ๊ฐ„๊ฒฉ์œผ๋กœ ํ™•์ธ), ์ƒˆ ํ”„๋กœ์ ํŠธ. ์•ˆ ๋˜๋Š” ๊ฒƒ: ์—”์ง„ ์‹คํ–‰ ํŒŒ์ผ ๋„์šฐ๊ธฐ์™€ ์•ˆ๋“œ๋กœ์ด๋“œ ์Šคํ…Œ์ด์ง•(๋ฐ์Šคํฌํ†ฑ ์•ฑ์˜ ์ผ). ์›น ์—”์ง„ ๋นŒ๋“œ์— mruby ๊ฐ€ ์—†์œผ๋ฉด Ruby ๊ฒŒ์ž„๋„ ๋Œ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‹œ์ž‘ ํ™”๋ฉด ์•„๋ž˜์— ์ด ์ค„๊ณผ "๋ฐ์Šคํฌํ†ฑ ์•ฑ ๋ฐ›๊ธฐ"(๋ฆด๋ฆฌ์Šค ํŽ˜์ด์ง€)๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ƒˆ ํ”„๋กœ์ ํŠธ: ์‹œ์ž‘ ํ™”๋ฉด์˜ "์ƒˆ ํ”„๋กœ์ ํŠธ"(๋˜๋Š” Ctrl+N, ํŒŒ์ผ > ์ƒˆ ํ”„๋กœ์ ํŠธ. "์ƒ˜ํ”Œ ํ”„๋กœ์ ํŠธ ์—ด๊ธฐ" ๋’ค์—๋„ ๊ฐ™์Šต๋‹ˆ๋‹ค)๋กœ ๋นˆ ํด๋”๋ฅผ ๊ณ ๋ฅด๊ณ  ํ…œํ”Œ๋ฆฟ๊ณผ ์–ธ์–ด๋ฅผ ์ •ํ•˜๋ฉด ๊ทธ ํด๋”์— ํ…œํ”Œ๋ฆฟ์„ ์“ฐ๊ณ  ์—ฝ๋‹ˆ๋‹ค. ํด๋”๋ฅผ ๊ธฐ์–ตํ•˜๋Š” ๊ฒƒ์€ ๋Œ€ํ™”์ƒ์ž์—์„œ "๋งŒ๋“ค๊ธฐ"๋ฅผ ๋ˆ„๋ฅธ ๋’ค๋ผ, ์ค‘๊ฐ„์— ์ทจ์†Œํ•˜๋ฉด ์ตœ๊ทผ ํด๋”๋„ ํด๋” ์•ˆ๋„ ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค. ๋น„์–ด ์žˆ์ง€ ์•Š์€ ํด๋”๋Š” ํ•œ ๋ฒˆ ๋ฌป๊ณ , ์žˆ๋Š” ํŒŒ์ผ์€ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ์—†๋Š” ๊ฒƒ๋งŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
  • ์ƒ˜ํ”Œ ํ”„๋กœ์ ํŠธ ์—ด๊ธฐ: ์—”์ง„์˜ RPG ๋ฐ๋ชจ ใ€Œ๋– ๋‚˜๊ธฐ ์ „์—ใ€๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ํ’€์–ด ์—ด๊ณ  ํ•ญ๊ตฌ ๋งˆ์„ ๋งต(resources/maps/port_town.json)์„ ๋งต ๋ทฐ๋กœ ๋„์›๋‹ˆ๋‹ค. ์ƒˆ ํ”„๋กœ์ ํŠธ์˜ "RPG ๋ฐ๋ชจ" ํ…œํ”Œ๋ฆฟ๊ณผ ๊ฐ™์€ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค. ํƒ€์ผ์„ ์น ํ•˜๊ฑฐ๋‚˜ ์ด๋ฒคํŠธ ๋ ˆ์ด์–ด์—์„œ ๋Œ€์‚ฌ๋ฅผ ๊ณ ์น˜๊ณ  ์ €์žฅํ•œ ๋’ค F5 ๋ฅผ ๋ˆ„๋ฅด๋ฉด ํƒ€์ดํ‹€๋ถ€ํ„ฐ, Ctrl+F5 ๋ฅผ ๋ˆ„๋ฅด๋ฉด ๊ทธ ๋งต์—์„œ ๋ฐ”๋กœ ๊ฒŒ์ž„ ํƒญ์œผ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ๋ผ ํŽ˜์ด์ง€๋ฅผ ๋‹ค์‹œ ์—ด๋ฉด ์ฒ˜์Œ ์ƒํƒœ๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. ์˜ˆ์ „์˜ ์ดˆ์› ์ƒ˜ํ”Œ์€ e2e ๊ฐ€ ์“ฐ๋ฉฐ ?sample=meadow ๋กœ ์—ฝ๋‹ˆ๋‹ค.
  • ์ •๋ณด ์ฐฝ(๋„์›€๋ง > InitialEditor ์ •๋ณด): ํŒ, ๋นŒ๋“œํ•œ ์ปค๋ฐ‹, ์›น ์—”์ง„์˜ ์ปค๋ฐ‹๊ณผ ๊ธฐ๋Šฅ, ๋ฐ์Šคํฌํ†ฑ ์•ฑ์ด๋ฉด ์ฐพ์€ ์—”์ง„(์•ฑ์— ๋“  ์—”์ง„์ด๋ฉด ๊ทธ ํŒ), ์ œ3์ž ๊ณ ์ง€(์›น ์—”์ง„๊ณผ ํ•จ๊ป˜ ์‹ค๋ฆฐ engine/THIRD-PARTY.md), ์›นํŒ์ด๋ฉด "๋ฐ์Šคํฌํ†ฑ ์•ฑ ๋ฐ›๊ธฐ", ๋ฐ์Šคํฌํ†ฑ ์•ฑ์ด๋ฉด "์›นํŒ ์—ด๊ธฐ". ๋ฐ”๊นฅ ๋งํฌ๋Š” ๋ฐ์Šคํฌํ†ฑ ์•ฑ์—์„œ๋Š” ๊ธฐ๋ณธ ๋ธŒ๋ผ์šฐ์ €๋กœ, ์›นํŒ์—์„œ๋Š” ์ƒˆ ํƒญ์œผ๋กœ ์—ด๋ฆฝ๋‹ˆ๋‹ค.
  • ๋ฐ–์—์„œ ๋ฐ”๋€ ํŒŒ์ผ์€ ํฌ๊ธฐ์™€ ์ˆ˜์ • ์‹œ๊ฐ๋งŒ ๋น„๊ตํ•ด์„œ ์ฐพ์Šต๋‹ˆ๋‹ค(๋‚ด์šฉ์€ ์ฝ์ง€ ์•Š๋Š” ํด๋ง). ํฌ๊ธฐ์™€ ์ˆ˜์ • ์‹œ๊ฐ์ด ๋‘˜ ๋‹ค ๊ทธ๋Œ€๋กœ์ธ ๋ณ€๊ฒฝ(์ˆ˜์ • ์‹œ๊ฐ์„ ๋ณด์กดํ•˜๋Š” ๋ณต์‚ฌ ๋“ฑ)์€ ๋†“์นฉ๋‹ˆ๋‹ค.
  • ์ด๋ฆ„ ๋ฐ”๊พธ๊ธฐ๋Š” ๋ธŒ๋ผ์šฐ์ €์˜ move() ๊ฐ€ ๋˜๋ฉด ๊ทธ๊ฒƒ์„, ์•ˆ ๋˜๊ฑฐ๋‚˜ ์‹คํŒจํ•˜๋ฉด ๋ณต์‚ฌ ๋’ค ์ง€์šฐ๊ธฐ๋ฅผ ์”๋‹ˆ๋‹ค. ํฌ๋กฌ 153 ์€ ํŒŒ์ผ์—๋งŒ move() ๊ฐ€ ์žˆ์–ด์„œ ํด๋” ์ด๋ฆ„ ๋ฐ”๊พธ๊ธฐ๋Š” ๋Š˜ ๋ณต์‚ฌ์ž…๋‹ˆ๋‹ค. move() ์ชฝ์˜ ์ž๋™ ํ…Œ์ŠคํŠธ๋Š” ๊ฐ€์งœ ํŒŒ์ผ ์‹œ์Šคํ…œ์œผ๋กœ๋งŒ ๋•๋‹ˆ๋‹ค.
  • ์‹œํฌ๋ฆฟ ์ฐฝ: ํฌ๋กœ๋ฏธ์›€์˜ ์‹œํฌ๋ฆฟ ์ฐฝ(off-the-record ํ”„๋กœํ•„)์—์„œ๋Š” IndexedDB ์— ๊ธฐ์–ตํ•œ ํด๋” ํ•ธ๋“ค์„ ๊บผ๋‚ด๋Š” ์ˆœ๊ฐ„ ํƒญ์ด ์•„๋‹ˆ๋ผ ๋ธŒ๋ผ์šฐ์ € ํ”„๋กœ์„ธ์Šค๊ฐ€ ํ†ต์งธ๋กœ ๊บผ์ง‘๋‹ˆ๋‹ค(ํฌ๋กฌ 153 ์—์„œ ํ™•์ธ, ์‹œํฌ๋ฆฟ ์ฐฝ์˜ ์ €์žฅ์†Œ๋„ ํ•จ๊ป˜ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค). ๊ทธ๋ž˜์„œ "๋‹ค์‹œ ์—ด๊ธฐ"๋Š” ์ผ๋ฐ˜ ์ฐฝ์ด๋ผ๊ณ  ํ™•์‹ ํ•  ๋•Œ๋งŒ ํ•ธ๋“ค์„ ๋ฐ”๋กœ ๊บผ๋ƒ…๋‹ˆ๋‹ค. ๊ธฐ์ค€์€ JS ํž™ ํ•œ๋„(performance.memory.jsHeapSizeLimit)๋ฅผ ์•Œ ์ˆ˜ ์žˆ๊ณ , ์ €์žฅ ํ• ๋‹น๋Ÿ‰์ด ๊ทธ ๋‘ ๋ฐฐ๋ณด๋‹ค ํฌ๊ณ  4 GiB ๋ณด๋‹ค๋„ ํฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜๋จธ์ง€๋Š” ๋ชจ๋‘ ํ•ธ๋“ค์„ ๊บผ๋‚ด์ง€ ์•Š๊ณ , ์ด์œ ๋ฅผ ํ•œ ์ค„ ์•Œ๋ฆฐ ๋’ค ํด๋” ๊ณ ๋ฅด๊ธฐ ๋Œ€ํ™”์ƒ์ž๋ฅผ ์—ฝ๋‹ˆ๋‹ค(ํฌ๋กฌ์€ ์ง€๋‚œ๋ฒˆ์— ๊ณ ๋ฅธ ํด๋”์—์„œ ์—ฝ๋‹ˆ๋‹ค). ๊ฐ™์€ ํด๋”๋ฅผ ๊ณ ๋ฅด๋ฉด ๋ฉ๋‹ˆ๋‹ค. ํฌ๋กฌ 153 ์˜ ์‹œํฌ๋ฆฟ ์ฐฝ๊ณผ ๊ฒŒ์ŠคํŠธ ์ฐฝ์€ ํ• ๋‹น๋Ÿ‰์ด ๋”ฑ 2 GiB(์“ด ๋’ค์—๋Š” 2 GiB ์— ์‚ฌ์šฉ๋Ÿ‰์„ ๋”ํ•œ ๊ฐ’)์ด๊ณ , ์ผ๋ฐ˜ ์ฐฝ์€ 10 GiB ์˜€์Šต๋‹ˆ๋‹ค. ํž™ ํ•œ๋„๋ฅผ ์•Œ๋ ค ์ฃผ์ง€ ์•Š๋Š” ๋ธŒ๋ผ์šฐ์ €๋Š” ์ผ๋ฐ˜ ์ฐฝ์ด์–ด๋„ ํด๋” ๊ณ ๋ฅด๊ธฐ๋กœ ๋•๋‹ˆ๋‹ค.
  • ์ผ๋ฐ˜ ์ฐฝ์—์„œ ํ•ธ๋“ค์„ ๊บผ๋‚ด๋‹ค ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๊บผ์ง„ ํ”์ ์ด ๋ช‡ ๋ถ„ ์•ˆ์— ๋‚จ์•„ ์žˆ์œผ๋ฉด ๊ทธ ํŽ˜์ด์ง€์—์„œ๋„ "๋‹ค์‹œ ์—ด๊ธฐ"๊ฐ€ ํด๋” ๊ณ ๋ฅด๊ธฐ๋กœ ๋•๋‹ˆ๋‹ค. ํด๋”๋ฅผ ํ•˜๋‚˜ ์—ด๋ฉด ํ”์ ์„ ์ง€์›๋‹ˆ๋‹ค.
  • ๋กœ์ปฌ์—์„œ ์›นํŒ์„ ๋„์šฐ๋ ค๋ฉด yarn dev ๋’ค http://127.0.0.1:5173/?backend=browser. ?backend=opfs ๋Š” ๋ธŒ๋ผ์šฐ์ € ์ „์šฉ ์ €์žฅ์†Œ(OPFS)๋ฅผ ํด๋” ๋Œ€์‹  ๋ฐ”๋กœ ์—ฌ๋Š” ํ…Œ์ŠคํŠธ์šฉ์ž…๋‹ˆ๋‹ค (tests/e2e/web-folder.spec.ts).

์›นํŒ ๋ฐฐํฌ (Cloudflare Pages)

Pages ๋Š” ์ €์žฅ์†Œ๋ฅผ ๋ฐ›์•„ yarn build ์˜ dist/ ๋ฅผ ๋ƒ…๋‹ˆ๋‹ค. ์„ค์ •์€ Pages ๋Œ€์‹œ๋ณด๋“œ์— ์žˆ๊ณ  ์ €์žฅ์†Œ์—๋Š” wrangler.toml ์„ ๋‘์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹œ๋ณด๋“œ ๊ฐ’์€ ์ด๋ ‡์Šต๋‹ˆ๋‹ค (๋ฐ”๊ฟ€ ๋•Œ๋Š” ์ด ํ‘œ๋„ ๊ณ ์นฉ๋‹ˆ๋‹ค).

์นธ ๊ฐ’
ํ”„๋กœ์ ํŠธ initial-editor
๋นŒ๋“œ ๋ช…๋ น yarn build
์ถœ๋ ฅ ํด๋” dist
๋ฃจํŠธ / (์ €์žฅ์†Œ ๋ฃจํŠธ)
Node .node-version (22)
Yarn .yarnrc.yml ์˜ yarnPath (Berry 4.3.1)
ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์—†์Œ. ์ •๋ณด ์ฐฝ์˜ ์ปค๋ฐ‹์€ Pages ๊ฐ€ ์ฃผ๋Š” CF_PAGES_COMMIT_SHA ๋ฅผ vite.config.ts ๊ฐ€ ์ฝ์Šต๋‹ˆ๋‹ค
ํ”„๋กœ๋•์…˜ main ๋ธŒ๋žœ์น˜, https://initial-editor.biud436.com (https://initial-editor.pages.dev)
๋ฏธ๋ฆฌ๋ณด๊ธฐ next ์™€ PR ๋ธŒ๋žœ์น˜. next ๋Š” https://next.initial-editor.pages.dev
  • Pages ๋นŒ๋“œ๋Š” ์—”์ง„์„ ๋งŒ๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. packages/app/public/engine/ ์— ์ปค๋ฐ‹ํ•œ ์›น ์—”์ง„๊ณผ ์ œ3์ž ๊ณ ์ง€๋ฅผ ๊ทธ๋Œ€๋กœ ์‹ฃ์Šต๋‹ˆ๋‹ค.
  • ์‘๋‹ต ํ—ค๋”๋Š” packages/app/public/_headers ์ž…๋‹ˆ๋‹ค: engine/ ์€ ์ด๋ฆ„์— ํ•ด์‹œ๊ฐ€ ์—†์–ด no-cache, Initial2D.wasm ์€ application/wasm(์•„๋‹ˆ๋ฉด ์ŠคํŠธ๋ฆฌ๋ฐ ์ปดํŒŒ์ผ์ด ์‹คํŒจํ•˜๊ณ  ์ฝ˜์†”์— ์˜ค๋ฅ˜ ์ค„์ด ๋œน๋‹ˆ๋‹ค), ํ•ด์‹œ ์ด๋ฆ„์˜ assets/ ๋Š” 1๋…„, ๋ชจ๋“  ์‘๋‹ต์— nosniff ์™€ referrer ์ •์ฑ…. ๊ต์ฐจ ์ถœ์ฒ˜ ๊ฒฉ๋ฆฌ ํ—ค๋”(COOP, COEP)์™€ CSP ๋Š” ๋‘์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ๋นŒ๋“œํ•œ dist/ ๊ฒ€์‚ฌ: node scripts/check-web-dist.mjs ๊ฐ€ index.html ๊ณผ ๊ทธ๊ฒƒ์ด ๋ถ€๋ฅด๋Š” assets/, _headers ๊ทœ์น™(wasm ํƒ€์ž…, ์—”์ง„ ์บ์‹œ, nosniff, ๊ฒฉ๋ฆฌ ํ—ค๋” ์—†์Œ), ์›น ์—”์ง„ ํŒŒ์ผ๊ณผ MANIFEST ์˜ sha256, engine/THIRD-PARTY.md, Pages ํ•œ๋„(ํŒŒ์ผ ํ•˜๋‚˜ 25 MiB, 2๋งŒ ๊ฐœ)๋ฅผ ๋ด…๋‹ˆ๋‹ค. ๋ฐ์Šคํฌํ†ฑ ๋ฒˆ๋“ค์šฉ ๋นŒ๋“œ๋Š” --desktop ์„ ๋ถ™์—ฌ ์†Œ์Šค๋งต์ด ์—†๋Š”์ง€๋„ ๋ด…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ํด๋”๋Š” --dist <ํด๋”>.
  • ํ—ค๋”๊นŒ์ง€ ๋กœ์ปฌ์—์„œ ๋ณด๋ ค๋ฉด wrangler pages dev ๋กœ Pages ๋ฅผ ํ‰๋‚ด ๋ƒ…๋‹ˆ๋‹ค (_headers ๋ฅผ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค).
yarn build && node scripts/check-web-dist.mjs
npx wrangler@3 pages dev dist --port 8788                                  # http://127.0.0.1:8788/?backend=browser
PAGES_URL=http://127.0.0.1:8788 yarn test:e2e tests/e2e/pages.spec.ts       # ๋„์›Œ ๋‘” Pages ๋กœ
PAGES_WRANGLER=1 yarn test:e2e tests/e2e/pages.spec.ts                      # ์ŠคํŽ™์ด wrangler ๋ฅผ ๋„์šฐ๊ณ  ๋ˆ๋‹ค (ํฌํŠธ PAGES_PORT, ๊ธฐ๋ณธ 8788)
  • tests/e2e/pages.spec.ts ๋Š” ํ—ค๋”(wasm ํƒ€์ž…, ์บ์‹œ, nosniff, ๊ฒฉ๋ฆฌ ํ—ค๋” ์—†์Œ, ๊ณ ์ง€ ํŒŒ์ผ)์™€ ํ๋ฆ„(์ƒ˜ํ”Œ ํ”„๋กœ์ ํŠธ ์—ด๊ธฐ, F5, ๋งต์—์„œ ํ•œ ์นธ ์น ํ•ด ์ €์žฅ, F5 ๋กœ ๊ทธ ์นธ๋งŒ ๋ฐ”๋€Œ๋Š”์ง€, ์ŠคํŠธ๋ฆฌ๋ฐ ์ปดํŒŒ์ผ ์‹คํŒจ ์ค„์ด ์—†๋Š”์ง€, ์ •๋ณด ์ฐฝ)์„ ๋ด…๋‹ˆ๋‹ค. PAGES_URL ๋„ PAGES_WRANGLER ๋„ ์—†์œผ๋ฉด ํ—ค๋” ๊ฒ€์‚ฌ๋Š” ๊นŒ๋‹ญ์„ ์ ๊ณ  ๊ฑด๋„ˆ๋›ฐ๊ณ , ํ๋ฆ„์€ Playwright ๊ฐ€ ๋„์šด vite preview ๋กœ ๋•๋‹ˆ๋‹ค. wrangler ๋ฅผ ๋ฐ›์ง€ ๋ชปํ•˜๋ฉด ๊ทธ ๊นŒ๋‹ญ๋„ ์ ๊ณ  ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค.

์—๋””ํ„ฐ ์•ˆ์—์„œ ์‹คํ–‰ (E4)

์—”์ง„์˜ WebAssembly ๋นŒ๋“œ๋ฅผ ๊ฒŒ์ž„ ํƒญ์˜ canvas ์— ์˜ฌ๋ ค ๊ฒŒ์ž„์„ ์—๋””ํ„ฐ ์•ˆ์—์„œ ๋Œ๋ฆฝ๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ € ๋ชจ๋“œ(๋ธŒ๋ฆฌ์ง€, ๋ฉ”๋ชจ๋ฆฌ, ์›นํŒ)์˜ F5 ๋Š” ๋Š˜ ์ด์ชฝ์ด๊ณ , Tauri ์•ฑ์€ ์„ค์ •์˜ ์‹คํ–‰ ๋ฐฉ์‹(ํ”„๋กœ์„ธ์Šค, ์—๋””ํ„ฐ ์•ˆ)์œผ๋กœ ๊ณ ๋ฆ…๋‹ˆ๋‹ค. ์ƒํƒœ ๋ฐ”์˜ ์—”์ง„ ์นธ์— ๋ฐฉ์‹์ด ๋ถ™์Šต๋‹ˆ๋‹ค.

  • F5 ๋ฅผ ๋ˆ„๋ฅด๋ฉด ๊ฒŒ์ž„ ํƒญ์ด ์—ด๋ฆฌ๊ณ  game.json, scripts/, resources/ ๋ฅผ ์›น ์—”์ง„์˜ ๊ฐ€์ƒ ํŒŒ์ผ ์‹œ์Šคํ…œ์— ์˜ฌ๋ฆฐ ๋’ค ์—”์ง„์ด ๋œน๋‹ˆ๋‹ค. resources/rtp/, resources/aldebaran/src/, *.zip, *.psd, 32 MB ๋ฅผ ๋„˜๋Š” ํŒŒ์ผ์€ ์˜ฌ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. canvas ๋Š” game.json ์˜ ์ฐฝ ํฌ๊ธฐ์ด๊ณ  ํƒญ์— ๋งž์ถฐ ์ •์ˆ˜ ๋ฐฐ์œจ๋กœ ์ปค์ง‘๋‹ˆ๋‹ค (ํƒญ์ด ์ž‘์œผ๋ฉด ์ค„์ธ๋‹ค).
  • ๊ฒŒ์ž„ ํƒญ์€ ์ฒ˜์Œ์— ๋ฌธ์„œ ์˜์—ญ ์˜ค๋ฅธ์ชฝ์˜ ์ƒˆ ๊ทธ๋ฃน์— ์—ด๋ ค์„œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๊ณ ์น˜๋Š” ๋™์•ˆ์—๋„ ๋ณด์ž…๋‹ˆ๋‹ค. ํƒญ์„ ๋‹ค๋ฅธ ์ž๋ฆฌ๋กœ ๋Œ์–ด ๋‘๋ฉด ๋‹ซ์•˜๋‹ค ๋‹ค์‹œ ์—ด์–ด๋„ ๊ทธ ์ž๋ฆฌ์— ์—ด๋ฆฝ๋‹ˆ๋‹ค (์—๋””ํ„ฐ๋ฅผ ์ƒˆ๋กœ ๊ณ ์น˜๋ฉด ์ฒ˜์Œ ์ž๋ฆฌ๋กœ).
  • ๊ฒŒ์ž„ ํƒญ์„ ๋ˆ„๋ฅด๊ฑฐ๋‚˜ (์ด๋ฏธ ์•ž์— ์žˆ์–ด๋„) ๋‹ค๋ฅธ ์ž๋ฆฌ๋กœ ๋Œ์–ด ์˜ฎ๊ธฐ๋ฉด ํ‚ค๊ฐ€ ๊ฒŒ์ž„์œผ๋กœ ๊ฐ‘๋‹ˆ๋‹ค. F5, Shift+F5, Ctrl+F5, ๋ฆฌ๋กœ๋“œ๋Š” ๊ฒŒ์ž„์ด๋‚˜ ์Šคํฌ๋ฆฝํŠธ ํŽธ์ง‘๊ธฐ๋‚˜ ์ž…๋ ฅ ์นธ์— ์ดˆ์ ์ด ์žˆ์–ด๋„, ํ•œ๊ธ€์„ ์กฐํ•ฉํ•˜๋Š” ์ค‘์ด์–ด๋„ ์—๋””ํ„ฐ๊ฐ€ ๋ฐ›๊ณ , ๋ธŒ๋ผ์šฐ์ €์˜ ์ƒˆ๋กœ ๊ณ ์นจ์œผ๋กœ ๊ฐ€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฆฌ๋กœ๋“œ๊ฐ€ ๊บผ์ ธ ์žˆ์„ ๋•Œ ๋ˆ„๋ฅธ Ctrl+Shift+R(mac์€ Cmd+Shift+R)๋„ ๋ธŒ๋ผ์šฐ์ €์˜ ๊ฐ•๋ ฅ ์ƒˆ๋กœ ๊ณ ์นจ์œผ๋กœ ๊ฐ€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์„ค์ • ๊ฐ™์€ ๋Œ€ํ™”์ƒ์ž๊ฐ€ ๋–  ์žˆ์„ ๋•Œ๋Š” ๋‹จ์ถ•ํ‚ค๊ฐ€ ๋Œ€ํ™”์ƒ์ž ๋ชซ์ด๋ผ F5 ๋„ ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ € ๋ชจ๋“œ์—์„œ ์ €์žฅํ•˜์ง€ ์•Š์€ ๋ฌธ์„œ๊ฐ€ ์žˆ์œผ๋ฉด ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ ๊ณ ์น˜๊ฑฐ๋‚˜ ๋‹ซ๊ธฐ ์ „์— ๋ฌป์Šต๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋“œ์™€ ์›นํŒ์˜ "์ƒ˜ํ”Œ๋กœ ํ•ด ๋ณด๊ธฐ"๋Š” ํŒŒ์ผ์ด ํŽ˜์ด์ง€์—๋งŒ ์žˆ์–ด์„œ, ์ด๋ฒˆ์— ์ €์žฅํ•œ ๊ฒƒ์ด ์žˆ์œผ๋ฉด ๋ฌธ์„œ๊ฐ€ ๋ชจ๋‘ ์ €์žฅ๋˜์–ด ์žˆ์–ด๋„ ๋ฌป์Šต๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ €๋Š” ๋ˆ„๋ฅด๊ธฐ ์ „์—๋Š” ์†Œ๋ฆฌ๋ฅผ ๋‚ด์ง€ ์•Š์•„์„œ, ์†Œ๋ฆฌ๊ฐ€ ๋ฉˆ์ถฐ ์žˆ์œผ๋ฉด "์†Œ๋ฆฌ ์ผœ๊ธฐ"๊ฐ€ ๋œน๋‹ˆ๋‹ค (๊ฒŒ์ž„ ํ™”๋ฉด์„ ๋ˆŒ๋Ÿฌ๋„ ์ผœ์ง„๋‹ค).
  • ์ถœ๋ ฅ(Lua print, ์—”์ง„ ๋กœ๊ทธ)์€ ์ฝ˜์†”์— ์˜ค๊ณ  ์˜ค๋ฅ˜ ์ค„์€ ๋งํฌ์ž…๋‹ˆ๋‹ค. ์Šคํฌ๋ฆฝํŠธ, ์”ฌ, ๋งต์„ ์ €์žฅํ•˜๋ฉด ๊ทธ ํŒŒ์ผ๋งŒ ๋‹ค์‹œ ์˜ฌ๋ฆฌ๊ณ  VM ์„ ๋‹ค์‹œ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค (์ฝ˜์†”์— "ํ•ซ ๋ฆฌ๋กœ๋“œ: ์—๋””ํ„ฐ ์•ˆ ์—”์ง„"). ํŒŒ์ผ์„ ์˜ฌ๋ฆฌ๊ฑฐ๋‚˜ ์—”์ง„์ด ๋œจ๋Š” ์ค‘์— ์ €์žฅํ•˜๋ฉด ์—”์ง„์ด ์ฒซ ํ”„๋ ˆ์ž„์„ ๋ˆ ๋’ค์— ๊ทธ ํŒŒ์ผ์„ ๋‹ค์‹œ ์˜ฌ๋ฆฝ๋‹ˆ๋‹ค. ๊ทธ ์‚ฌ์ด ์‹œ์ž‘ ์Šคํฌ๋ฆฝํŠธ๋‚˜ ์ฒซ update, render์˜ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋ฉด ๊ฒŒ์ž„์€ ๊ณง ๋๋‚˜๋ฏ€๋กœ ๊ณ ์นœ ๊ฒƒ์„ ์˜ฌ๋ฆฌ์ง€ ์•Š๊ณ  ์ฝ˜์†”์— "๊ฒŒ์ž„์ด ๋œจ๋Š” ์ค‘์— ๋๋‚˜์„œ ์ €์žฅํ•œ ํŒŒ์ผ์„ ์˜ฌ๋ฆฌ์ง€ ์•Š์•˜๋‹ค" ํ•œ ์ค„์„ ๋‚จ๊ธฐ๋‹ˆ F5๋กœ ๋‹ค์‹œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์‹คํ–‰ ์ค‘์—๋„ update๋‚˜ render์˜ ์˜ค๋ฅ˜๊ฐ€ ๋‚œ ๋’ค ๊ฒŒ์ž„์ด ๋๋‚˜๊ธฐ ์ „์— ๋“  ์ €์žฅ์€ ์˜ฌ๋ฆฌ์ง€ ์•Š๊ณ  "๊ฒŒ์ž„์ด ๋๋‚˜์„œ ์ €์žฅํ•œ ํŒŒ์ผ์„ ์˜ฌ๋ฆฌ์ง€ ์•Š์•˜๋‹ค" ํ•œ ์ค„๋งŒ ๋‚จ๊น๋‹ˆ๋‹ค (์ข…๋ฃŒ ์ฝ”๋“œ๋Š” ์—”์ง„์ด ์ค€ 1). ๊ฒŒ์ž„์ด ๋Œ์ง€ ์•Š์„ ๋•Œ ์ €์žฅํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋“œ์™€ ์›นํŒ(์ƒ˜ํ”Œ ํฌํ•จ)์€ ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š๊ณ  ์ˆ˜๋™ ๋ฆฌ๋กœ๋“œ๋„ ๊บผ์ ธ ์žˆ์œผ๋ฉฐ, ๋ธŒ๋ฆฌ์ง€ ๋ชจ๋“œ๋Š” ํ„ฐ๋ฏธ๋„์—์„œ INITIAL2D_HMR=1 ๋กœ ๋„์šด ์—”์ง„์œผ๋กœ ๋ณด๋‚ด๋˜ ์—”์ง„์ด ์—†์œผ๋ฉด ์ฝ˜์†”์— "์—”์ง„์ด ๋–  ์žˆ์ง€ ์•Š์•„ ๋ฆฌ๋กœ๋“œ๋ฅผ ๊ฑด๋„ˆ๋›ฐ์—ˆ๋‹ค" ํ•œ ์ค„๋งŒ ๋‚จ๊น๋‹ˆ๋‹ค. ์ •์ง€ํ•˜๊ฑฐ๋‚˜ ๊ฒŒ์ž„ ํƒญ์„ ๋‹ซ์œผ๋ฉด ์—”์ง„ ์ธ์Šคํ„ด์Šค์™€ WebGL ์ปจํ…์ŠคํŠธ๋ฅผ ๋ฒ„๋ฆฌ๊ณ , ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋ฉด ์ƒˆ๋กœ ๋„์›๋‹ˆ๋‹ค.
  • ์Šคํฌ๋ฆฝํŠธ ์˜ค๋ฅ˜๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ์—”์ง„๊ณผ ๊ฐ™์€ ์ค„(Lua error in update: ./scripts/lua/main.lua:5: ..., Ruby ๋Š” mruby: uncaught exception in update ์™€ ์—ญ์ถ”์ )๋กœ ์ฝ˜์†”์— ์˜ค๊ณ , ์ค„์„ ๋ˆ„๋ฅด๋ฉด ๊ทธ ํŒŒ์ผ ๊ทธ ์ค„๋กœ ๊ฐ‘๋‹ˆ๋‹ค. ๋๋‚˜๋Š” ๋ชจ์–‘๋„ ๋„ค์ดํ‹ฐ๋ธŒ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์‹œ์ž‘ ๋•Œ๋‚˜ Update, Render ์˜ ์˜ค๋ฅ˜๋Š” ๊ฒŒ์ž„์ด ์ข…๋ฃŒ ์ฝ”๋“œ 1 ๋กœ ๋๋‚˜๊ณ  (๊ฒŒ์ž„ ํƒญ ์ƒํƒœ ๋  "์˜ค๋ฅ˜๋กœ ๋๋‚จ (์ข…๋ฃŒ ์ฝ”๋“œ 1)", ์ƒํƒœ ๋ฐ” "์ข…๋ฃŒ ์ฝ”๋“œ 1"), ์‹คํ–‰ ์ค‘ ์ €์žฅํ•œ ์Šคํฌ๋ฆฝํŠธ์˜ ์˜ค๋ฅ˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋งŒ ๋ฉˆ์ถ”๊ณ  ๊ฒŒ์ž„ ํƒญ์€ ์‚ด์•„ ์žˆ์–ด์„œ ๊ณ ์ณ ์ €์žฅํ•˜๋ฉด ๋‹ค์‹œ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค (์ฝ˜์†”์— ๊ฒฝ๊ณ ). Ruby ์˜ ๋์—†๋Š” ์žฌ๊ท€๋Š” C ๋ฅผ ๊ฑฐ์น˜๋Š” ๊ฒƒ(๋ฌธ์ž์—ด ๋ณด๊ฐ„ ์•ˆ์˜ to_s ๊ฐ™์€)๋„ ๋„ค์ดํ‹ฐ๋ธŒ์ฒ˜๋Ÿผ SystemStackError ์ด๊ณ , ์—”์ง„ ๋ฐ”์ธ๋”ฉ ์•ˆ์—์„œ ๋‚œ C++ ์˜ˆ์™ธ(ํƒ€์ž…์ด ํ‹€๋ฆฐ ๋งต์„ ์ฝ์€ Tilemap.new ๊ฐ™์€)๋Š” RuntimeError ๋ผ์„œ rescue ๋กœ ์žกํž™๋‹ˆ๋‹ค. ์•Œ๋ ค์ง„ ํ•œ๊ณ„: ์›น ์—”์ง„์—์„œ๋Š” C๋ฅผ ๊ฑฐ์นœ ๊นŠ์€ ์žฌ๊ท€ ๋„ˆ๋จธ์˜ ์˜ˆ์™ธ๋ฅผ rescue๋กœ ์žก์„ ๋•Œ๋งˆ๋‹ค ๊ฒŒ์ž„์ด ๋ฉˆ์ถฅ๋‹ˆ๋‹ค. ํฌ๋กฌ์—์„œ ์ˆ˜์‹ญ ms, DevTools๊ฐ€ ๋ถ™์–ด ์žˆ์œผ๋ฉด ์ˆ˜๋ฐฑ ms์ด๊ณ  ๋„ค์ดํ‹ฐ๋ธŒ๋Š” 0 ms์ž…๋‹ˆ๋‹ค. ์Œ“์ธ ํ”„๋ ˆ์ž„์„ ํ•˜๋‚˜์”ฉ ํ’€์–ด ๋‚ด๋Š” WebAssembly ์˜ˆ์™ธ ์ฒ˜๋ฆฌ์˜ ๋น„์šฉ์ด๋ผ ์—”์ง„์—์„œ ๊ณ ์น  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ, update๋งˆ๋‹ค ์žก์ง€ ๋ง๊ณ  ๋์—†๋Š” ์žฌ๊ท€๋ฅผ ๊ณ ์นฉ๋‹ˆ๋‹ค. ์˜ˆ์™ธ๊ฐ€ ์—”์ง„ ๋ฐ–์œผ๋กœ ๋‚˜์˜ค๋ฉด(์—”์ง„์ด ์ฃฝ์—ˆ๋‹ค) ์ฝ˜์†”์— fatal: ํƒ€์ž…: ๋ฉ”์‹œ์ง€ ์ค„์ด ์ฐํžˆ๊ณ  ์ข…๋ฃŒ ์ฝ”๋“œ 1 ๋กœ ๋๋‚ฉ๋‹ˆ๋‹ค. ์›น ์—”์ง„์—์„œ Lua ์˜ os.exit ์™€ Ruby ์˜ exit! ๋Š” ๊ฒŒ์ž„์„ ๋๋‚ด์ง€ ์•Š์œผ๋ฏ€๋กœ GameExit() ๋‚˜ System.exit ์„ ์”๋‹ˆ๋‹ค. ์ด ํŒ๋‹จ๊ณผ FPS(์—”์ง„์ด ๋ˆ ํ”„๋ ˆ์ž„ ์ˆ˜)๋Š” ์—”์ง„ ๋กœ๋”์˜ onExit, frames(), errorText() ๋ฅผ ์“ฐ๊ณ , ๊ทธ๊ฒƒ์ด ์—†๋Š” ์˜› ์—”์ง„ ๋นŒ๋“œ์—์„œ๋Š” ์ค„๊ณผ window ์˜ค๋ฅ˜๋กœ ์•Œ์•„๋‚ด๊ณ  FPS ๋Š” ํŽ˜์ด์ง€์˜ ํ”„๋ ˆ์ž„ ์ˆ˜์ž…๋‹ˆ๋‹ค.
  • ์›น ์—”์ง„ ๋นŒ๋“œ์— mruby ๊ฐ€ ๋“ค์—ˆ์œผ๋ฉด(MANIFEST.json ์˜ ๊ธฐ๋Šฅ์ด lua mruby wasm) game.json ์˜ script ๊ฐ€ mruby ์ธ ๊ฒŒ์ž„๋„ ๊ฒŒ์ž„ ํƒญ์—์„œ ๋•๋‹ˆ๋‹ค. mruby ์—†์ด ๋งŒ๋“  ๋นŒ๋“œ๋ฉด ๋„์šฐ์ง€ ์•Š๊ณ  ์ด์œ ๋ฅผ ์•Œ๋ฆฝ๋‹ˆ๋‹ค.
  • ์—”์ง„ ํŒŒ์ผ์€ packages/app/public/engine/ ์— ๋“  ์—”์ง„ ์ €์žฅ์†Œ ์›น ๋นŒ๋“œ์˜ ์‚ฌ๋ณธ์ด๊ณ  Cloudflare Pages ๋นŒ๋“œ์— ๊ทธ๋Œ€๋กœ ์‹ค๋ฆฝ๋‹ˆ๋‹ค. ์—”์ง„์„ ๊ณ ์ณค์œผ๋ฉด ์—”์ง„ ์ €์žฅ์†Œ์—์„œ tools/build_web.sh ๋ฅผ ๋Œ๋ฆฐ ๋’ค INITIAL2D_DIR=../Initial2D yarn sync:engine-web ์œผ๋กœ ๋‹ค์‹œ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. MANIFEST.json ์— ์—”์ง„ ์ปค๋ฐ‹, ์ปค๋ฐ‹ ์•ˆ ๋œ ๋ณ€๊ฒฝ์ด ์žˆ์—ˆ๋Š”์ง€, sha256, ๊ธฐ๋Šฅ(wasm ์— libmruby ๊ฐ€ ๋งํฌ๋˜์—ˆ์œผ๋ฉด mruby)์ด ์ ํžˆ๊ณ  ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ํŒŒ์ผ๊ณผ ๋Œ€์กฐํ•ฉ๋‹ˆ๋‹ค. INITIAL2D_DIR ์ €์žฅ์†Œ๊ฐ€ MANIFEST ์˜ ์—”์ง„ ์ปค๋ฐ‹์— ์žˆ์œผ๋ฉด ๊ทธ build-web/site/ ์™€๋„ ๋Œ€์กฐํ•˜๊ณ , ์ปค๋ฐ‹์ด ๋‹ค๋ฅด๋ฉด ๊นŒ๋‹ญ์„ ์ ๊ณ  ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค.
  • e2e ๋Š” tests/e2e/game-view.spec.ts ์ž…๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋“œ ์ƒ˜ํ”Œ(Lua ์™€ Ruby, Lua ์˜ค๋ฅ˜ ๋‘˜, Ruby ์˜ค๋ฅ˜ ๋‘˜. Ruby ์˜ค๋ฅ˜๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ์—”์ง„์ด ๊ฐ™์€ ํŒŒ์ผ๋กœ ์ฐ๋Š” ์ค„ ๋ฌถ์Œ๊ณผ ๊ฒฌ์ค๋‹ˆ๋‹ค)๊ณผ, ์—”์ง„ ์ €์žฅ์†Œ(INITIAL2D_DIR)๊ฐ€ ์žˆ์œผ๋ฉด ์•Œ๋ฐ๋ฐ”๋ž€ ์‚ฌ๋ณธ์„ ๋ธŒ๋ฆฌ์ง€ ๋ชจ๋“œ(ํฌํŠธ 6073, E2E_BRIDGE_PORT ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค)๋กœ Lua ์™€ Ruby ๋‘ ํŒ ๋Œ๋ฆฝ๋‹ˆ๋‹ค. GAME_VIEW_SCREENSHOT=<png ๊ฒฝ๋กœ> ๋ฅผ ์ฃผ๋ฉด ๊ฒŒ์ž„ ํƒญ์„ ์ฐ์–ด ๋‘ก๋‹ˆ๋‹ค.
  • ๊ฐ™์€ ํ™”๋ฉด์ธ์ง€: ๊ฐ™์€ e2e ๊ฐ€ ์—”์ง„์˜ ์ธ์ˆ˜ ์”ฌ(์•Œ๋ฐ๋ฐ”๋ž€ ํƒ€์ดํ‹€, INITIAL2D_ALDEBARAN_STOP=title)์„ ๊ฐ™์€ ํŒŒ์ผ๋กœ ๋„ค์ดํ‹ฐ๋ธŒ ์—”์ง„(ํ—ค๋“œ๋ฆฌ์Šค, ํ”„๋กœ์„ธ์Šค ์‹คํ–‰๊ณผ ๊ฐ™์€ ์‹คํ–‰ ํŒŒ์ผ)๊ณผ ๊ฒŒ์ž„ ํƒญ์—์„œ ๋Œ๋ ค 20 ํ”„๋ ˆ์ž„์งธ๋ฅผ ๊ฒฌ์ค๋‹ˆ๋‹ค. ๊ทœ์น™์€ ์—”์ง„์˜ ๊ณจ๋“  ๊ฒ€์‚ฌ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค (์ฑ„๋„ ์ฐจ์ด 24 ์ดˆ๊ณผ๋ฉด ๋‹ค๋ฅธ ํ”ฝ์…€, ๋‹ค๋ฅธ ํ”ฝ์…€ 2% ๊นŒ์ง€). ๋„ค์ดํ‹ฐ๋ธŒ ์‹คํ–‰ ํŒŒ์ผ์€ INITIAL2D_NATIVE (๊ธฐ๋ณธ <์—”์ง„ ์ €์žฅ์†Œ>/build/Initial2D)์ด๊ณ , ์—†์œผ๋ฉด ์—”์ง„ ์ €์žฅ์†Œ์˜ ๊ณจ๋“  tests/golden/aldebaran_title.png ์™€ ๊ฒฌ์ค๋‹ˆ๋‹ค. ์žฐ ๊ฐ’์€ docs/plans/e4-embedded-play.md ์— ์žˆ์Šต๋‹ˆ๋‹ค.

์”ฌ ํŽธ์ง‘ (E2)

  • resources/scenes/*.json ์„ ์—ด๋ฉด ์”ฌ ๋ทฐ(PIXI)๊ฐ€ ๋œน๋‹ˆ๋‹ค. ํด๋ฆญ๊ณผ ์ƒ์ž ์„ ํƒ, ๋Œ๊ธฐ(๋˜๋Œ๋ฆฌ๊ธฐ ํ•œ ๋‹จ๊ณ„), ๋ฐฉํ–ฅํ‚ค(1px, Shift 10px), ๊ฒฉ์ž์™€ ์Šค๋ƒ…๊ณผ ์คŒ(Ctrl+=, Ctrl+-, Ctrl+0), ์นด๋ฉ”๋ผ ์‚ฌ๊ฐํ˜•์€ game.json ์˜ ์ฐฝ ํฌ๊ธฐ์™€ ๋ฐฐ์œจ์—์„œ ์˜ต๋‹ˆ๋‹ค. ์”ฌ ๋ทฐ๋Š” ๊ทผ์‚ฌ์ด๊ณ  ์ง„์งœ ํ™”๋ฉด์€ ์‹คํ–‰์ด ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค (ํ˜„์žฌ ์”ฌ๋ถ€ํ„ฐ ์‹คํ–‰ Ctrl+F5).

  • ๊ณ„์ธต ํŒจ๋„์€ ๊ทธ๋ฆฌ๊ธฐ ์ˆœ์„œ์ด๊ณ (์œ„๊ฐ€ ๋จผ์ €), ๋ˆˆ ํ† ๊ธ€๊ณผ ์ด๋ฆ„ ๋ฐ”๊พธ๊ธฐ(F2)์™€ ๋Œ์–ด์„œ ์ˆœ์„œ ๋ฐ”๊พธ๊ธฐ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์ธ์ŠคํŽ™ํ„ฐ๋Š” ๊ณตํ†ต ์นธ(id, x, y, ํ‘œ์‹œ)๊ณผ ํƒ€์ž…๋ณ„ ์นธ(์Šคํ”„๋ผ์ดํŠธ: ์ด๋ฏธ์ง€์™€ ํ”„๋ ˆ์ž„๊ณผ ๋ฐฐ์œจ, ๊ธ€์ž: ๊ธ€๊ณผ ํฐํŠธ), ์Šคํฌ๋ฆฝํŠธ ๋ชฉ๋ก(๋ถ™์ด๊ธฐ, ๋งŒ๋“ค๊ธฐ, ์—ด๊ธฐ, ์ˆœ์„œ, ๋งค๊ฐœ๋ณ€์ˆ˜), ๊ฒ€์‚ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค.

  • ์ปดํฌ๋„ŒํŠธ์™€ ๋งค๊ฐœ๋ณ€์ˆ˜: ์ธ์ŠคํŽ™ํ„ฐ๋Š” ๋ถ™์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—”์ง„์ด ๋ถ€๋ฅด๋Š” ์ˆœ์„œ๋Œ€๋กœ ๋ณด์—ฌ ์ฃผ๊ณ , ์œ„์•„๋ž˜ ๋‹จ์ถ”๋กœ ์ˆœ์„œ๋ฅผ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค. ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” scripts/components/<๊ฒฝ๋กœ>.json ์— ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค (Lua์™€ Ruby๊ฐ€ ๊ฐ™์€ ํŒŒ์ผ์„ ์”๋‹ˆ๋‹ค). ์„ ์–ธ์ด ์žˆ์œผ๋ฉด ์ธ์ŠคํŽ™ํ„ฐ๊ฐ€ ๊ทธ ํ•„๋“œ๋กœ ํผ์„ ๊ทธ๋ฆฌ๊ณ , ๊ณ ์นœ ๊ฐ’๋งŒ ์”ฌ ํŒŒ์ผ์˜ params ์— ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. "๊ธฐ๋ณธ๊ฐ’ ๋ณต์›"์€ ๊ณ ์นœ ๊ฐ’์„ ์ง€์›๋‹ˆ๋‹ค. ์„ ์–ธ์ด ์—†์œผ๋ฉด "๋งค๊ฐœ๋ณ€์ˆ˜ ์„ ์–ธ ๋งŒ๋“ค๊ธฐ"๊ฐ€ ์˜ค๋ธŒ์ ํŠธ์— ์ด๋ฏธ ์žˆ๋Š” ๊ฐ’์˜ ํ˜•์‹์œผ๋กœ ์„ ์–ธ ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ์—ฝ๋‹ˆ๋‹ค. ํŽธ์ง‘๊ธฐ๋Š” ์„ ์–ธ ํŒŒ์ผ์„ ์Šคํ‚ค๋งˆ๋กœ ๊ฒ€์‚ฌํ•˜๊ณ , ์„ ์–ธ์— ๋งž์ง€ ์•Š๋Š” ๊ฐ’(๋ชจ๋ฅด๋Š” ํ‚ค, ํ˜•์‹, ๋ฒ”์œ„, ์”ฌ์— ์—†๋Š” ์˜ค๋ธŒ์ ํŠธ)์€ ๊ฒ€์‚ฌ ๊ฒฐ๊ณผ์— ์˜ค๋ฅ˜๋กœ ๋œน๋‹ˆ๋‹ค. ํ˜•์‹์€ ์—”์ง„ docs/plans/r1-scene-loader.md 5.4์ ˆ์ž…๋‹ˆ๋‹ค.

    { "version": 1, "fields": [
      { "key": "speed", "type": "number", "label": "์†๋„", "default": 60, "min": 0 },
      { "key": "target", "type": "object", "label": "๋Œ€์ƒ" }
    ] }

    ํ•„๋“œ ํ˜•์‹์€ string, text, number, integer, boolean, enum(values ์ค‘ ํ•˜๋‚˜), object(์”ฌ ์˜ค๋ธŒ์ ํŠธ id)์ž…๋‹ˆ๋‹ค. Lua ์ปดํฌ๋„ŒํŠธ๋Š” ํ›…์˜ ๋งˆ์ง€๋ง‰ ์ธ์ž๋กœ ๋ฐ›๊ณ (function Mover.update(obj, scene, elapsed, params)), Ruby ์ปดํฌ๋„ŒํŠธ๋Š” initialize(params = {}) ๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค.

    ์”ฌ ๋กœ๋”๋Š” ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค ๋•Œ ํ…œํ”Œ๋ฆฟ์—์„œ ๋ณต์‚ฌ๋ฉ๋‹ˆ๋‹ค. ์—”์ง„ v2.0.0-alpha.2 ์ „์— ๋งŒ๋“  ํ”„๋กœ์ ํŠธ์˜ ๋กœ๋”๋Š” params ๋ฅผ ๋„˜๊ธฐ์ง€ ์•Š์œผ๋ฏ€๋กœ, ์ธ์ŠคํŽ™ํ„ฐ๊ฐ€ ์ด๋ฅผ ์•Œ๋ฆฌ๊ณ  "์”ฌ ๋กœ๋” ๊ต์ฒด"๋กœ ์—๋””ํ„ฐ์— ๋“  ๋กœ๋”๋กœ ๋ฎ์–ด์”๋‹ˆ๋‹ค (๋กœ๋”๋ฅผ ์ง์ ‘ ๊ณ ์ณค๋‹ค๋ฉด ๊ทธ ๋ณ€๊ฒฝ์€ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค).

  • ์”ฌ ๋ฉ”๋‰ด: ์ƒˆ ์”ฌ(Ctrl+Shift+N), ์˜ค๋ธŒ์ ํŠธ ์ถ”๊ฐ€(Ctrl+Shift+A ๋˜๋Š” ํƒ€์ž…๋ณ„ ํ•˜์œ„ ๋ฉ”๋‰ด), ์‹œ์ž‘ ์”ฌ์œผ๋กœ ์ง€์ •(game.json ์˜ startScene). ํŽธ์ง‘ ๋ฉ”๋‰ด์˜ ๋ณต์‚ฌ์™€ ๋ถ™์—ฌ๋„ฃ๊ธฐ์™€ ๋ณต์ œ(Ctrl+D)์™€ ์‚ญ์ œ๋Š” ์”ฌ ํƒญ์—์„œ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

  • ํƒ€์ผ๋งต ์˜ค๋ธŒ์ ํŠธ: ์”ฌ > ์˜ค๋ธŒ์ ํŠธ ์ถ”๊ฐ€ > ํƒ€์ผ๋งต. ์ธ์ŠคํŽ™ํ„ฐ์—์„œ resources/maps/์˜ ๋งต ํŒŒ์ผ์„ ๊ณ ๋ฅด๋ฉด ์”ฌ ๋ทฐ๊ฐ€ ๊ทธ ๋งต์˜ ๋ ˆ์ด์–ด๋ฅผ ํƒ€์ผ์…‹์œผ๋กœ ์˜ค๋ธŒ์ ํŠธ ์ž๋ฆฌ์— ๊ทธ๋ฆฌ๊ณ , ๋งต ํŒŒ์ผ์ด๋‚˜ ํƒ€์ผ์…‹ ๊ทธ๋ฆผ์ด ๋ฐ”๋€Œ๋ฉด ๋‹ค์‹œ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค. ๋ฐ”๋‹ฅ ๋ ˆ์ด์–ด ์ˆ˜(groundLayers)๋งŒํผ์˜ ์•ž ๋ ˆ์ด์–ด๋Š” ์”ฌ์˜ ๋ชจ๋“  ์˜ค๋ธŒ์ ํŠธ ์•„๋ž˜์—, ๋‚˜๋จธ์ง€ ๋ ˆ์ด์–ด๋Š” ๋ชจ๋“  ์˜ค๋ธŒ์ ํŠธ ์œ„์— ๊ทธ๋ฆฝ๋‹ˆ๋‹ค. ๋ชฉ๋ก์—์„œ ํƒ€์ผ๋งต๋ณด๋‹ค ์•ž์— ์žˆ๋Š” ์˜ค๋ธŒ์ ํŠธ๋„ ๋ฐ”๋‹ฅ ์œ„์— ๋ณด์ด๊ณ , ๊ฒŒ์ž„(์—”์ง„์˜ scene_types/tilemap ๋ชจ๋“ˆ์ด ๊ฐ™์€ ํŒŒ์ผ์„ ์—ฐ๋‹ค)๊ณผ ๊ฐ™์€ ์ˆœ์„œ์ž…๋‹ˆ๋‹ค. "๋งต ์—ด๊ธฐ"๋Š” ๊ทธ ๋งต์„ ๋งต ๋ทฐ๋กœ ์—ฝ๋‹ˆ๋‹ค. ์”ฌ ๋ทฐ์—์„œ ํƒ€์ผ๋งต์€ ๋ฐฐ๊ฒฝ์ฒ˜๋Ÿผ ๋‹ค๋ฃน๋‹ˆ๋‹ค. ๋ˆ„๋ฅด๊ณ  ๋†“์œผ๋ฉด ๊ณ ๋ฅด๊ณ , ๊ณ ๋ฅธ ๋’ค์— ๋Œ์–ด์•ผ ์˜ฎ๊ฒจ์ง€๋ฉฐ, ๊ณ ๋ฅด์ง€ ์•Š์€ ๋งต ์œ„์—์„œ ๋Œ๋ฉด ์ƒ์ž ์„ ํƒ์ด ๋ฉ๋‹ˆ๋‹ค. ๋งต ํŒŒ์ผ์„ ๊ณ ๋ฅด์ง€ ์•Š์•˜๊ฑฐ๋‚˜, ๊ณ ๋ฅธ ๋งต ํŒŒ์ผ์ด ์—†๊ฑฐ๋‚˜(์ง€์› ๊ฑฐ๋‚˜ ์ด๋ฆ„์„ ๋ฐ”๊ฟˆ), ์žˆ์–ด๋„ ์—”์ง„์ด ์—ด์ง€ ๋ชปํ•˜๋Š” ๋งต(JSON์ด ์•„๋‹ˆ๊ฑฐ๋‚˜, ๋ฒ„์ „๊ณผ ํฌ๊ธฐ๊ฐ€ ํ‹€๋ ธ๊ฑฐ๋‚˜, ๋ ˆ์ด์–ด๋‚˜ ํƒ€์ผ์…‹์ด ๋น„์—ˆ๊ฑฐ๋‚˜, ํƒ€์ผ์…‹ ๊ทธ๋ฆผ์ด ์—†๋Š” ๋งต)์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํƒ€์ผ๋งต์€ ์—”์ง„์ด ์”ฌ์„ ๊ฑฐ๋ถ€ํ•˜๋ฏ€๋กœ ๊ฒ€์‚ฌ ๊ฒฐ๊ณผ์— ์˜ค๋ฅ˜๋กœ ๋œน๋‹ˆ๋‹ค. ๊ฒ€์‚ฌ๋Š” ์—”์ง„์˜ ๋งต ์ฝ๊ธฐ ๊ทœ์น™์„ ๊ทธ๋Œ€๋กœ ๋”ฐ๋ผ์„œ, ์—”์ง„์ด ์—ฌ๋Š” ๋งต์€ ์˜ค๋ฅ˜๋กœ ๋ณด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋งต ํŒŒ์ผ์ด๋‚˜ ๊ทธ ํƒ€์ผ์…‹ ๊ทธ๋ฆผ์ด ๋ฐ”๋€Œ๋ฉด ๋‹ค์‹œ ๊ฒ€์‚ฌํ•ฉ๋‹ˆ๋‹ค.

  • ์ƒˆ ํ”„๋กœ์ ํŠธ(Tauri): ๋นˆ ํ”„๋กœ์ ํŠธ, ํ”Œ๋ž˜ํ”ผ๋ฒ„๋“œ, ํƒ€์ผ๋งต, RPG ๋ฐ๋ชจ ๊ฐ€์šด๋ฐ ํ•˜๋‚˜์™€ Lua ๋˜๋Š” Ruby. ์—”์ง„์˜ ์”ฌ ๋กœ๋”์™€ ์ง„์ž… ํŒŒ์ผ๊ณผ ์˜ˆ์ œ๊ฐ€ ํ•จ๊ป˜ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. ํƒ€์ผ๋งต์€ ํƒ€์ผ์…‹๊ณผ ๋งต ํ•œ ์žฅ(resources/maps/start.json), ๊ทธ ๋งต์„ ์—ฌ๋Š” ์”ฌ, ๋งต ์˜ค๋ธŒ์ ํŠธ ์Šคํ‚ค๋งˆ๋ผ์„œ ๋งต์„ ์น ํ•˜๊ณ  ๋ฐ”๋กœ F5 ๋กœ ๋Œ๋ ค ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. RPG ๋ฐ๋ชจ๋Š” ์—”์ง„์˜ ใ€Œ๋– ๋‚˜๊ธฐ ์ „์—ใ€(ํƒ€์ดํ‹€, ํ•ญ๊ตฌ ๋งˆ์„๊ณผ ์—ฌ๊ด€, ์ด๋ฒคํŠธ์™€ ๋Œ€ํ™”, ์•„์ดํ…œ)์ด๊ณ  RPG ๋ ˆ์ด์–ด๊ฐ€ Lua ์—๋งŒ ์žˆ์–ด Lua ๋กœ๋งŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. .gitignore ์—๋Š” .initial-editor/ ์™€ ์—”์ง„์ด ์‹คํ–‰ํ•  ๋•Œ ์“ฐ๋Š” config.setting ์ด ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.

  • ํ…œํ”Œ๋ฆฟ ํŒŒ์ผ์€ ์—”์ง„ ์ €์žฅ์†Œ์˜ ์‚ฌ๋ณธ์ž…๋‹ˆ๋‹ค. INITIAL2D_DIR=../Initial2D yarn sync:templates ๋กœ ์—”์ง„ ์ฒดํฌ์•„์›ƒ์—์„œ ๋‹ค์‹œ ๋งž์ถ”๊ณ , ์—”์ง„์˜ ํ…œํ”Œ๋ฆฟ ๋ฌถ์Œ(tools/pack_templates.py ๊ฐ€ ๋งŒ๋“  Initial2D-templates.zip)์—์„œ ๋งž์ถœ ๋•Œ๋Š” yarn sync:templates --from-zip <zip ์ด๋‚˜ dist ํด๋”> ์ž…๋‹ˆ๋‹ค. ์—”์ง„์˜ ์ถ”์  ํŒŒ์ผ์ด ์ปค๋ฐ‹๊ณผ ๋‹ค๋ฅด๋ฉด ๋ฉˆ์ถ”๋ฏ€๋กœ ์—”์ง„์„ ๋จผ์ € ์ปค๋ฐ‹ํ•ฉ๋‹ˆ๋‹ค (--allow-dirty ๋กœ ๋„˜๊ธธ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ๊ทธ ์‚ฌ๋ณธ์€ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ๋ง‰์Šต๋‹ˆ๋‹ค).

  • ๊ต์ฐจ ๊ฒ€์‚ฌ yarn test:engine-scene ์ด ํ…œํ”Œ๋ฆฟ ์…‹ x ์–ธ์–ด ๋‘˜์„ ์ž„์‹œ ํ”„๋กœ์ ํŠธ๋กœ ์จ์„œ ์ง„์งœ ์—”์ง„์„ ํ—ค๋“œ๋ฆฌ์Šค๋กœ ๋Œ๋ฆฝ๋‹ˆ๋‹ค. ๋นˆ ํ”„๋กœ์ ํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ์— ๋งค๊ฐœ๋ณ€์ˆ˜ ์„ ์–ธ๊ณผ ๊ฐ’์„ ์ฃผ๊ณ  ์—”์ง„์ด ๋„˜๊ธด params ๋ฅผ ๋ด…๋‹ˆ๋‹ค. ํƒ€์ผ๋งต์€ ๋งต ๋ฌธ์„œ๋กœ ์นธ (24, 28) ์„ ํ‘œ์‹ ํƒ€์ผ๋กœ ์น ํ•ด ์ €์žฅํ•œ ๋’ค ์—”์ง„ ํ™”๋ฉด์˜ ๊ทธ ์นธ ์ƒ‰์„ ๋ด…๋‹ˆ๋‹ค. ์—”์ง„์€ INITIAL2D_DIR ์˜ build/Initial2D ์ด๊ณ , ๋ฐฐํฌ์šฉ ๋นŒ๋“œ์ฒ˜๋Ÿผ ๋‹ค๋ฅธ ์‹คํ–‰ ํŒŒ์ผ์€ INITIAL2D_EXE=<๊ฒฝ๋กœ> yarn test:engine-scene ์œผ๋กœ ์ค๋‹ˆ๋‹ค.

๋น„์ฃผ์–ผ ์Šคํฌ๋ฆฝํŒ…

์ปดํฌ๋„ŒํŠธ๋ฅผ ๋…ธ๋“œ ๊ทธ๋ž˜ํ”„๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜ํ”„๋Š” ์ƒˆ ์‹คํ–‰๊ธฐ๊ฐ€ ์•„๋‹ˆ๋ผ Lua ์™€ Ruby ์ฝ”๋“œ๋ฅผ ๋งŒ๋“œ๋Š” ์›๋ณธ์ด๋ผ์„œ, ๊ฒŒ์ž„์€ ์†์œผ๋กœ ์“ด ์ปดํฌ๋„ŒํŠธ์™€ ๋˜‘๊ฐ™์ด ๋•๋‹ˆ๋‹ค (์”ฌ ๋กœ๋”, ๋งค๊ฐœ๋ณ€์ˆ˜, ํ•ซ ๋ฆฌ๋กœ๋“œ, ์˜ค๋ฅ˜ ์ค„). ๊ณ„ํš๊ณผ ํฌ๋งท์€ docs/plans/visual-scripting.md์ž…๋‹ˆ๋‹ค.

  • ๊ทธ๋ž˜ํ”„๋Š” scripts/components/<๊ฒฝ๋กœ>.graph.json ์ด๊ณ  ์ปดํฌ๋„ŒํŠธ components/<๊ฒฝ๋กœ> ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์ €์žฅํ•˜๋ฉด scripts/lua/components/<๊ฒฝ๋กœ>.lua, scripts/ruby/components/<๊ฒฝ๋กœ>.rb, ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ–ˆ์œผ๋ฉด ์„ ์–ธ ํŒŒ์ผ scripts/components/<๊ฒฝ๋กœ>.json ์„ ํ•จ๊ป˜ ์”๋‹ˆ๋‹ค. ์ƒ์„ฑ ํŒŒ์ผ์€ ์ปค๋ฐ‹ํ•ฉ๋‹ˆ๋‹ค (์—”์ง„์€ ๊ทธ๋ž˜ํ”„๋ฅผ ์ฝ์ง€ ์•Š์Šต๋‹ˆ๋‹ค). ๊ฒŒ์ž„์ด ๋„๋Š” ์ค‘์ด๋ฉด ์ƒ์„ฑ ์ฝ”๋“œ๋„ ํ•ซ ๋ฆฌ๋กœ๋“œ์— ์‹ค๋ฆฝ๋‹ˆ๋‹ค.
  • ํŒŒ์ผ > ์ƒˆ ๊ทธ๋ž˜ํ”„ ์ปดํฌ๋„ŒํŠธ(Ctrl+Alt+G)๋กœ ๋งŒ๋“ค๊ณ , ๊ทธ๋ž˜ํ”„ ํŒŒ์ผ์„ ์—ด๋ฉด ์บ”๋ฒ„์Šค๊ฐ€ ๋œน๋‹ˆ๋‹ค. ๋…ธ๋“œ๋Š” ์˜ค๋ฅธ์ชฝ ํด๋ฆญ์ด๋‚˜ ๋‘ ๋ฒˆ ํด๋ฆญ, ๋˜๋Š” ํฌํŠธ์—์„œ ๋ˆ ์„ ์„ ๋นˆ ๊ณณ์— ๋†“์•„ ์—ฌ๋Š” ๋ชฉ๋ก์—์„œ ๋”ํ•˜๊ณ , ํฌํŠธ์—์„œ ํฌํŠธ๋กœ ๋Œ์–ด ์ž‡์Šต๋‹ˆ๋‹ค. ์ด์–ด์ง€์ง€ ์•Š์€ ์ž…๋ ฅ์˜ ์ƒ์ˆ˜๋Š” ๋…ธ๋“œ ์•ˆ์—์„œ ๊ณ ์นฉ๋‹ˆ๋‹ค. ์˜† ์ฐฝ์—์„œ ๊ณ ๋ฅธ ๋…ธ๋“œ์˜ ์„ค์ •๊ณผ ์ƒํƒœ ํ•„๋“œ, ์ง€์—ญ ๋ณ€์ˆ˜, ๋งค๊ฐœ๋ณ€์ˆ˜, ๋…ธ๋“œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ณ ์นฉ๋‹ˆ๋‹ค. ์ž๋™ ์ •๋ ฌ, ๋˜๋Œ๋ฆฌ๊ธฐ, ๋ณต์‚ฌ์™€ ๋ถ™์—ฌ๋„ฃ๊ธฐ, ๋ณต์ œ, ์‚ญ์ œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
  • ์ด๋™์€ ๊ฐ€์šด๋ฐ๋‚˜ ์˜ค๋ฅธ์ชฝ ๋ฒ„ํŠผ(๋˜๋Š” Space ์™€ ๋Œ๊ธฐ), ํ™•๋Œ€๋Š” ํœ , F ๋Š” ํ™”๋ฉด ๋งž์ถค์ด๊ณ , ์˜ค๋ฅธ์ชฝ ์•„๋ž˜ ๋ฏธ๋‹ˆ๋งต์„ ๋ˆ„๋ฅด๋ฉด ๊ทธ ์ž๋ฆฌ๋กœ ๊ฐ‘๋‹ˆ๋‹ค. ์„ ์˜ ์˜ค๋ฅธ์ชฝ ํด๋ฆญ์ด๋‚˜ Alt ์™€ ํฌํŠธ ํด๋ฆญ์€ ์—ฐ๊ฒฐ์„ ๋Š์Šต๋‹ˆ๋‹ค. ์„ ์„ ๋นˆ ๊ณณ์— ๋†“์•„ ์—ฐ ๋ชฉ๋ก์€ ๊ทธ ์„ ์— ์ด์„ ์ˆ˜ ์žˆ๋Š” ๋…ธ๋“œ๋งŒ ๋ณด์ž…๋‹ˆ๋‹ค.
  • ์˜† ์ฐฝ์˜ ์ƒํƒœ ํ•„๋“œ, ์ง€์—ญ ๋ณ€์ˆ˜, ๋งค๊ฐœ๋ณ€์ˆ˜ ์ค„ ์•ž์˜ โ ฟ ์•„์ด์ฝ˜์„ ์บ”๋ฒ„์Šค๋กœ ๋“œ๋ž˜๊ทธํ•˜๋ฉด ๊ทธ ์ฝ๊ธฐ ๋…ธ๋“œ๊ฐ€ ์ƒ๊ธฐ๊ณ , ์ž…๋ ฅ ํฌํŠธ ์œ„๋กœ ๋“œ๋ž˜๊ทธํ•˜๋ฉด ๊ทธ ํฌํŠธ์— ๋ฐ”๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค. Alt ๋ฅผ ๋ˆ„๋ฅธ ์ฑ„ ๋†“์œผ๋ฉด ์“ฐ๊ธฐ ๋…ธ๋“œ์ž…๋‹ˆ๋‹ค (๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์ฝ๊ธฐ๋งŒ).
  • ํšจ๊ณผ์Œ๊ณผ ๋ฐฐ๊ฒฝ ์Œ์•… ๋…ธ๋“œ๋Š” ํŒŒ์ผ ๊ฒฝ๋กœ(๋นˆ ๊ฐ’์ด๋‚˜ ํด๋” ๊ฒฝ๋กœ๋Š” ์˜ค๋ฅ˜), ์ด๋ฆ„(๋น„์šฐ๋ฉด ํŒŒ์ผ ๊ฒฝ๋กœ), ๋ฐ˜๋ณต(ํšจ๊ณผ์Œ์€ ์ถ”๊ฐ€ ๋ฐ˜๋ณต, ์Œ์•…์€ ์žฌ์ƒ ํšŸ์ˆ˜)์ž…๋‹ˆ๋‹ค.
  • ๋จธ๋ฆฌ์ค„์˜ "๋ฉ”๋ชจ"๋Š” ์„ ํƒํ•œ ๋…ธ๋“œ๋ฅผ ๊ฐ์‹ธ๋Š” ๋ฉ”๋ชจ ์ƒ์ž๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ œ๋ชฉ ์ค„์„ ๋Œ๋ฉด ์•ˆ์˜ ๋…ธ๋“œ๊ฐ€ ํ•จ๊ป˜ ์›€์ง์ž…๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋Š” ์ฝ”๋“œ์— ๋“ค์–ด๊ฐ€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์˜ค๋ฅ˜๊ฐ€ ์žˆ์œผ๋ฉด ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๊ณ , ๋…ธ๋“œ ํ…Œ๋‘๋ฆฌ์™€ ์˜† ์ฐฝ์˜ ๋ฌธ์ œ ๋ชฉ๋ก์— ๋ณด์ž…๋‹ˆ๋‹ค. ๊ฒŒ์ž„์˜ ์˜ค๋ฅ˜ ์ค„(์ฝ˜์†” ๋งํฌ)์ด ์ƒ์„ฑ ํŒŒ์ผ์„ ๊ฐ€๋ฆฌํ‚ค๋ฉด ๊ทธ๋ž˜ํ”„๋ฅผ ์—ด๊ณ  ๊ทธ ์ค„์„ ๋งŒ๋“  ๋…ธ๋“œ๋ฅผ ๊ณ ๋ฆ…๋‹ˆ๋‹ค. ์ƒ์„ฑ ํŒŒ์ผ์€ ์Šคํฌ๋ฆฝํŠธ ์—๋””ํ„ฐ์—์„œ ์ฝ๊ธฐ ์ „์šฉ์ด๊ณ  "๊ทธ๋ž˜ํ”„ ์—ด๊ธฐ" ๋‹จ์ถ”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ธ์ŠคํŽ™ํ„ฐ์˜ ์ปดํฌ๋„ŒํŠธ "์—ด๊ธฐ"๋Š” ๊ทธ ์ปดํฌ๋„ŒํŠธ์˜ ๊ทธ๋ž˜ํ”„๊ฐ€ ์žˆ์œผ๋ฉด ๊ทธ๋ž˜ํ”„๋ฅผ ์—ฝ๋‹ˆ๋‹ค.
  • ์ƒ์„ฑ ํŒŒ์ผ์˜ ์ฒซ ์ค„์€ -- ๊ทธ๋ž˜ํ”„์—์„œ ๋งŒ๋“  ํŒŒ์ผ: <๊ทธ๋ž˜ํ”„ ๊ฒฝ๋กœ> ์ž…๋‹ˆ๋‹ค. ์ด ์ค„์ด ์—†๋Š” ํŒŒ์ผ(์†์œผ๋กœ ์“ด ํŒŒ์ผ)์€ ๋ฎ์–ด์“ฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ๋…ธ๋“œ๋Š” ์ด๋ฒคํŠธ(init, update, render, destroy), ํ๋ฆ„(์กฐ๊ฑด ๋ถ„๊ธฐ, ๊ฐ’ ๋ถ„๊ธฐ, ๋ฐ˜๋ณต), ์ƒํƒœ์™€ ์ง€์—ญ ๋ณ€์ˆ˜์™€ ๋งค๊ฐœ๋ณ€์ˆ˜, ์˜ค๋ธŒ์ ํŠธ์™€ props, ์”ฌ, ์ˆ˜ํ•™, ๋น„๊ต์™€ ๋…ผ๋ฆฌ, ํ…์ŠคํŠธ, ์—”์ง„ API(์ž…๋ ฅ, ์†Œ๋ฆฌ, ํ™”๋ฉด ํฌ๊ธฐ ๋“ฑ 22๊ฐœ)์ž…๋‹ˆ๋‹ค.
  • ๊ฒŒ์ž„์˜ ๋„์šฐ๋ฏธ ๋ชจ๋“ˆ์€ ๋…ธ๋“œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(*.nodes.json)๋กœ ๋…ธ๋“œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๋‘ ์–ธ์–ด์˜ ์ด๋ฆ„์„ ์ ์–ด ๋‘๋ฉด Lua ๋Š” flappy.GRAVITY, Ruby ๋Š” FlappyCommon::GRAVITY ๋กœ ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ๊ณต์œ  ์ƒํƒœ ํ‘œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์— ํ•„๋“œ(fields)๋ฅผ ์ ์–ด ๋‘๋ฉด ๊ทธ ์ƒํƒœ๋ฅผ ์“ฐ๋Š” ๊ทธ๋ž˜ํ”„๋“ค์ด ํ•„๋“œ๋ฅผ ๋‹ค์‹œ ์ ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์˜ˆ: ํ”Œ๋ž˜ํ”ผ bird ์ „์ฒด๋ฅผ ๋…ธ๋“œ 80๊ฐœ๋กœ ์ ์€ ๊ทธ๋ž˜ํ”„๊ฐ€ packages/core/src/graph/fixtures/flappy/ ์— ์žˆ๊ณ , ๋งŒ๋“  ์ฝ”๋“œ(bird.expected.lua, bird.expected.rb)๊ฐ€ ๊ทธ ์˜†์— ์žˆ์Šต๋‹ˆ๋‹ค.

๊ต์ฐจ ๊ฒ€์‚ฌ yarn test:engine-graph ๋Š” ๊ทธ๋ž˜ํ”„์—์„œ ๋งŒ๋“  ์ฝ”๋“œ๋ฅผ ์ง„์งœ ์—”์ง„์œผ๋กœ ๋Œ๋ฆฝ๋‹ˆ๋‹ค. ํ”Œ๋ž˜ํ”ผ๋Š” bird ๋ฅผ ๊ทธ๋ž˜ํ”„์˜ ๊ฒƒ์œผ๋กœ ๋ฐ”๊ฟ”๋„ ์†์œผ๋กœ ์“ด bird ์™€ ๊ฐ™์€ ํŒ(์ƒํƒœ ์ „์ด, ์ ์ˆ˜, ์š”์•ฝ)์ด ๋‚˜์˜ค๋Š”์ง€, ์ƒ˜ํ”Œ๋Ÿฌ ๊ทธ๋ž˜ํ”„๋Š” ๋…ธ๋“œ๋งˆ๋‹ค ์ฐ์€ ๊ฐ’์ด ๊ธฐ๋Œ€๊ฐ’๊ณผ ๊ฐ™๊ณ  Lua ์™€ Ruby ๊ฐ€ ๊ฐ™์€์ง€ ๋ด…๋‹ˆ๋‹ค.

INITIAL2D_DIR=../Initial2D yarn test:engine-graph   # ์—”์ง„ ๋นŒ๋“œ(build/Initial2D)๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค
KEEP_WORKDIR=1 yarn test:engine-graph               # ์ž„์‹œ ํ”„๋กœ์ ํŠธ๋ฅผ ๋‚จ๊ธด๋‹ค

๋งต ํŽธ์ง‘ (E3)

resources/maps/*.json(์—”์ง„ ๋งต ํฌ๋งท v1, v2)์„ ์—ด๋ฉด ๋งต ๋ทฐ๊ฐ€ ๋œน๋‹ˆ๋‹ค. ์•Œ๋ฐ๋ฐ”๋ž€ ์ˆฒ(256x28 ์นธ)์ฒ˜๋Ÿผ ์ƒ์„ฑ๊ธฐ๊ฐ€ ๋งŒ๋“  ๋งต๋„ ์‹ค์ œ ํƒ€์ผ์…‹์œผ๋กœ ๋ณด์ด๊ณ , ๋ชฌ์Šคํ„ฐ์™€ ์ˆœ์ฐฐ ๋ฒ”์œ„, ํ”์ , ๊ตฌ๊ฐ„ ๊ฐ™์€ ๋ฐฐ์น˜๊ฐ€ ๋งต ์œ„์— ํ‘œ์‹์œผ๋กœ ๋‚˜์˜ต๋‹ˆ๋‹ค.

  • ์น ํ•˜๊ธฐ: ํŒ”๋ ˆํŠธ์—์„œ ํ•œ ์นธ์„ ๋ˆ„๋ฅด๊ฑฐ๋‚˜ ๋Œ์–ด์„œ ์—ฌ๋Ÿฌ ์นธ์„ ๊ณ ๋ฅด๊ณ  ํŽœ(B), ์‚ฌ๊ฐํ˜•(R), ์ฑ„์šฐ๊ธฐ(G), ์ง€์šฐ๊ฐœ(E), ์Šคํฌ์ด๋“œ(I)๋กœ ์น ํ•ฉ๋‹ˆ๋‹ค. ๋ถ“์งˆ ํ•œ ๋ฒˆ์ด ๋˜๋Œ๋ฆฌ๊ธฐ ํ•œ ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค. ์น ํ•  ๋ ˆ์ด์–ด๋Š” ๋ ˆ์ด์–ด ํŒจ๋„์—์„œ ๊ณ ๋ฅด๊ณ , ๊ฑฐ๊ธฐ์„œ ๋ณด์ด๊ธฐ์™€ ์ด๋ฆ„๊ณผ ์ถ”๊ฐ€, ์‚ญ์ œ, ์ˆœ์„œ๋„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.
  • ํ†ตํ–‰: ํ†ตํ–‰ ๋„๊ตฌ(C)๋กœ ์™ผ์ชฝ ํด๋ฆญ์€ ํ†ตํ–‰ ๋ถˆ๊ฐ€(1), ์˜ค๋ฅธ์ชฝ ํด๋ฆญ์ด๋‚˜ Alt๋Š” ํ†ตํ–‰ ๊ฐ€๋Šฅ(0)์ž…๋‹ˆ๋‹ค. ๋งต > ํ†ตํ–‰ ์˜ค๋ฒ„๋ ˆ์ด๋กœ ๊ฒน์ณ ๋ด…๋‹ˆ๋‹ค.
  • ์˜ค๋ธŒ์ ํŠธ: ์˜ค๋ธŒ์ ํŠธ ๋„๊ตฌ(V)๋กœ ๊ณ ๋ฅด๊ณ  ๋Œ์–ด ์˜ฎ๊น๋‹ˆ๋‹ค. ์ˆœ์ฐฐ ๋ฒ”์œ„ ์†์žก์ด์™€ ๋  ๊ฐ€์žฅ์ž๋ฆฌ๋„ ๋Œ๋ฆฝ๋‹ˆ๋‹ค. ๋งต ์˜ค๋ธŒ์ ํŠธ ํŒจ๋„์€ ํƒ€์ž…๋ณ„ ๋ชฉ๋ก๊ณผ ์ถ”๊ฐ€, ์ธ์ŠคํŽ™ํ„ฐ๋Š” ํ”„๋กœ์ ํŠธ์˜ resources/schema/map-objects.json์œผ๋กœ ๋งŒ๋“  ํผ๊ณผ ๊ฒ€์‚ฌ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ํƒ€์ž…๊ณผ ์นธ์€ ์Šคํ‚ค๋งˆ๊ฐ€ ์ •ํ•˜๋ฏ€๋กœ ์—๋””ํ„ฐ๋Š” ๋ชฌ์Šคํ„ฐ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ๋ชจ๋ฆ…๋‹ˆ๋‹ค. ํ•„์ˆ˜ ์นธ์ด ๋น„๋ฉด(๊ธ€ ์นธ์€ ๊ณต๋ฐฑ๋ฟ์ด์–ด๋„) ๊ฒ€์‚ฌ ๊ฒฐ๊ณผ์— ๋œน๋‹ˆ๋‹ค.
  • ํŽธ์ง‘ ๋ฉ”๋‰ด: ๋งต ํƒญ์—์„œ๋Š” ์ž˜๋ผ๋‚ด๊ธฐ, ๋ณต์‚ฌ, ๋ถ™์—ฌ๋„ฃ๊ธฐ, ๋ณต์ œ(Ctrl+D), ์‚ญ์ œ๊ฐ€ ๋งต ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค. ๋ถ™์ธ ๊ฒƒ๊ณผ ๋ณต์ œํ•œ ๊ฒƒ์€ ํ•œ ์นธ ์˜ค๋ฅธ์ชฝ์— ๋†“์ด๊ณ  y๋Š” ๊ทธ๋Œ€๋กœ๋ผ ๋ฐ”๋‹ฅ์— ์„  ๋ชฌ์Šคํ„ฐ์™€ ์‹œ์ž‘ ์ง€์ ์ด ๋ฐ”๋‹ฅ์— ๋‚จ์Šต๋‹ˆ๋‹ค. ์ˆœ์ฐฐ ๋ฒ”์œ„๋„ ๊ฐ™์ด ์˜ฎ๊ฒจ์ง€๊ณ , ๋งต ์˜ค๋ฅธ์ชฝ ๋์ด๋ฉด ์™ผ์ชฝ์œผ๋กœ ๊ฐ‘๋‹ˆ๋‹ค. ์ž˜๋ผ๋‚ด๊ณ  ๋ถ™์ด๋ฉด id๊ฐ€ ๊ทธ๋Œ€๋กœ๋ผ ์˜ฎ๊ธฐ๊ธฐ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค(์‹œ์ž‘ ์ง€์ ์€ start ๊ทธ๋Œ€๋กœ). ์”ฌ ์˜ค๋ธŒ์ ํŠธ์™€๋Š” ํด๋ฆฝ๋ณด๋“œ๊ฐ€ ๋”ฐ๋กœ์ž…๋‹ˆ๋‹ค.
  • ์ƒˆ ๋งต: ๋งต > ์ƒˆ ๋งต(Ctrl+Alt+M). ์ด๋ฆ„, ํฌ๊ธฐ, ํƒ€์ผ ํฌ๊ธฐ, ํƒ€์ผ์…‹(ํ”„๋กœ์ ํŠธ์˜ PNG), ๋ ˆ์ด์–ด ์ด๋ฆ„, ํ†ตํ–‰์„ ์ •ํ•˜๋ฉด resources/maps/<์ด๋ฆ„>.json์ด ์ƒ๊ธฐ๊ณ  ์—ด๋ฆฝ๋‹ˆ๋‹ค.
  • ํฌ๊ธฐ ๋ฐ”๊พธ๊ธฐ: ๋งต > ํฌ๊ธฐ ๋ฐ”๊พธ๊ธฐ, ๋˜๋Š” ๋งต ๋ทฐ ๋จธ๋ฆฌ ๋ ์˜ ํฌ๊ธฐ๋ฅผ ๋ˆ„๋ฆ…๋‹ˆ๋‹ค. ๊ธฐ์ค€์ (์•„ํ™‰ ์นธ)์— ๋”ฐ๋ผ ๋‚ด์šฉ์ด ์˜ฎ๊ฒจ์ง€๊ณ , ๋งต ๋ฐ–์œผ๋กœ ๋‚˜๊ฐ€๋Š” ์˜ค๋ธŒ์ ํŠธ๋Š” ์ง€์šฐ์ง€ ์•Š๊ณ  ์•Œ๋ ค ์ค๋‹ˆ๋‹ค.
  • ์ด ๋งต์—์„œ ์‹คํ–‰: ๋งต > ์ด ๋งต์—์„œ ์‹คํ–‰(Ctrl+F5, ๋ฐ์Šคํฌํ†ฑ ์•ฑ). ์Šคํ‚ค๋งˆ์˜ play.env๋ฅผ ์ฑ„์›Œ ์—”์ง„์„ ๋„์›๋‹ˆ๋‹ค. ์˜ค๋ธŒ์ ํŠธ๋ฅผ ํ•˜๋‚˜ ๊ณจ๋ž์œผ๋ฉด ๊ทธ ์ž๋ฆฌ(๋ฒ”์œ„๊ฐ€ ์žˆ๋Š” ๋ชฌ์Šคํ„ฐ๋Š” ๋ฒ”์œ„ ์ตœ์†Œ X์—์„œ 48px ์™ผ์ชฝ), ์•„๋‹ˆ๋ฉด ์ปค์„œ๋‚˜ ํ™”๋ฉด ๊ฐ€์šด๋ฐ์„œ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์•Œ๋ฐ๋ฐ”๋ž€์€ INITIAL2D_ALDEBARAN_STAGE์™€ INITIAL2D_ALDEBARAN_AT์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์Šคํ‚ค๋งˆ์˜ play์— "maps": ["aldebaran_*"]์ฒ˜๋Ÿผ ๋งต ์ด๋ฆ„ ๊ธ€๋กญ ๋ชฉ๋ก(*๋Š” ์•„๋ฌด ๊ธ€์ž์—ด, ?๋Š” ํ•œ ๊ธ€์ž)์„ ๋‘๋ฉด ๋งž๋Š” ๋งต์—์„œ๋งŒ ์—”์ง„์„ ๋„์›๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋งต์—์„œ๋„ ์—ฌ๊ธฐ์„œ ์‹คํ–‰๊ณผ Ctrl+F5๋Š” ์ผœ์ ธ ์žˆ๊ณ , ๋ˆ„๋ฅด๋ฉด ๋„์šฐ์ง€ ์•Š๊ณ  ์ด์œ ๋ฅผ ํ† ์ŠคํŠธ์™€ ์ฝ˜์†”์— ํ•œ ์ค„๋กœ ์•Œ๋ฆฝ๋‹ˆ๋‹ค. ๋ฉ”๋‰ด ํˆดํŒ์—๋„ ๊ทธ ์ด์œ ๊ฐ€ ๋ณด์ž…๋‹ˆ๋‹ค. ์—†์œผ๋ฉด ๋ชจ๋“  ๋งต์—์„œ ๋„์›๋‹ˆ๋‹ค.
  • ์ €์žฅ(Ctrl+S)์€ ์—”์ง„๊ณผ ๊ฐ™์€ ํ˜•์‹์ž…๋‹ˆ๋‹ค. 2์นธ ๋“ค์—ฌ์“ฐ๊ธฐ์— ํƒ€์ผ ๋ฐฐ์—ด์€ ๋งต ํ•œ ์ค„์ด ํ•œ ์ค„์ด๋ผ diff๊ฐ€ ์นธ ๋‹จ์œ„๋กœ ๋ณด์ด๊ณ , objects์™€ events์™€ ๋ชจ๋ฅด๋Š” ํ‚ค๋Š” ๊ทธ๋Œ€๋กœ ๋‚จ์Šต๋‹ˆ๋‹ค.
  • ๋งต ํƒญ์„ ์—ด๋ฉด ํŒ”๋ ˆํŠธ, ๋ ˆ์ด์–ด, ๋งต ์˜ค๋ธŒ์ ํŠธ ํŒจ๋„์ด ์—†์„ ๋•Œ ๋ถ™์Šต๋‹ˆ๋‹ค (์ง์ ‘ ๋‹ซ์€ ๊ฒƒ์€ ๋‹ค์‹œ ์—ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค). ์ฐฝ > ๋ ˆ์ด์•„์›ƒ > ํƒ€์ผ๋งต์€ ๋งต ํŽธ์ง‘์šฉ ๋ฐฐ์น˜์ž…๋‹ˆ๋‹ค.

์ธ์ˆ˜ ํ…Œ์ŠคํŠธ tests/e2e/aldebaran-map.spec.ts๋Š” ์—”์ง„ ์ €์žฅ์†Œ์˜ ์ˆฒ ๋งต์„ ์‚ฌ๋ณธ์œผ๋กœ ์—ด์–ด ํƒ€์ผ ์„ธ ์นธ๊ณผ ๋Š‘๋Œ€ ํ•˜๋‚˜๋ฅผ ๊ณ ์ณ ์ €์žฅํ•˜๊ณ , Ctrl+F5๊ฐ€ ๋„˜๊ธด ํ™˜๊ฒฝ ๋ณ€์ˆ˜์— INITIAL2D_ALDEBARAN_TRACE=1์„ ๋”ํ•ด ์—”์ง„์„ ํ—ค๋“œ๋ฆฌ์Šค๋กœ ๋Œ๋ฆฝ๋‹ˆ๋‹ค (Lua, ๋นŒ๋“œ์— mruby๊ฐ€ ์žˆ์œผ๋ฉด Ruby๋„). ์—”์ง„์ด ์ฐ๋Š” ์•Œ๋ฐ๋ฐ”๋ž€: ๋งต <๊ฒฝ๋กœ> ํƒ€์ผ <๊ฒ€์‚ฌํ•ฉ> ์ค„์˜ ๊ฒ€์‚ฌํ•ฉ์ด ์ €์žฅํ•œ ํŒŒ์ผ์—์„œ ๊ฐ™์€ ์‹(๋ ˆ์ด์–ด ์ˆœ์„œ์™€ ์นธ ์ˆœ์„œ๋Œ€๋กœ (ํ•ฉ * 31 + gid) mod 1000000007)์œผ๋กœ ๊ณ„์‚ฐํ•œ ๊ฐ’๊ณผ ๊ฐ™๊ณ  ์›๋ณธ์˜ ๊ฐ’๊ณผ ๋‹ฌ๋ผ์•ผ ํ•˜๋ฉฐ, ์•Œ๋ฐ๋ฐ”๋ž€: ๋ชฌ์Šคํ„ฐ ... ์ค„์—์„œ ์˜ฎ๊ธด ๋Š‘๋Œ€๊ฐ€ ์ƒˆ x์™€ ์ˆœ์ฐฐ ๋ฒ”์œ„์—ฌ์•ผ ํ†ต๊ณผํ•ฉ๋‹ˆ๋‹ค. ์—”์ง„์ด ๊ณ ์น˜์ง€ ์•Š์€ ๋งต์„ ์ฝ์œผ๋ฉด ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค. ์—”์ง„ ์ €์žฅ์†Œ๋Š” ๊ณ ์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

yarn build
INITIAL2D_DIR=../Initial2D yarn test:e2e tests/e2e/aldebaran-map.spec.ts                  # ์—”์ง„ ๋นŒ๋“œ(build/Initial2D)๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค
KEEP_WORKDIR=1 INITIAL2D_DIR=../Initial2D yarn test:e2e tests/e2e/aldebaran-map.spec.ts   # ์‚ฌ๋ณธ ํ”„๋กœ์ ํŠธ์™€ ์Šคํฌ๋ฆฐ์ƒท์„ ๋‚จ๊ธด๋‹ค

์—”์ง„ ์‹คํ–‰ ํŒŒ์ผ์ด๋‚˜ ์ˆฒ ๋งต์ด ์—†์œผ๋ฉด ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค. ์—”์ง„์€ INITIAL2D_ALDEBARAN_AT์œผ๋กœ ์‹œ์ž‘ํ•  ๋•Œ๋งˆ๋‹ค ์•Œ๋ฐ๋ฐ”๋ž€: ์‹œ์ž‘ x <x> (y <y>)๋ฅผ ์ฐ๊ณ (์—”์ง„ PR #47 ์ดํ›„), INITIAL2D_ALDEBARAN_TRACE=1์ด๋ฉด ๋งต๊ณผ ๋ชฌ์Šคํ„ฐ ๊ฒ€์ˆ˜ ์ค„์„ ์ฐ๋Š” ํŒ(์—”์ง„ PR #48 ์ดํ›„)์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฒ€์ˆ˜ ์ค„์ด ์—†๋Š” ์—”์ง„์ด๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.

๊ต์ฐจ ๊ฒ€์‚ฌ yarn test:engine-map์€ ๋งต ํŽธ์ง‘์ด ์—”์ง„๊ณผ ๋งž๋Š”์ง€ ์„ธ ๊ฐ€์ง€๋กœ ๋ด…๋‹ˆ๋‹ค. ํŽธ์ง‘์€ ๋งต ๋ทฐ์˜ ๋„๊ตฌ์™€ ๋งต ๋ฌธ์„œ, ์”ฌ ๋ฌธ์„œ๋กœ ํ•˜๊ณ  ์ €์žฅ๋„ ์•ฑ๊ณผ ๊ฐ™์€ ํ•จ์ˆ˜๋กœ ํ•ฉ๋‹ˆ๋‹ค.

  • ํ†ตํ–‰: ํƒ€์ผ๋งต ํ…œํ”Œ๋ฆฟ์˜ ๋งต์—์„œ ํ†ตํ–‰์„ ๋ง‰๊ณ  ํ’€์–ด ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์”ฌ์— ํƒ์นจ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถ™์—ฌ ์—”์ง„์˜ IsPassable(Ruby๋Š” passable?)์„ ์นธ๋งˆ๋‹ค ์ฐ๊ฒŒ ํ•˜๊ณ , ์ €์žฅํ•œ ํŒŒ์ผ๊ณผ ์—๋””ํ„ฐ ๋ชจ๋ธ๊ณผ ์นธ๋งˆ๋‹ค ๊ฐ™์€์ง€ ๋ด…๋‹ˆ๋‹ค. Lua์™€ Ruby ๋‘˜ ๋‹ค ๋Œ๋ฆฝ๋‹ˆ๋‹ค.
  • ์ƒˆ ๋งต ๊ณจ๋“ : ์ƒˆ ๋งต ๋Œ€ํ™”์ƒ์ž์™€ ๊ฐ™์€ ํ•จ์ˆ˜๋กœ ๋งต์„ ๋งŒ๋“ค๊ณ  ๋‘ ๋ ˆ์ด์–ด๋ฅผ ์น ํ•ด ์”ฌ์˜ ํƒ€์ผ๋งต ์˜ค๋ธŒ์ ํŠธ์— ๊ฒ๋‹ˆ๋‹ค. ์—”์ง„์˜ ํ”„๋ ˆ์ž„ 30์„ ์ €์žฅํ•œ ๋งต๊ณผ ํƒ€์ผ์…‹์œผ๋กœ ๊ทธ๋ฆฐ ๊ธฐ์ค€๊ณผ ๊ฒฌ์ค๋‹ˆ๋‹ค. ๊ทœ์น™์€ ์ˆฒ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค (์ฑ„๋„๋งˆ๋‹ค ยฑ8, ๋ ˆ์ด์–ด๋งˆ๋‹ค, ์น ํ•œ ์นธ๋งˆ๋‹ค). Lua์™€ Ruby ๋‘˜ ๋‹ค ๋Œ๋ฆฝ๋‹ˆ๋‹ค.
  • ํ•ญ๊ตฌ ๋งˆ์„: ์—”์ง„ ์ €์žฅ์†Œ ์ถ”์  ํŒŒ์ผ์˜ ์‚ฌ๋ณธ์—์„œ port_town.json์„ ์ด๋ฒคํŠธ ๋ ˆ์ด์–ด๊ฐ€ ๋ถ™์€ ์ฑ„๋กœ ์—ด๊ณ , ๊ณจ๋“  ํ™”๋ฉด ๋ฐ–์˜ ํ•œ ์นธ์„ ์น ํ•ด ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ํŒŒ์ผ์€ ๊ทธ ์นธ๋งŒ ๋‹ฌ๋ผ์•ผ ํ•˜๊ณ , ์—”์ง„์˜ ์ธ์ˆ˜ ์‹œ๋‚˜๋ฆฌ์˜ค(run_engine_tests.py --only=rpgdemo_scene)๊ฐ€ ์น ํ•˜๊ธฐ ์ „๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๋กœ ํ†ต๊ณผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ง ์ƒ์ž ๋Œ€์‚ฌ๊ฐ€ ์ €์žฅํ•œ ์ด๋ฒคํŠธ์˜ ๊ธ€์ธ์ง€, ๋Ÿฌ๋„ˆ๊ฐ€ ๋ณด๋Š” ๋งต ํ™”๋ฉด ์…‹(town, bag, wall)์ด ์น ํ•˜๊ธฐ ์ „๊ณผ ํ”ฝ์…€๊นŒ์ง€ ๊ฐ™์€์ง€๋„ ๋ด…๋‹ˆ๋‹ค. ๋Ÿฌ๋„ˆ์˜ ๊ณจ๋“  ๊ฒ€์‚ฌ๋Š” ๋‹ค๋ฅธ ํ”ฝ์…€ 2%๊นŒ์ง€ ๋ฐ›์•„์„œ ํ•œ ์นธ ์ฐจ์ด๋Š” ๋ณด์ง€ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

ํŒ๋งˆ๋‹ค ๋Œ€์กฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์—”์ง„์—๊ฒŒ๋งŒ ๊ณ ์น˜๊ธฐ ์ „ ๋งต, ์น ํ•˜๊ธฐ ์ „ ๋งต, deco๋ฅผ ๋น„์šด ๋งต์„ ์ฃผ๋ฉด ํŒ์ •์ด ๋–จ์–ด์ง€๋Š”์ง€ ๋ณด๊ณ , ๋งˆ์„ ์ฒซ ํ™”๋ฉด ์•ˆ์˜ ์นธ์„ ์น ํ•˜๋ฉด ๊ทธ ํ™”๋ฉด์ด ๊ทธ ์นธ ์ž๋ฆฌ์—์„œ๋งŒ ๋‹ฌ๋ผ์ง€๋Š”์ง€ ๋ด…๋‹ˆ๋‹ค. ์—”์ง„ ์‹คํ–‰ ํŒŒ์ผ์ด ์—†์œผ๋ฉด SKIP: ํ•œ ์ค„์„ ์ฐ๊ณ  ํ†ต๊ณผํ•ฉ๋‹ˆ๋‹ค. INITIAL2D_DIR์ด git ์ €์žฅ์†Œ๊ฐ€ ์•„๋‹ˆ๋ฉด ํ•ญ๊ตฌ ๋งˆ์„๋งŒ ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค. ์—”์ง„ ์ €์žฅ์†Œ๋Š” ๊ณ ์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

INITIAL2D_DIR=../Initial2D yarn test:engine-map   # ์—”์ง„ ๋นŒ๋“œ(build/Initial2D)์™€ python3, Pillow๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค
KEEP_WORKDIR=1 yarn test:engine-map               # ์ž„์‹œ ํ”„๋กœ์ ํŠธ์™€ ์—”์ง„ ์‚ฌ๋ณธ์„ ๋‚จ๊ธด๋‹ค

์•ฑ์— ์‹ฃ๋Š” ์—”์ง„

์„ค์น˜๋ณธ์€ ์—”์ง„ ์‹คํ–‰ ํŒŒ์ผ ํ•˜๋‚˜๋ฅผ ์•ฑ ์•ˆ์— ์‹ฃ์Šต๋‹ˆ๋‹ค. ์—”์ง„ ์ €์žฅ์†Œ์˜ tools/build_dist.sh ๋กœ ๋งŒ๋“  ๋ฐฐํฌ์šฉ ๋นŒ๋“œ์ด๊ณ , ์—๋””ํ„ฐ๊ฐ€ ๋ฌถ์ด๋Š” ์—”์ง„ ์ปค๋ฐ‹์€ engine-pin.json ์— ์žˆ์Šต๋‹ˆ๋‹ค.

# ํ•€์ด ์—”์ง„์˜ ๊ณต๊ฐœ ๋ฆด๋ฆฌ์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋ฉด (engineTag) ์—”์ง„ ๋นŒ๋“œ ์—†์ด ๋ฆด๋ฆฌ์Šค์—์„œ ๋ฐ›๋Š”๋‹ค
yarn engine:fetch                                     # ํ•€์˜ sha256 ์œผ๋กœ ํ™•์ธํ•œ๋‹ค

# ์—”์ง„์„ ์ง์ ‘ ๋งŒ๋“ค ๋•Œ: ์—”์ง„ ์ €์žฅ์†Œ์—์„œ (ํ•€์˜ ์ปค๋ฐ‹์œผ๋กœ ์ฒดํฌ์•„์›ƒํ•œ ๋’ค)
tools/build_dist.sh                                   # dist/Initial2D-<ํŠธ๋ฆฌํ”Œ>, dist/engine-dist.json

# ์—๋””ํ„ฐ์—์„œ
yarn engine:fetch --from ../Initial2D/dist            # src-tauri/binaries/ ์™€ src-tauri/licenses/engine/ ์œผ๋กœ ๋ฐ›๋Š”๋‹ค
yarn luals:fetch                                      # ์•ฑ์— ์‹ฃ๋Š” ์–ธ์–ด ์„œ๋ฒ„ LuaLS ๋ฅผ src-tauri/luals/ ๋กœ (์„ค์น˜๋ณธ ๋นŒ๋“œ ์ „์—)
node scripts/check-sidecar.mjs src-tauri/binaries/Initial2D-aarch64-apple-darwin
yarn tauri dev --config src-tauri/tauri.sidecar.conf.json     # ์•ฑ์— ๋“  ์—”์ง„์œผ๋กœ ๊ฐœ๋ฐœ ๋นŒ๋“œ
yarn tauri build --config src-tauri/tauri.dist.conf.json --config src-tauri/tauri.sidecar.conf.json   # ์„ค์น˜๋ณธ (.app ๊ณผ dmg)
yarn engine:check                                     # ํ…œํ”Œ๋ฆฟ, ์›น ์—”์ง„, RPG ํ”ฝ์Šค์ฒ˜, ๋ฐ›์€ ์—”์ง„์ด ํ•€์˜ ์ปค๋ฐ‹์ธ์ง€
  • ์„ค์น˜๋ณธ ๋นŒ๋“œ๋Š” ๋ฎ์–ด์“ฐ๊ธฐ ์„ค์ • ๋‘˜์„ ์ด ์ˆœ์„œ๋กœ ์ค๋‹ˆ๋‹ค. tauri.dist.conf.json ์ด ์†Œ์Šค๋งต ์—†๋Š” ํ”„๋ŸฐํŠธ(yarn build:desktop)์™€ ์ œ3์ž ๊ณ ์ง€(licenses/)์™€ ์–ธ์–ด ์„œ๋ฒ„(luals/, ๋จผ์ € yarn luals:fetch)๋ฅผ, tauri.sidecar.conf.json ์ด ์•ฑ์— ๋“  ์—”์ง„๊ณผ engine.json ์„ ์‹ฃ์Šต๋‹ˆ๋‹ค. --bundles ๋ฅผ ์ฃผ์ง€ ์•Š์œผ๋ฉด .app ๊ณผ ํ•จ๊ป˜ dmg ๋„ ๋งŒ๋“ค๊ณ , ๊ทธ๋•Œ Finder ์ฐฝ์ด ์ž ๊น ๋œน๋‹ˆ๋‹ค. .app ๋งŒ ๋งŒ๋“ค๋ ค๋ฉด --bundles app ์„ ๋ถ™์ž…๋‹ˆ๋‹ค.

  • --from ํด๋”๋Š” ์—”์ง„์˜ dist/ ๋‚˜ dist.yml ์‚ฐ์ถœ๋ฌผ ํด๋”์ž…๋‹ˆ๋‹ค. ์—”์ง„ ์ปค๋ฐ‹์ด ํ•€๊ณผ ๋‹ค๋ฅด๋ฉด ๋ฐ›์ง€ ์•Š๊ณ , ๋‹ค๋ฅธ ์—”์ง„์„ ์ž ๊น ์‹œํ—˜ํ•  ๋•Œ๋Š” --any-commit ์„ ๋ถ™์ž…๋‹ˆ๋‹ค. --target <ํŠธ๋ฆฌํ”Œ> ๋กœ ๋‹ค๋ฅธ ํƒ€๊นƒ์„ ๋ฐ›๊ณ , Windows ํƒ€๊นƒ์€ ์—”์ง„์ด ์—†์–ด ๊ณ ์ง€๋งŒ ๋ฐ›์Šต๋‹ˆ๋‹ค. --templates <๋นˆ ํด๋”> ๋Š” ์—”์ง„ ๋Œ€์‹  ํ…œํ”Œ๋ฆฟ ๋ฌถ์Œ(Initial2D-templates.zip)์„ ํ’‰๋‹ˆ๋‹ค.

  • ๋ฐ›์€ ํŒŒ์ผ์€ gitignore ์ž…๋‹ˆ๋‹ค: src-tauri/binaries/Initial2D-<ํŠธ๋ฆฌํ”Œ>, src-tauri/binaries/engine.json(ํŒ ์ •๋ณด. ์ƒํƒœ ๋ฐ” ํˆดํŒ๊ณผ ์„ค์ •์— "์•ฑ์— ๋“  ์—”์ง„ (cac4b94, lua mruby)" ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค), src-tauri/licenses/engine/THIRD-PARTY.md.

  • check-sidecar.mjs ๋Š” ๋ฐ›์€ ํŒŒ์ผ์ด๋‚˜ ๋นŒ๋“œํ•œ .app ์„ ๋ฐ›์•„ ๋™์  ์˜์กด(Homebrew ๊ฒฝ๋กœ๊ฐ€ ์—†๋Š”์ง€), --features, --version ์˜ ์ปค๋ฐ‹์ด ํ•€๊ณผ engine.json ์— ๊ฐ™์€์ง€, ๋ชจ๋ฅด๋Š” ์ธ์ž์— ์ข…๋ฃŒ ์ฝ”๋“œ 2 ์ธ์ง€ ๋ด…๋‹ˆ๋‹ค. ์—”์ง„์€ ๋ฒ„๋ฆฌ๋Š” ์ž„์‹œ ํด๋”์—์„œ ์ฐฝ ์—†์ด ๋•๋‹ˆ๋‹ค. engine.json ์€ ๋ฐ›์€ ํŒŒ์ผ ์˜†(src-tauri/binaries/engine.json)์ด๋‚˜ ์•ฑ์˜ Contents/Resources/engine/ ์—์„œ ์ฐพ๊ณ , ์—†์œผ๋ฉด ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๊ณณ์— ์žˆ์œผ๋ฉด --engine-json <๊ฒฝ๋กœ>, ์—”์ง„ ์‹คํ–‰ ํŒŒ์ผ๋งŒ ๋ณผ ๋•Œ๋Š” --no-engine-json ์„ ๋ถ™์ž…๋‹ˆ๋‹ค.

  • ์—”์ง„์„ ์˜ฌ๋ฆด ๋•Œ๋Š” engine-pin.json ์˜ engineCommit ์„ ๋ฐ”๊พธ๊ณ , ์—”์ง„ ์ €์žฅ์†Œ๋ฅผ ๊ทธ ์ปค๋ฐ‹์œผ๋กœ ์ฒดํฌ์•„์›ƒํ•ด yarn sync:templates, yarn sync:engine-web, yarn sync:rpg ๋ฅผ ๋‹ค์‹œ ๋Œ๋ฆฐ ๋’ค yarn engine:check ๋กœ ๋งž์ถฐ์กŒ๋Š”์ง€ ๋ด…๋‹ˆ๋‹ค. ciEngineRef ๋Š” ์ƒˆ ์—”์ง„ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•œ PR ์ด ์ž ์‹œ ์“ฐ๋Š” ์นธ์ด๋ผ ๋ฆด๋ฆฌ์Šค ์ „์—๋Š” ๋น„์›๋‹ˆ๋‹ค.

  • ๊ทธ ์ปค๋ฐ‹์— ์—”์ง„ ํƒœ๊ทธ์™€ ๊ณต๊ฐœ ๋ฆด๋ฆฌ์Šค๊ฐ€ ์žˆ์œผ๋ฉด yarn engine:pin <ํƒœ๊ทธ> ๋กœ ํ•€์„ ๋ฆด๋ฆฌ์Šค์— ๋ฌถ์Šต๋‹ˆ๋‹ค. ๋ฆด๋ฆฌ์Šค์˜ engine-dist.json ๊ณผ SHA256SUMS.txt ๋ฅผ ๋ฐ›์•„ engineTag ์™€ ์ž์‚ฐ(ํƒ€๊นƒ๋ณ„ ์—”์ง„, ํ…œํ”Œ๋ฆฟ ๋ฌถ์Œ, ์ œ3์ž ๊ณ ์ง€)์˜ sha256 ์„ ์ ์Šต๋‹ˆ๋‹ค. ๋ฆด๋ฆฌ์Šค์˜ ์ปค๋ฐ‹์ด ํ•€๊ณผ ๋‹ค๋ฅด๋ฉด ์“ฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํด๋”์—์„œ ์ฝ์œผ๋ ค๋ฉด --from <ํด๋”> ๋ฅผ ๋ถ™์ž…๋‹ˆ๋‹ค.

์„ค์น˜ ํŒŒ์ผ๊ณผ ์ž๊ฐ€ ๊ฒ€์‚ฌ

์„ค์น˜ ํŒŒ์ผ์€ GitHub Actions ์˜ release ์›Œํฌํ”Œ๋กœ๊ฐ€ ๋งŒ๋“ญ๋‹ˆ๋‹ค. macOS arm64 dmg, Linux AppImage ์™€ deb, Windows NSIS ์ž…๋‹ˆ๋‹ค. ์—”์ง„์€ engine-pin.json ์˜ ์ปค๋ฐ‹์œผ๋กœ ์›Œํฌํ”Œ๋กœ ์•ˆ์—์„œ ๋นŒ๋“œํ•ด ์‹ฃ๊ณ , ๋งŒ๋“  ์„ค์น˜๋ณธ์ด ์Šค์Šค๋กœ ์ƒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด ๋Œ๋ ค ๋ณธ ๋’ค ๋ฒˆ๋“ค๊ณผ SHA256SUMS.txt ๋ฅผ ์‚ฐ์ถœ๋ฌผ๋กœ ์˜ฌ๋ฆฝ๋‹ˆ๋‹ค. Actions ํƒญ์—์„œ release ๋ฅผ ์ˆ˜๋™์œผ๋กœ ๋Œ๋ฆฌ๋ฉด(dry run) ์‚ฐ์ถœ๋ฌผ๋งŒ ๋‚˜์˜ค๊ณ , v* ํƒœ๊ทธ๋ฅผ ๋ฐ€๋ฉด ์ดˆ์•ˆ ๋ฆด๋ฆฌ์Šค๊นŒ์ง€ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๊ณต๊ฐœ๋Š” ์ง์ ‘ ํ•ฉ๋‹ˆ๋‹ค. Windows ํŒ์—๋Š” ์—”์ง„์ด ์—†์–ด F5 ๊ฐ€ ์—๋””ํ„ฐ ์•ˆ์—์„œ ๋•๋‹ˆ๋‹ค.

์„ค์น˜ ํŒŒ์ผ์€ ๊ทธ ์‹คํ–‰์˜ Summary ์•„๋ž˜ Artifacts ์—์„œ ๋ฐ›์Šต๋‹ˆ๋‹ค (InitialEditor-<์ปค๋ฐ‹> ํ•˜๋‚˜์— ์ „๋ถ€์™€ SHA256SUMS.txt). ์„œ๋ช…ํ•˜์ง€ ์•Š์€ ์•ฑ์ด๋ผ ์ฒ˜์Œ ํ•œ ๋ฒˆ ๋ง‰ํž™๋‹ˆ๋‹ค.

  • macOS (Apple Silicon๋งŒ): dmg ๋ฅผ ์—ด์–ด InitialEditor ๋ฅผ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ํด๋”๋กœ ์˜ฎ๊น๋‹ˆ๋‹ค. ์ฒ˜์Œ ์—ด ๋•Œ ๋ง‰ํžˆ๋ฉด ์‹œ์Šคํ…œ ์„ค์ • > ๊ฐœ์ธ์ •๋ณด ๋ณดํ˜ธ ๋ฐ ๋ณด์•ˆ์—์„œ "๊ทธ๋ž˜๋„ ์—ด๊ธฐ", ๋˜๋Š” xattr -dr com.apple.quarantine /Applications/InitialEditor.app
  • Windows: ์„ค์น˜ ํŒŒ์ผ์„ ์—ด๋ฉด SmartScreen ์ด ๋ง‰์Šต๋‹ˆ๋‹ค. "์ถ”๊ฐ€ ์ •๋ณด" ๋ฅผ ๋ˆŒ๋Ÿฌ "์‹คํ–‰". ์‚ฌ์šฉ์ž ํด๋”์— ์„ค์น˜๋˜์–ด ๊ด€๋ฆฌ์ž ๊ถŒํ•œ์€ ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค
  • Linux: AppImage ๋Š” chmod +x InitialEditor_*.AppImage ๋’ค ์‹คํ–‰ (FUSE 2 ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค). deb ๋Š” sudo apt install ./InitialEditor_*.deb

๊ฐ™์€ ์•ˆ๋‚ด๊ฐ€ docs/releases/first-open.md ์— ์žˆ๊ณ , ์ดˆ์•ˆ ๋ฆด๋ฆฌ์Šค ๋ณธ๋ฌธ ๋งจ ์œ„์— ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.

yarn version:set 2.0.0-alpha.1    # ๋ฃจํŠธ์™€ packages/*, Cargo.toml, Cargo.lock ์˜ ํŒ์„ ํ•œ๊บผ๋ฒˆ์— ๋ฐ”๊พธ๊ณ  yarn install
yarn version:check                # ํŒ์ด ํ•œ ๊ฐ€์ง€์ธ์ง€ (--tag v<ํŒ>, --bundles <๋ฒˆ๋“ค ํด๋”> ๋Š” ๋ฆด๋ฆฌ์Šค ์›Œํฌํ”Œ๋กœ๊ฐ€ ์“ด๋‹ค)
yarn licenses                     # src-tauri/licenses/THIRD-PARTY-editor.md ๋ฅผ ๋‹ค์‹œ ์“ด๋‹ค (์˜์กด์„ฑ์ด ๋ฐ”๋€Œ๋ฉด. CI ๋Š” --check)
yarn build:desktop                # ์†Œ์Šค๋งต ์—†๋Š” ํ”„๋ŸฐํŠธ (๋ฆด๋ฆฌ์Šค ๋ฒˆ๋“ค์ด ์“ด๋‹ค)

# ์ด ์ปดํ“จํ„ฐ์—์„œ ์„ค์น˜๋ณธ์„ ๋งŒ๋“ค์–ด ์ž๊ฐ€ ๊ฒ€์‚ฌ
yarn engine:fetch --from ../Initial2D/dist
yarn luals:fetch
yarn tauri build --bundles app --config src-tauri/tauri.dist.conf.json --config src-tauri/tauri.sidecar.conf.json
yarn selftest:app src-tauri/target/release/bundle/macos/InitialEditor.app
yarn selftest:app <์•ฑ> --forest ../Initial2D     # ์•Œ๋ฐ๋ฐ”๋ž€ ์ˆฒ์— ํ•œ ์นธ์„ ์น ํ•ด ๊ฒŒ์ž„ ํ™”๋ฉด๊ณผ ๊ฒฌ์ฃผ๋Š” ๊ฒƒ๊นŒ์ง€
yarn selftest:app <์•ฑ> --rpg ../Initial2D        # ํ•ญ๊ตฌ ๋งˆ์„์˜ ์ด๋ฒคํŠธ ๋ ˆ์ด์–ด์™€ ์ด๋ฒคํŠธ ์•ž์—์„œ ์‹คํ–‰, ์ž๋™ ์žฌ์ƒ๊นŒ์ง€
  • yarn selftest:app ์€ ์ฐฝ์„ ๋„์šฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์•ฑ์„ ์ž๊ฐ€ ๊ฒ€์‚ฌ ๋ชจ๋“œ(INITIAL_EDITOR_SELFTEST=<๊ณ„ํš ํŒŒ์ผ>)๋กœ ๋„์šฐ๋ฉด, ์•ฑ์— ๋“  ํ…œํ”Œ๋ฆฟ์œผ๋กœ ํ”Œ๋ž˜ํ”ผ Lua, ํ”Œ๋ž˜ํ”ผ Ruby, ํƒ€์ผ๋งต ํ”„๋กœ์ ํŠธ๋ฅผ ์ž„์‹œ ํด๋”์— ๋งŒ๋“ค๊ณ , ํƒ€์ผ๋งต์€ ๋งต ๋ฌธ์„œ๋กœ ํ•œ ์นธ์„ ์น ํ•ด ์ €์žฅํ•œ ๋’ค, ์…‹ ๋‹ค ์•ฑ์— ๋“  ์—”์ง„์œผ๋กœ ๋Œ๋ฆฝ๋‹ˆ๋‹ค. ํ”Œ๋ž˜ํ”ผ Lua ์—์„œ๋Š” ์•ฑ์— ๋“  LuaLS ๊ฐ€ ๋œจ๊ณ  ์ง„์ž… ์Šคํฌ๋ฆฝํŠธ์˜ Json. ๋’ค ์™„์„ฑ๊ณผ ํ˜ธ๋ฒ„์— Load ๊ฐ€ ๋‚˜์˜ค๋Š”์ง€๋„ ๋ด…๋‹ˆ๋‹ค. ๋๋‚˜๋ฉด scripts/selftest-check.mjs ๊ฐ€ ์‹คํ–‰๋งˆ๋‹ค ๋‚จ์€ ์ „์ฒด ๋กœ๊ทธ์™€ ์Šคํฌ๋ฆฐ์ƒท์œผ๋กœ ํŒ์ •ํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—… ํด๋”(๋ณด๊ณ ์„œ, ๋กœ๊ทธ, ์Šคํฌ๋ฆฐ์ƒท)๋Š” ์ง€์šฐ์ง€ ์•Š๊ณ  ๊ฒฝ๋กœ๋ฅผ ์ฐ์Šต๋‹ˆ๋‹ค.
  • ์ž๊ฐ€ ๊ฒ€์‚ฌ๋Š” ์„ค์ •, ์ตœ๊ทผ ํ”„๋กœ์ ํŠธ, ๋ ˆ์ด์•„์›ƒ, ์ฐฝ ์œ„์น˜, ์›น๋ทฐ ์ €์žฅ์†Œ๋ฅผ ์ฝ์ง€๋„ ์“ฐ์ง€๋„ ์•Š์Šต๋‹ˆ๋‹ค. ํ™•์ธ ์ฐฝ์ด ๋œจ๊ฑฐ๋‚˜ ์›น๋ทฐ ๋ณด์•ˆ ์ •์ฑ…(CSP) ์œ„๋ฐ˜์ด ์žˆ์œผ๋ฉด ์‹คํŒจ์ž…๋‹ˆ๋‹ค.
  • --forest <์—”์ง„ ์ €์žฅ์†Œ> ๋Š” ์ˆฒ ๋งต์˜ ์‚ฌ๋ณธ์„ ๋งต ๋ทฐ๋กœ ์—ด์–ด deco ๋ ˆ์ด์–ด์˜ ๋นˆ ์นธ ํ•˜๋‚˜๋ฅผ ์น ํ•ด ์ €์žฅํ•˜๊ณ  ์•ฑ์— ๋“  ์—”์ง„์œผ๋กœ ๋Œ๋ฆฐ ๋’ค, ๊ฒŒ์ž„ ํ™”๋ฉด์„ ๋งต ๋ทฐ์™€ ๊ฒฌ์ฃผ๊ณ  ์ €์žฅํ•œ ๋งต๊ณผ ํƒ€์ผ์…‹์œผ๋กœ ์ง์ ‘ ๊ทธ๋ฆฐ ๊ธฐ์ค€๊ณผ๋„ ๊ฒฌ์ค๋‹ˆ๋‹ค. ๋ ˆ์ด์–ด๋งˆ๋‹ค, ์น ํ•œ ์นธ๊นŒ์ง€ ๊ฒŒ์ž„ ํ™”๋ฉด์— ์žˆ์–ด์•ผ ํ†ต๊ณผํ•ฉ๋‹ˆ๋‹ค (๊ฒŒ์ž„์ด ๋ ˆ์ด์–ด ํ•˜๋‚˜๋ฅผ ๋นผ๊ณ  ๊ทธ๋ฆฌ๊ฑฐ๋‚˜ ์น ํ•˜๊ธฐ ์ „ ๋งต์„ ๋Œ๋ฆฌ๋ฉด ์‹คํŒจ).
  • --rpg <์—”์ง„ ์ €์žฅ์†Œ> ๋Š” ํ•ญ๊ตฌ ๋งˆ์„(port_town.json)์˜ ์‚ฌ๋ณธ์„ ๋งต ๋ทฐ๋กœ ์—ด์–ด RPG ํ™•์žฅ์ด ๋ถ™์ธ ์ด๋ฒคํŠธ ๋ ˆ์ด์–ด์™€ ๋ทฐ๊ฐ€ ๊ทธ๋ฆฐ ํ‘œ์‹์„ ๋ณด๊ณ ์„œ์— ์ ๊ณ , ๋งต ๋ฉ”๋‰ด์˜ "์ด ์ด๋ฒคํŠธ ์•ž์—์„œ ์‹คํ–‰"๊ณผ "์ด ์ด๋ฒคํŠธ ์ž๋™ ์žฌ์ƒ"์„ ๋ฌผ๊ณ ๊ธฐ ์žฅ์ˆ˜์—๊ฒŒ ์•ฑ์— ๋“  ์—”์ง„์œผ๋กœ ๋Œ๋ฆฝ๋‹ˆ๋‹ค. ํŒ์ •์€ ํ‘œ์‹ 17๊ฐœ๊ฐ€ ๋งต ํŒŒ์ผ์˜ ์ž๋ฆฌ์— ๊ฒŒ์ž„์˜ ๊ทธ๋ฆฌ๊ธฐ ๊ทœ์น™๋Œ€๋กœ ์žˆ๋Š”์ง€, ๊ฒŒ์ž„์ด ์ด๋ฒคํŠธ๋ฅผ ๋‹ค ์ฝ์—ˆ๋Š”์ง€, ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ํŒ์ •์ด ๋งต ํŒŒ์ผ๋กœ ์…ˆํ•œ ์ž๋ฆฌ์— ์„ฐ๋Š”์ง€(rpg:player:), ์ž๋™ ์žฌ์ƒ์ด ์ด๋ฒคํŠธ๋ฅผ ๋Œ๋ ธ๋Š”์ง€(rpg:event:) ๋ด…๋‹ˆ๋‹ค. --forest ์™€ ๊ฐ™์€ ์ €์žฅ์†Œ๋ฉด ์‚ฌ๋ณธ ํ•˜๋‚˜๋ฅผ ํ•จ๊ป˜ ์”๋‹ˆ๋‹ค.
  • --embedded ๋Š” ์—๋””ํ„ฐ ์•ˆ ์‹คํ–‰์„ ๋”ํ•˜๋Š”๋ฐ ์ฐฝ์ด ๋œน๋‹ˆ๋‹ค. --total-timeout <ms> ๋กœ ์ „์ฒด ์‹œ๊ฐ„์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋กœ์ปฌ์—์„œ dmg ๊นŒ์ง€ ๋งŒ๋“ค๋ฉด(--bundles app,dmg) Finder ์ฐฝ์ด ์ž ๊น ๋œน๋‹ˆ๋‹ค. CI ์—์„œ๋Š” ๋œจ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • CSP ๋Š” src-tauri/tauri.conf.json ์˜ app.security.csp ์ž…๋‹ˆ๋‹ค. ์ƒˆ ๊ธฐ๋Šฅ์ด ๋ง‰ํžˆ๋ฉด ์ž๊ฐ€ ๊ฒ€์‚ฌ ๋ณด๊ณ ์„œ์˜ cspViolations ์— ๋ฌด์—‡์ด ๋ง‰ํ˜”๋Š”์ง€ ๋‚˜์˜ต๋‹ˆ๋‹ค.

์•ˆ๋“œ๋กœ์ด๋“œ๋กœ ์Šคํ…Œ์ด์ง•

๋ฐ์Šคํฌํ†ฑ ์•ฑ์˜ "์‹คํ–‰ > ์•ˆ๋“œ๋กœ์ด๋“œ๋กœ ์Šคํ…Œ์ด์ง•" ์€ ์—ด๋ฆฐ ํ”„๋กœ์ ํŠธ๋ฅผ ์—”์ง„ ์ €์žฅ์†Œ์˜ android/app/src/main/assets/ ๋กœ ์˜ฎ๊น๋‹ˆ๋‹ค. ์—”์ง„์˜ android/prepare_assets.sh --project <ํ”„๋กœ์ ํŠธ> ๋ฅผ ๋ถ€๋ฅด๋Š” ๊ฒƒ์ด๋ผ ์—”์ง„ ์ €์žฅ์†Œ(Initial2D ์ฒดํฌ์•„์›ƒ)์™€ bash, python3 ์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. APK ๋นŒ๋“œ์™€ ์„ค์น˜๋Š” ํ•˜์ง€ ์•Š๊ณ , ๋๋‚˜๋ฉด ์ฝ˜์†”์— ์น  ๋ช…๋ น์„ ์ ์–ด ์ค๋‹ˆ๋‹ค.

  • ์—”์ง„ ์ €์žฅ์†Œ๋Š” ์„ค์ •์˜ "์—”์ง„ ์ €์žฅ์†Œ" ์นธ, ์—ด๋ฆฐ ํ”„๋กœ์ ํŠธ ์ž์‹ , ์ฐพ์€ ์—”์ง„์˜ ์ €์žฅ์†Œ(<์ €์žฅ์†Œ>/build/Initial2D), ํ˜•์ œ ํด๋” ../Initial2D ์ˆœ์„œ๋กœ ์ฐพ์Šต๋‹ˆ๋‹ค. ์„ค์ • ์นธ์ด ์•„๋‹Œ ๊ณณ์—์„œ ์ฐพ์€ ์Šคํฌ๋ฆฝํŠธ๋Š” ๊ฒฝ๋กœ๋ฅผ ๋ณด์ด๊ณ  "์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰ ํ—ˆ์šฉ" ์„ ๋ˆ„๋ฅธ ๋’ค์—๋งŒ ๋Œ๋ฆฝ๋‹ˆ๋‹ค. ํ—ˆ์šฉ์€ ํ”„๋กœ์ ํŠธ๋งˆ๋‹ค ์•ฑ ์„ค์ •์— ๋‚จ๊ณ  ์„ค์ •์—์„œ ์ทจ์†Œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ™•์ธ ๋Œ€ํ™”์ƒ์ž๊ฐ€ ํŒŒ์ผ ์ˆ˜์™€ ํฌ๊ธฐ๋ฅผ ๋ฏธ๋ฆฌ ์…‰๋‹ˆ๋‹ค. ๋Œ€์ƒ ํด๋”๋Š” ํ†ต์งธ๋กœ ๋ฐ”๋€๋‹ˆ๋‹ค. config.setting, ์  ํŒŒ์ผ, zip, psd ๋Š” ๋„ฃ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • "RTP ๋ณ€ํ™˜๋ฌผ ๋„ฃ๊ธฐ" ๋Š” ๊ธฐ๋ณธ ๊บผ์ง์ž…๋‹ˆ๋‹ค. ์ผœ๋ฉด resources/rtp/ ๊ฐ€ ๋“ค์–ด๊ฐ€๋Š”๋ฐ ์žฌ๋ฐฐํฌํ•  ์ˆ˜ ์—†๋Š” ์†Œ์žฌ๋ผ ๊ทธ APK ๋Š” ๊ฐœ์ธ ๊ธฐ๊ธฐ ์‹œํ—˜์—๋งŒ ์”๋‹ˆ๋‹ค.
  • Windows ๋Š” Git for Windows ์˜ bash ์™€ Python 3 ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ์—”์ง„ ์ €์žฅ์†Œ๊ฐ€ --project ๋ฅผ ๋ชจ๋ฅด๋Š” ํŒ(tools/stage_list.py ๊ฐ€ ์—†๋‹ค)์ด๋ฉด ๋ฏธ๋ฆฌ ์„ธ๊ธฐ์—์„œ ๋ฉˆ์ถ”๊ณ  ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋Œ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์—”์ง„ ์ €์žฅ์†Œ๋ฅผ ์˜ฌ๋ฆฝ๋‹ˆ๋‹ค.
  • ๊ต์ฐจ ๊ฒ€์‚ฌ: INITIAL2D_DIR=../Initial2D yarn test:android-stage ๊ฐ€ ํ…œํ”Œ๋ฆฟ์œผ๋กœ ๋งŒ๋“  ํ”Œ๋ž˜ํ”ผ ํ”„๋กœ์ ํŠธ๋ฅผ ์—๋””ํ„ฐ์™€ ๊ฐ™์€ ์ธ์ž๋กœ ์ž„์‹œ ํด๋”์— ์Šคํ…Œ์ด์ง•ํ•˜๊ณ , ๊ธฐ๊ธฐ์ฒ˜๋Ÿผ ํ’€์–ด ๋ฐ์Šคํฌํ†ฑ ์—”์ง„์œผ๋กœ ๋Œ๋ฆฝ๋‹ˆ๋‹ค. --project ๋ฅผ ๋ชจ๋ฅด๋Š” ์—”์ง„์ด๋‚˜ ๋นŒ๋“œํ•œ ์—”์ง„์ด ์—†์œผ๋ฉด ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค.

RPG ์ด๋ฒคํŠธ (E5)

๋งต ํŒŒ์ผ์˜ events๋ฅผ ๋งต ์œ„์—์„œ ๊ณ ์น˜๋Š” RPG ํ™•์žฅ(packages/ext-rpg)์ž…๋‹ˆ๋‹ค. ์—”์ง„์˜ ์ด๋ฒคํŠธ ์Šคํ‚ค๋งˆ(resources/schema/event-commands.json)์™€ ๊ฒŒ์ž„ ์„ค์ •(resources/data/rpg-game.json)์„ ์ฝ๊ณ , ์—”์ง„๊ณผ ๊ฐ™์€ ๊ฒ€์‚ฌ๋ฅผ ๊ฐ™์€ ๊ฒฝ๋กœ(events[3].commands[2].text)๋กœ ๋‚ด๊ณ , ๋˜๋Œ๋ฆด ์ˆ˜ ์žˆ๋Š” ๋ช…๋ น์œผ๋กœ ์ด๋ฒคํŠธ์™€ ์ปค๋งจ๋“œ๋ฅผ ๊ณ ์นฉ๋‹ˆ๋‹ค. ๊ณ ์นœ ์ด๋ฒคํŠธ๋Š” ๊ทธ ์•ž์—์„œ ๋ฐ”๋กœ ๋„์›Œ ๋ด…๋‹ˆ๋‹ค. ๊ณ„์•ฝ์˜ ์ •๋ณธ์€ ์—”์ง„์˜ docs/plans/m2-rpg-events.md์ž…๋‹ˆ๋‹ค.

  • ์ด๋ฒคํŠธ ๋ ˆ์ด์–ด: rpg-game.json์— ๋“ฑ๋ก๋œ ๋งต(ํ•ญ๊ตฌ ๋งˆ์„, ์—ฌ๊ด€)์„ ์—ด๋ฉด ๋ ˆ์ด์–ด ํŒจ๋„์— "์ด๋ฒคํŠธ" ์ค„์ด ์˜ค๋ธŒ์ ํŠธ ์œ„์— ์ƒ๊น๋‹ˆ๋‹ค. ์™ธํ˜•์ด ์žˆ๋Š” ์ด๋ฒคํŠธ๋Š” CharSet์˜ ์„œ ์žˆ๋Š” ํ”„๋ ˆ์ž„์ด ๊ฒŒ์ž„๊ณผ ๊ฐ™์€ ์ž๋ฆฌ(๋ฐœ์ด ์นธ ์•„๋ž˜ ๋ณ€)์—, ๋‚˜๋จธ์ง€๋Š” ์นธ์— ํŠธ๋ฆฌ๊ฑฐ ๊ธ€์ž(๋ง, ๋ฐŸ, ์ž, ๋ณ‘)๋กœ ๋ณด์ž…๋‹ˆ๋‹ค. ์™ธํ˜•์€ ์Šคํ‚ค๋งˆ์˜ ํ›„๋ณด ์ค‘ ํ”„๋กœ์ ํŠธ์— ์žˆ๋Š” ์ฒซ ๊ทธ๋ฆผ์ด๋ผ RTP๊ฐ€ ์žˆ์œผ๋ฉด RTP ๊ทธ๋ฆผ์ž…๋‹ˆ๋‹ค. ๋“ฑ๋ก๋˜์ง€ ์•Š์€ ๋งต(์•Œ๋ฐ๋ฐ”๋ž€, ์ƒ˜ํ”Œ)์—๋Š” ์ค„ ๋Œ€์‹  ํ•œ ์ค„ ์•ˆ๋‚ด๊ฐ€ ์žˆ๊ณ , ์Šคํ‚ค๋งˆ๊ฐ€ ์—†๋Š” ํ”„๋กœ์ ํŠธ์—๋Š” ๋ ˆ์ด์–ด ์ค„๋„, ๋งต ๋ฉ”๋‰ด์˜ ์ด๋ฒคํŠธ ํ•ญ๋ชฉ๋„, ์ฐฝ ๋ฉ”๋‰ด์˜ ์ด๋ฒคํŠธ๋„ ์—†์Šต๋‹ˆ๋‹ค. RTP ํŒ๊ณผ ๊ธฐ๋ณธ ํŒ์ด ๋”ฐ๋กœ ์žˆ๋Š” ๋งต(๋งˆ์„, ์˜ค๋‘๋ง‰)๊ณผ ์Šคํ‚ค๋งˆ ๋ฒ„์ „์„ ๋ชจ๋ฅด๋Š” ๊ฒฝ์šฐ๋Š” ์ฝ๊ธฐ ์ „์šฉ์ด๊ณ  ์ด์œ ๊ฐ€ ์ž๋ฌผ์‡  ์˜†์— ๋ณด์ž…๋‹ˆ๋‹ค. ์ฝ๊ธฐ ์ „์šฉ์ด์–ด๋„ ๋งต ํฌ๊ธฐ๋ฅผ ๋ฐ”๊พธ๋ฉด ์ด๋ฒคํŠธ๋Š” ํƒ€์ผ๊ณผ ํ•จ๊ป˜ ์˜ฎ๊ฒจ์ง‘๋‹ˆ๋‹ค. ๋ ˆ์ด์–ด์˜ ๋ˆˆ์„ ๋„๋ฉด ํƒ€์ผ ๋ ˆ์ด์–ด์ฒ˜๋Ÿผ ๋งต ๋ทฐ์—์„œ ๊ณ ์น˜์ง€ ์•Š๊ณ  ์•Œ๋ฆฝ๋‹ˆ๋‹ค.

  • ์ด๋ฒคํŠธ ๋„๊ตฌ(N): ํด๋ฆญ์œผ๋กœ ๊ณ ๋ฅด๊ธฐ(Shift, Ctrl์€ ๋”ํ•˜๊ณ  ๋นผ๊ธฐ), ๋นˆ ๊ณณ์„ ๋Œ๋ฉด ์ƒ์ž ์„ ํƒ, ๋Œ์–ด์„œ ์นธ ๋‹จ์œ„๋กœ ์˜ฎ๊ธฐ๊ธฐ(๋†“์„ ์ˆ˜ ์—†๋Š” ์นธ์ด๋ฉด ๋นจ๊ฐ„ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋กœ ์•Œ๋ ค ์ฃผ๊ณ  ์ œ์ž๋ฆฌ์— ๋‘ก๋‹ˆ๋‹ค. ๋ฐฐํšŒ ๊ตฌ์—ญ๋„ ๊ฐ™์ด ์˜ฎ๊ธฐ๊ณ  Alt๋ฅผ ๋ˆ„๋ฅด๋ฉด ๊ตฌ์—ญ์€ ๋‘ก๋‹ˆ๋‹ค), ๊ณ ๋ฅธ ์ด๋ฒคํŠธ์˜ ๋ฐฐํšŒ ๊ตฌ์—ญ ๊ฐ€์žฅ์ž๋ฆฌ ๋Œ๊ธฐ, ๋นˆ ์นธ ๋”๋ธ”ํด๋ฆญ์œผ๋กœ ์ƒˆ ์ด๋ฒคํŠธ, ๋ฐฉํ–ฅํ‚ค๋กœ ํ•œ ์นธ, Delete๋กœ ์ง€์šฐ๊ธฐ, Enter๋กœ ์ปค๋งจ๋“œ ํŽธ์ง‘๊ธฐ. Ctrl+C, Ctrl+V(์ปค์„œ ์นธ์—), Ctrl+D๋Š” ์ด๋ฒคํŠธ ์ „์šฉ ํด๋ฆฝ๋ณด๋“œ๋ผ ๋งต ์˜ค๋ธŒ์ ํŠธ๋‚˜ ์”ฌ๊ณผ ์„ž์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ๊ธฐ ํ•œ ๋ฒˆ, ์ž…๋ ฅ ์นธ์˜ ํƒ€์ดํ•‘ ํ•œ ๋ฒˆ์ด ๋˜๋Œ๋ฆฌ๊ธฐ ํ•œ ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค.

  • ์ธ์ŠคํŽ™ํ„ฐ: ์Šคํ‚ค๋งˆ์˜ ์ด๋ฒคํŠธ ์นธ(id, ์นธ, ๋ฐฉํ–ฅ, ํŠธ๋ฆฌ๊ฑฐ, ์™ธํ˜•๊ณผ 8๋ช… ๊ฒฉ์ž, ์ง€๋‚˜๊ฐ€๊ธฐ, ๋ง‰๊ธฐ, ์†๋„, ๋ฐฐํšŒ)๊ณผ ๊ทธ ์•„๋ž˜ ์ปค๋งจ๋“œ ๋ชฉ๋ก ํŽธ์ง‘๊ธฐ์ž…๋‹ˆ๋‹ค. id๋ฅผ ๋ฐ”๊พธ๋ฉด ์ด ๋งต์˜ moveRoute์™€ turn์˜ ๋Œ€์ƒ๋„ ํ•จ๊ป˜ ๋ฐ”๋€๋‹ˆ๋‹ค. ์ปค๋งจ๋“œ ํŠธ๋ฆฌ๋Š” ์œ„์•„๋ž˜๋กœ ์ค„, Enter๋กœ ์ธ์ž ํผ, Insert๋กœ ํŒ”๋ ˆํŠธ, Ctrl+์œ„์•„๋ž˜๋กœ ์˜ฎ๊ธฐ๊ธฐ, Ctrl+C์™€ Ctrl+V๋กœ ์—ฌ๋Ÿฌ ์ค„ ๋ณต์‚ฌ์™€ ๋ถ™์—ฌ๋„ฃ๊ธฐ, Delete๋กœ ๋นผ๊ธฐ์ž…๋‹ˆ๋‹ค (macOS๋Š” ๋„๊ตฌ ์ค„์˜ ๋„ฃ๊ธฐ ๋‹จ์ถ”๋‚˜ ๋ ์ค„์˜ Enter). ํŠธ๋ฆฌ์—์„œ ๋ˆ„๋ฅธ ๊ธ€์ž ํ‚ค๋Š” ๋งต ๋„๊ตฌ๋ฅผ ๋ฐ”๊พธ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ธ์ž ํผ์˜ ํ•œ ์ค„ ์นธ์€ Enter๋กœ ๊ฐ’์„ ๋„ฃ๊ณ  ํผ์— ๋‚จ๊ณ , Escape๋กœ ํŠธ๋ฆฌ์— ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. ์ž…๋ ฅ ์นธ ์•ˆ์˜ Ctrl+Z๋Š” ๋ฌธ์„œ๋ฅผ ๋˜๋Œ๋ฆฌ๊ณ  ์นธ๋„ ๋˜๋Œ๋ฆฐ ๊ธ€์„ ๋ณด์ž…๋‹ˆ๋‹ค (์”ฌ ์ธ์ŠคํŽ™ํ„ฐ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค). ๊ณ ๋ฅธ ์ด๋ฒคํŠธ๋Š” ๋ฒˆํ˜ธ๊ฐ€ ์•„๋‹ˆ๋ผ ์ด๋ฒคํŠธ๋ผ์„œ ์•ž์˜ ์ด๋ฒคํŠธ๋ฅผ ์ง€์šฐ๊ณ  ๋˜๋Œ๋ ค๋„ ๊ฐ™์€ ์ด๋ฒคํŠธ๊ฐ€ ๊ณจ๋ผ์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋งต ์ด๋™์˜ ๋Œ€์ƒ ๊ณ ๋ฅด๊ธฐ: transfer(๋งต ์ธ์ž์™€ x, y๊ฐ€ ์žˆ๋Š” ์ปค๋งจ๋“œ)์˜ ์ธ์ž ํผ ์•„๋ž˜์— "๋งต์—์„œ ๊ณ ๋ฅด๊ธฐ"์™€ "๋Œ€์ƒ ๋ณด๊ธฐ" ๋‹จ์ถ”๊ฐ€ ์žˆ๊ณ  Tab์œผ๋กœ ๊ฐˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. "๋งต์—์„œ ๊ณ ๋ฅด๊ธฐ"๋Š” ๋Œ€์ƒ ๋งต(rpg-game.json์˜ file)์„ ํƒญ์œผ๋กœ ์—ด๊ณ  ๋ทฐ ์œ„์— "ํƒ€์ผ์„ ํด๋ฆญํ•ด ์ด๋™ ์œ„์น˜ ์ง€์ • (Esc: ์ทจ์†Œ)" ๋ ๋ฅผ ๋„์›๋‹ˆ๋‹ค. ํƒ€์ผ์„ ๋ˆ„๋ฅด๋ฉด ์›๋ž˜ ๋งต์˜ ํƒญ์œผ๋กœ ๋Œ์•„์™€ x, y๊ฐ€ ํ•œ ๋ฒˆ์— ๋ฐ”๋€Œ๊ณ (์›๋ž˜ ๋งต์˜ ๋˜๋Œ๋ฆฌ๊ธฐ ํ•œ ๋‹จ๊ณ„) ๊ทธ ์ปค๋งจ๋“œ์˜ ํผ์ด ์—ด๋ ค ์žˆ์Šต๋‹ˆ๋‹ค. Esc, ๋งต ๋ฐ–์ด๋‚˜ ๋ทฐ ๋ฐ–์˜ ๋ˆ„๋ฆ„, ๋ ์˜ ์ทจ์†Œ๋Š” ๋ฐ”๊พธ์ง€ ์•Š๊ณ  ๋Œ์•„์˜ค๊ณ , ๊ณ ๋ฅด๋Š” ๋™์•ˆ ์›๋ž˜ ํƒญ์„ ๋‹ซ์œผ๋ฉด ๋ฐ”๊พธ์ง€ ์•Š๊ณ  ๋๋‚ฉ๋‹ˆ๋‹ค. ๊ฐ™์€ ๋งต์œผ๋กœ ๊ฐ€๋Š” ์ด๋™์ด๋ฉด ๊ทธ ๋งต์˜ ๋ทฐ์—์„œ ๊ณ ๋ฆ…๋‹ˆ๋‹ค. ๊ณ ๋ฅด๋Š” ๋™์•ˆ ๋งต ๋„๊ตฌ๋Š” ๋ˆ„๋ฆ„๊ณผ ํ‚ค๋ฅผ ๋ฐ›์ง€ ์•Š๊ณ , ํœ ๊ณผ ์˜ค๋ฅธ์ชฝ ๋Œ๊ธฐ์™€ Space+๋Œ๊ธฐ๋Š” ๊ทธ๋Œ€๋กœ ๋ทฐ๋ฅผ ์˜ฎ๊น๋‹ˆ๋‹ค. "๋Œ€์ƒ ๋ณด๊ธฐ"๋Š” ๋Œ€์ƒ ๋งต์„ ์—ด๊ณ  x, y ํƒ€์ผ์„ ๋ทฐ ๊ฐ€์šด๋ฐ์— ๋‘ก๋‹ˆ๋‹ค. ๋งต์ด ๋น„์—ˆ๊ฑฐ๋‚˜, rpg-game.json์— ์—†๊ฑฐ๋‚˜, ํŒŒ์ผ์ด ์—†๊ฑฐ๋‚˜, ์—”์ง„์ด ์—ด ์ˆ˜ ์—†๋Š” ๋งต(๋ชจ๋ฅด๋Š” ๋ฒ„์ „, ํƒ€์ผ์…‹ ๊ทธ๋ฆผ ์—†์Œ ๋“ฑ)์ด๋ฉด ๋‘ ๋‹จ์ถ”๊ฐ€ ๊บผ์ง€๊ณ  ์ด์œ ๊ฐ€ ํ•œ ์ค„ ๋ณด์ž…๋‹ˆ๋‹ค. ์ฝ๊ธฐ ์ „์šฉ ๋ ˆ์ด์–ด๋Š” ๊ณ ๋ฅด๊ธฐ๋งŒ, x, y๊ฐ€ ์—†์œผ๋ฉด ๋Œ€์ƒ ๋ณด๊ธฐ๋งŒ ๊บผ์ง‘๋‹ˆ๋‹ค.

  • ์ด๋ฒคํŠธ ํŒจ๋„(์ฐฝ > ์ด๋ฒคํŠธ, ํƒ€์ผ๋งต ๋ ˆ์ด์•„์›ƒ์— ๋“ค์–ด ์žˆ์Œ): ์ด ๋งต์˜ ์ด๋ฒคํŠธ ๋ชฉ๋ก๊ณผ ์ฐพ๊ธฐ(id, ํŠธ๋ฆฌ๊ฑฐ, ๋Œ€์‚ฌ), ์˜ค๋ฅ˜์™€ ๊ฒฝ๊ณ  ์ˆ˜, ๊ทธ๋ฆฌ๊ณ  ์‹œ์ž‘ ์ƒํƒœ ํ•œ ์ค„(arrived,item:warehouse_key=1 ๊ผด, INITIAL2D_RPG_STATE์™€ ๊ฐ™์€ ๊ทœ์น™)์ž…๋‹ˆ๋‹ค. ์‹œ์ž‘ ์ƒํƒœ๋Š” ๋งต๋งˆ๋‹ค .initial-editor/rpg-play.json์— ๋‚จ์Šต๋‹ˆ๋‹ค.

  • ์ €์žฅ: ์—”์ง„์ด ๊ฑด๋„ˆ๋›ธ ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋Š” ๋งต์€ ์ €์žฅํ•˜๊ธฐ ์ „์— ๋ชฉ๋ก์„ ๋ณด์ด๊ณ  ๋ฌป์Šต๋‹ˆ๋‹ค. ์—๋””ํ„ฐ์˜ ํŽธ์ง‘์€ ๊ทธ๋Ÿฐ ๊ฐ’์„ ๋งŒ๋“ค์ง€ ์•Š์œผ๋ฏ€๋กœ ๋ฐ–์—์„œ ๊ณ ์นœ ํŒŒ์ผ์—์„œ๋งŒ ๋‚˜์˜ต๋‹ˆ๋‹ค. ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ ์ด๋ฒคํŠธ ์นธ์€ ์ด๋ฒคํŠธ ํŒจ๋„์— events[n]๊ณผ ํ•จ๊ป˜ ํ‹€๋ฆฐ ์ค„๋กœ ๋ณด์ž…๋‹ˆ๋‹ค. 2^53์„ ๋„˜๋Š” ์ •์ˆ˜(์—”์ง„์€ 64๋น„ํŠธ ์ •์ˆ˜๋กœ ์ฝ์Šต๋‹ˆ๋‹ค)๋Š” ๊ธ€ ๊ทธ๋Œ€๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

  • ์ด ๋งต์—์„œ ์‹คํ–‰(Ctrl+F5): ๋“ฑ๋ก๋œ ๋งต์—์„œ๋Š” rpg-game.json์˜ play๋กœ ๋„์›๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ํ•˜๋‚˜๋ฅผ ๊ณจ๋ž์œผ๋ฉด ๊ทธ ์•ž ์นธ์—์„œ ์ด๋ฒคํŠธ ์ชฝ์„ ๋ณด๊ณ , ์•„๋‹ˆ๋ฉด ์ปค์„œ ์นธ, ๊ทธ๋‹ค์Œ ๋ทฐ ๊ฐ€์šด๋ฐ์—์„œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์„ค ์ˆ˜ ์žˆ๋Š” ์นธ์— ์•„๋ž˜๋ฅผ ๋ณด๊ณ  ์„ญ๋‹ˆ๋‹ค. ์…‹ ๋‹ค ์—†์œผ๋ฉด ์ •์˜ ํŒŒ์ผ์˜ ์‹œ์ž‘์ž…๋‹ˆ๋‹ค. ๋“ฑ๋ก๋˜์ง€ ์•Š์€ ๋งต(์•Œ๋ฐ๋ฐ”๋ž€)์€ ์ง€๊ธˆ์ฒ˜๋Ÿผ map-objects.json์˜ play(maps๊ฐ€ ๋ฐ›๋Š” ๋งต๋งŒ)๋กœ ๋„์›๋‹ˆ๋‹ค.

  • ์ด ์ด๋ฒคํŠธ ์•ž์—์„œ ์‹คํ–‰, ์ด ์ด๋ฒคํŠธ ์ž๋™ ์žฌ์ƒ: ์ธ์ŠคํŽ™ํ„ฐ์˜ "์•ž์—์„œ ์‹คํ–‰"๊ณผ "์ž๋™ ์žฌ์ƒ" ๋‹จ์ถ”, ๋งต ๋ฉ”๋‰ด, ์ด๋ฒคํŠธ ํŒจ๋„ ์ค„์˜ ์šฐํด๋ฆญ(๋˜๋Š” Shift+F10)์— ์žˆ์Šต๋‹ˆ๋‹ค. ์•ž ์นธ์€ ์™ธํ˜•๊ณผ ๋ฐฉํ–ฅ์ด ์žˆ์œผ๋ฉด ์ด๋ฒคํŠธ๊ฐ€ ๋ฐ”๋ผ๋ณด๋Š” ์นธ, ์•„๋‹ˆ๋ฉด ์•„๋ž˜, ์™ผ์ชฝ, ์˜ค๋ฅธ์ชฝ, ์œ„ ์ˆœ์„œ์ž…๋‹ˆ๋‹ค. ์ž๋™ ์žฌ์ƒ์€ ๊ฒฐ์ • ํ‚ค(action), ์ด๋ฒคํŠธ ์ชฝ์œผ๋กœ ํ•œ ๊ฑธ์Œ(touch), ์œ„์น˜ ์—†์ด ๋งต์— ๋“ค์–ด์„œ๊ธฐ(auto)๋ฅผ ํ•œ ๋ฒˆ ํ•˜๊ณ  ๋Œ€ํ™”๋ฅผ ์•Œ์•„์„œ ๋„˜๊ธฐ๋ฉฐ(์„ ํƒ์ง€๋Š” ์ฒซ ํ•ญ๋ชฉ), ๋๋‚˜๋ฉด ๊ฒŒ์ž„์ด ์Šค์Šค๋กœ ๋‹ซํž™๋‹ˆ๋‹ค. parallel์€ ๋๋‚˜์ง€ ์•Š์•„ ๋‹จ์ถ”๊ฐ€ ๊บผ์ง€๊ณ  ์ด์œ ๊ฐ€ ๋ณด์ž…๋‹ˆ๋‹ค. ์ €์žฅํ•˜์ง€ ์•Š์€ ๋งต์€ ๋จผ์ € ์ €์žฅํ• ์ง€ ๋ฌป์Šต๋‹ˆ๋‹ค. ์—๋””ํ„ฐ๋Š” ์ž๋™ ์žฌ์ƒ์˜ ์ค„์„ ์ง€์ผœ๋ด…๋‹ˆ๋‹ค. ์”ฌ์„ ๋ฐ”๊พธ๋Š” ์ปค๋งจ๋“œ(๋ฐ๋ชจ์˜ ๋ฐฐ)๋กœ ๊ฒŒ์ž„์ด ์ƒˆ ๊ฒŒ์ž„์œผ๋กœ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋ฉด ๊ทธ ์ž๋ฆฌ์—์„œ ๋ฉˆ์ถ”๊ณ  ์ด์œ ๋ฅผ ์ฝ˜์†”๊ณผ ์•Œ๋ฆผ์— ๋‚จ๊น๋‹ˆ๋‹ค. ๊ฒŒ์ž„์ด ๋๋‚ฌ๋Š”๋ฐ ๊ทธ ์ด๋ฒคํŠธ์˜ rpg:event:<id> ์ค„์ด ์—†์—ˆ์œผ๋ฉด ์„ฑ๊ณต์ด ์•„๋‹ˆ๋ผ ์˜ค๋ฅ˜ ์ค„๋กœ ์•Œ๋ฆฝ๋‹ˆ๋‹ค. ๋ฐฐํšŒํ•˜๋Š” NPC๋Š” ์•ž์˜ auto ์ด๋ฒคํŠธ๊ฐ€ ๋„๋Š” ๋™์•ˆ ์ž๋ฆฌ๋ฅผ ๋– ๋‚  ์ˆ˜ ์žˆ์œผ๋‹ˆ, ์‹œ์ž‘ ์ƒํƒœ๋กœ ๊ทธ auto๋ฅผ ๊ฑด๋„ˆ๋›ฐ๊ฑฐ๋‚˜ ์•ž์—์„œ ์‹คํ–‰์œผ๋กœ ์†์ˆ˜ ๋ง์„ ๊ฒ๋‹ˆ๋‹ค.

  • ์‹œ์ž‘ ์ƒํƒœ: ์ด๋ฒคํŠธ ํŒจ๋„์˜ ์‹œ์ž‘ ์ƒํƒœ ์นธ์— ์ ์€ ๊ฐ’์ด ์„ธ ์‹คํ–‰์— INITIAL2D_RPG_STATE๋กœ ์‹ค๋ฆฝ๋‹ˆ๋‹ค. ๋น„์šฐ๋ฉด ์ƒˆ ๊ฒŒ์ž„ ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค. ๋ฐ๋ชจ์˜ ๋Œ€์‚ฌ๋Š” ๋Œ€๋ถ€๋ถ„ ๊นƒ๋ฐœ๊ณผ ์•„์ดํ…œ์œผ๋กœ ๊ฐˆ๋ฆฌ๋ฏ€๋กœ(arrived,heardAltar๋ฉด ์•„์ด๊ฐ€ ์กฐ๊ฐœ ๋ชฉ๊ฑธ์ด๋ฅผ ์ค๋‹ˆ๋‹ค) ์—ฌ๊ธฐ์— ์ ์–ด ๋‘๊ณ  ๋ด…๋‹ˆ๋‹ค.

  • ์‹คํ–‰์˜ ๋ณ€์ˆ˜์™€ ์ฝ˜์†”: play.env์˜ INITIAL2D_SCRIPT=lua, INITIAL2D_SCENE=rpg, INITIAL2D_MAP, INITIAL2D_RPG_AT, INITIAL2D_RPG_STATE, INITIAL2D_RPG_TRACE=1์— ์ž๋™ ์žฌ์ƒ์€ play.probe์˜ INITIAL2D_AUTOPLAY=1, INITIAL2D_RPG_ROUTE๋ฅผ ๋”ํ•ฉ๋‹ˆ๋‹ค. ์ž๋™ ์žฌ์ƒ์€ ์—๋””ํ„ฐ๊ฐ€ ๊ฒŒ์ž„์˜ ์ค„์„ ์ง€์ผœ๋ณด๋ฏ€๋กœ play์— ์—†์–ด๋„ INITIAL2D_RPG_TRACE=1์„ ๋Š˜ ๋„ฃ๊ณ , play.probe์˜ {event}๋Š” ๊ทธ ์ด๋ฒคํŠธ์˜ id๋กœ ์ฑ„์›๋‹ˆ๋‹ค. ํ”„๋กœ์„ธ์Šค ์‹คํ–‰๊ณผ ๊ฒŒ์ž„ ํƒญ(์›น ์—”์ง„) ๋ชจ๋‘ ๊ฐ™์€ ๋ณ€์ˆ˜์ด๊ณ , ์ฝ˜์†”์— rpg:player:(์„  ์นธ๊ณผ ๋ฐฉํ–ฅ), rpg:event:, rpg:message:์ด๋ฆ„|๋Œ€์‚ฌ, rpg:route:done ์ค„์ด ๋‚จ์Šต๋‹ˆ๋‹ค. game.json์ด mruby์—ฌ๋„ RPG ์‹คํ–‰์€ INITIAL2D_SCRIPT=lua๋กœ ๋ฎ์œผ๋ฏ€๋กœ ์–ธ์–ด ๊ฒ€์‚ฌ๋Š” ๋ฎ์€ ๊ฐ’์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

  • ํ”ฝ์Šค์ฒ˜: ๋ชจ๋ธ ํ…Œ์ŠคํŠธ๋Š” ์—”์ง„ ํŒŒ์ผ์˜ ์‚ฌ๋ณธ(packages/ext-rpg/test/fixtures/)์œผ๋กœ ๋•๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ์Šคํ‚ค๋งˆ, ๊ฒŒ์ž„ ์„ค์ •, ์•„์ดํ…œ ํ‘œ, ํ•ญ๊ตฌ ๋งˆ์„๊ณผ ์—ฌ๊ด€ ๋งต, ๊ฒฝ๋กœ ๋Œ€์กฐ ํ”ฝ์Šค์ฒ˜, ํ”Œ๋ ˆ์ด์Šคํ™€๋” ๊ทธ๋ฆผ์ž…๋‹ˆ๋‹ค. ์—”์ง„ ์ชฝ ํŒŒ์ผ์ด ๋ฐ”๋€Œ๋ฉด yarn sync:rpg๋กœ ๋‹ค์‹œ ๋งž์ถฅ๋‹ˆ๋‹ค. MANIFEST.json์— ์—”์ง„ ์ปค๋ฐ‹(40์ž)๊ณผ sha256์ด ๋‚จ๊ณ , ์—”์ง„ ์ €์žฅ์†Œ๊ฐ€ ์˜†์— ์žˆ์œผ๋ฉด ์‚ฌ๋ณธ์ด ์—”์ง„ ํŒŒ์ผ๊ณผ ๊ฐ™์€์ง€ ํ…Œ์ŠคํŠธ๊ฐ€ ๋ด…๋‹ˆ๋‹ค. resources/rtp/๋Š” ๋ณต์‚ฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์—”์ง„ ์ž‘์—… ํŠธ๋ฆฌ๊ฐ€ ์ปค๋ฐ‹๊ณผ ๋‹ค๋ฅด๋ฉด ๋ฉˆ์ถ”๊ณ , ๊ทธ๋ž˜๋„ ๋ณต์‚ฌํ•˜๋ ค๋ฉด --allow-dirty๋ฅผ ์ค๋‹ˆ๋‹ค.

  • ๊ต์ฐจ ๊ฒ€์‚ฌ: yarn test:engine-events๋Š” ์—”์ง„ ์ €์žฅ์†Œ์˜ ์‚ฌ๋ณธ ํ”„๋กœ์ ํŠธ์—์„œ ํ•ญ๊ตฌ ๋งˆ์„์„ ์•ฑ๊ณผ ๊ฐ™์€ ๊ธธ(๋งต ๋ฌธ์„œ์— ์ด๋ฒคํŠธ ๋ ˆ์ด์–ด๊ฐ€ ๋ถ™๋Š”๋‹ค)๋กœ ์—ด์–ด ๋ชจ๋ธ์˜ ๋ช…๋ น๋งŒ์œผ๋กœ ์ด๋ฒคํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  ์ €์žฅํ•œ ๋’ค, ์—๋””ํ„ฐ์˜ ์‹คํ–‰ ๋ช…๋ น๊ณผ ๊ฐ™์€ ํ•จ์ˆ˜๋กœ ๋งŒ๋“  ๋ณ€์ˆ˜๋กœ ์ง„์งœ ์—”์ง„์„ ํ—ค๋“œ๋ฆฌ์Šค ํ”„๋กœ์„ธ์Šค๋กœ ๋„์›Œ trace ์ค„(rpg:player:, rpg:message:, rpg:route:done)์„ ๋ด…๋‹ˆ๋‹ค. ํŒ์€ ๋‹ค์„ฏ์ž…๋‹ˆ๋‹ค: ๋ง ๊ฑธ๊ธฐ, ๋ฐŸ์•„์„œ ์—ฌ๊ด€์œผ๋กœ ์˜ฎ๊ธฐ๊ธฐ, auto ๋‘˜์ด ์ฐจ๋ก€๋กœ ๋Œ๊ธฐ, ๋˜๋Œ๋ฆฐ ๋งต์„ ์‹œ์ž‘ ์ƒํƒœ arrived๋กœ ๋‹ค์‹œ ๋„์šฐ๊ธฐ, ์—ฌ๊ธฐ์„œ ์‹คํ–‰(๊ณ ๋ฅธ ์ด๋ฒคํŠธ ์•ž์— ์„œ๊ธฐ๋งŒ). ๊ทธ๋ฆฌ๊ณ  ๋Ÿฌ๋„ˆ์ฒ˜๋Ÿผ ์ค„์„ ์ง€์ผœ๋ณด๋Š” ์ž๋™ ์žฌ์ƒ ๋‘˜์ด ์žˆ์Šต๋‹ˆ๋‹ค: ๋ฐฐ(ship)๋Š” ์ƒˆ ๊ฒŒ์ž„์œผ๋กœ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋Š” ์ž๋ฆฌ์—์„œ ๋ฉˆ์ถ”๊ณ , ๋ฐฐํšŒํ•˜๋Š” ์•„์ด(kid)๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋Œ์ง€ ์•Š์•˜์œผ๋ฉด ์‹คํŒจ๋กœ ์•Œ๋ฆฝ๋‹ˆ๋‹ค. ์—ฌ๊ด€์œผ๋กœ ์˜ฎ๊ธฐ๋Š” ํŒ์€ ๋Œ€์กฐ ํŒ ์…‹์ด ๋’ค๋”ฐ๋ฆ…๋‹ˆ๋‹ค. transfer์˜ x, y, dir์„ ํ•˜๋‚˜์”ฉ ๋นผ๊ณ  ๋„์›Œ ๋„์ฐฉ ๊ฒ€์‚ฌ๊ฐ€ ์‹ค์ œ๋กœ ์‹คํŒจํ•˜๋Š”์ง€ ๋ด…๋‹ˆ๋‹ค. ์—”์ง„ ์‹คํ–‰ ํŒŒ์ผ์ด ์—†๊ฑฐ๋‚˜ M2 ๊ณ„์•ฝ ์ „์˜ ์—”์ง„(Initial2D 74febb4 ์ด์ „)์ด๋ฉด SKIP: ํ•œ ์ค„์„ ์ฐ๊ณ  ํ†ต๊ณผํ•ฉ๋‹ˆ๋‹ค. ์—”์ง„ ์ €์žฅ์†Œ๋Š” ๊ณ ์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

INITIAL2D_DIR=../Initial2D yarn sync:rpg              # ์—”์ง„ ํŒŒ์ผ์„ ํ”ฝ์Šค์ฒ˜๋กœ ๋ณต์‚ฌํ•˜๊ณ  MANIFEST ๊ฐฑ์‹ 
INITIAL2D_DIR=../Initial2D yarn test:engine-events    # ์—”์ง„ ๋นŒ๋“œ(build/Initial2D)๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค
KEEP_WORKDIR=1 yarn test:engine-events                # ์‚ฌ๋ณธ ํ”„๋กœ์ ํŠธ๋ฅผ ๋‚จ๊ธด๋‹ค (๊ฒฝ๋กœ๋ฅผ ๋งˆ์ง€๋ง‰์— ์ฐ๋Š”๋‹ค)
yarn build && yarn test:e2e tests/e2e/rpg-layer.spec.ts  # ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋“œ์— ํ”ฝ์Šค์ฒ˜๋ฅผ ์จ ๋„ฃ๊ณ  ์ด๋ฒคํŠธ ๋ ˆ์ด์–ด๋ฅผ ๋ธŒ๋ผ์šฐ์ €๋กœ ๋ณธ๋‹ค
RPG_LAYER_SCREENSHOT=/tmp/shots yarn test:e2e tests/e2e/rpg-layer.spec.ts  # ๋งต ๋ทฐ๋ฅผ ์ฐ์–ด ๋‚จ๊ธด๋‹ค
INITIAL2D_DIR=../Initial2D yarn test:e2e tests/e2e/rpg-events.spec.ts     # ๋†“๊ธฐ๋ถ€ํ„ฐ ์ €์žฅ๊นŒ์ง€, ์‹คํ–‰ ๋ช…๋ น์˜ ๋ณ€์ˆ˜, ๋ธŒ๋ฆฌ์ง€ ๋ชจ๋“œ์˜ ์ž๋™ ์žฌ์ƒ
yarn build && yarn test:e2e tests/e2e/rpg-editor.spec.ts  # ์ข์€ ์ธ์ŠคํŽ™ํ„ฐ, ์ž…๋ ฅ ์นธ์˜ Ctrl+Z, ์ˆจ๊ธด ๋ ˆ์ด์–ด, RPG ์•„๋‹Œ ํ”„๋กœ์ ํŠธ์˜ ๋ฉ”๋‰ด
INITIAL2D_DIR=../Initial2D yarn test:e2e tests/e2e/rpg-transfer-pick.spec.ts  # ๋งต ์ด๋™์˜ ๋Œ€์ƒ ๊ณ ๋ฅด๊ธฐ์™€ ๋Œ€์ƒ ๋ณด๊ธฐ, ๋ธŒ๋ฆฌ์ง€ ๋ชจ๋“œ์˜ ์ €์žฅ
E2E_BRIDGE_PORT=6561 RPG_EVENTS_SCREENSHOT=/tmp/rpg.png yarn test:e2e tests/e2e/rpg-events.spec.ts  # ํฌํŠธ๋ฅผ ๋ฐ”๊พธ๊ณ  ๋๋‚œ ํ™”๋ฉด์„ ์ฐ๋Š”๋‹ค

rpg-events.spec.ts์˜ ๋ธŒ๋ฆฌ์ง€ ๋ชจ๋“œ๋Š” ์—”์ง„ ์ €์žฅ์†Œ์˜ resources(RTP ๋นผ๊ณ )์™€ scripts๋ฅผ ์ž„์‹œ ํด๋”์— ๋ณต์‚ฌํ•ด ์—ด๊ณ , ์•„์ด๋ฅผ ๊ณ ๋ฅธ ๋’ค ์ž๋™ ์žฌ์ƒ์„ ๋ˆŒ๋Ÿฌ ๊ฒŒ์ž„ ํƒญ์˜ ์›น ์—”์ง„์ด ์ฝ˜์†”์— ๋‚จ๊ธด ์ค„์„ ๋ด…๋‹ˆ๋‹ค. ๋ฐฐ์˜ ์ž๋™ ์žฌ์ƒ์€ ์ƒˆ ๊ฒŒ์ž„์œผ๋กœ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋Š” ์ž๋ฆฌ์—์„œ ๋ฉˆ์ถ”๋Š”์ง€ ๋ด…๋‹ˆ๋‹ค. ํ”„๋กœ์„ธ์Šค ์‹คํ–‰์€ ๋ธŒ๋ผ์šฐ์ €๋กœ ๋ณผ ์ˆ˜ ์—†์–ด yarn test:engine-events์™€ ๋Ÿฌ๋„ˆ์˜ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ (RunnerStore.play.test.ts, ์‹คํ–‰ ์ œ๊ณต์ž์˜ ๋ณ€์ˆ˜๊ฐ€ RunSpec.env์— ๊ทธ๋Œ€๋กœ ์‹ค๋ฆฐ๋‹ค)๊ฐ€ ๋งก์Šต๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ

ํ”„๋กœ์ ํŠธ๋Š” game.json์ด ์žˆ๋Š” ํด๋”์ž…๋‹ˆ๋‹ค. ์—”์ง„์ด ์ž‘์—… ํด๋”์˜ ./game.json์„ ์ฝ์œผ๋ฏ€๋กœ ์ƒˆ ๊ฐœ๋…์ด ์•„๋‹™๋‹ˆ๋‹ค. game.json์ด ์—†๋Š” ํด๋”(์˜ˆ: Initial2D ์ €์žฅ์†Œ ์ž์ฒด)๋ฅผ ์—ด๋ฉด ์—๋””ํ„ฐ๊ฐ€ ๋งŒ๋“ค ๊ฒƒ์ธ์ง€ ๋ฌป์Šต๋‹ˆ๋‹ค. ์—๋””ํ„ฐ๋งŒ ์“ฐ๋Š” ์ƒํƒœ (๋ ˆ์ด์•„์›ƒ ๋“ฑ)๋Š” .initial-editor/์— ๋‘๋ฏ€๋กœ gitignore ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ ํŒจ๋„์€ ์ฒ˜์Œ์— ํ”„๋กœ์ ํŠธ ํŒŒ์ผ(game.json, scripts/, resources/)๋งŒ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค. ์ ์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ์ด๋ฆ„๋„ ๋น ์ง‘๋‹ˆ๋‹ค. ๋จธ๋ฆฌ์˜ ๊น”๋•Œ๊ธฐ ๋‹จ์ถ” ์˜† ์ˆซ์ž๊ฐ€ ์ˆจ๊ธด ํ•ญ๋ชฉ ์ˆ˜์ด๊ณ , ๋ˆ„๋ฅด๋ฉด ์ „๋ถ€ ๋ณด์ž…๋‹ˆ๋‹ค. ์ผœ๊ณ  ๋ˆ ์ƒํƒœ๋Š” .initial-editor/project-view.json์— ๋‚จ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ ์ตœ์ƒ์œ„์— .initial-editorignore(.gitignore ๋ฌธ๋ฒ•)๋ฅผ ๋‘๋ฉด ๋” ๋บ„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

# ์ž‘์—… ํŒŒ์ผ
*.psd
/resources/aldebaran/src/

ํ”„๋กœ์ ํŠธ ์ „์ฒด ์ฐพ๊ธฐ, ๊ฒŒ์ž„ ํƒญ์ด ์˜ฌ๋ฆฌ๋Š” ํŒŒ์ผ, ์ธ์ŠคํŽ™ํ„ฐ์˜ ์ด๋ฏธ์ง€์™€ ์ปดํฌ๋„ŒํŠธ ๋ชฉ๋ก๋„ ์ด ํŒŒ์ผ์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. .gitignore๋Š” ๋”ฐ๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค (๊ฒŒ์ž„์ด ์ฝ๋Š” resources/rtp๊นŒ์ง€ ์ˆจ๊ธฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค). ๋ธŒ๋ฆฌ์ง€ ๋ชจ๋“œ๋Š” ๋ธŒ๋ฆฌ์ง€๊ฐ€ ์ด ํŒŒ์ผ์„ ๋„˜๊ฒจ์ฃผ์ง€ ์•Š์•„ ๊ธฐ๋ณธ ๊ทœ์น™๋งŒ ์”๋‹ˆ๋‹ค.

์ €์žฅ์†Œ ๊ตฌ์„ฑ

packages/core/            DOM ๋„ PIXI ๋„ ๋ชจ๋ฅด๋Š” ๋ชจ๋ธ: ํ”„๋กœ์ ํŠธ, ๋ฌธ์„œ์™€ ๋˜๋Œ๋ฆฌ๊ธฐ, ์ปค๋งจ๋“œ์™€ ๋ฉ”๋‰ด, ํ™•์žฅ API, ๋กœ๊ทธ, ์„ค์ •
packages/backend-bridge/  ProjectBackend ์˜ ๋ธŒ๋ฆฌ์ง€(HTTP + WebSocket) ๊ตฌํ˜„
packages/backend-fsaccess/ ProjectBackend ์˜ ๋ธŒ๋ผ์šฐ์ € ํด๋”(File System Access API) ๊ตฌํ˜„. ์›นํŒ์ด ์“ด๋‹ค
packages/backend-tauri/   ProjectBackend ์˜ Tauri ๊ตฌํ˜„ (invoke ๋ž˜ํผ). Rust ๋ณธ์ฒด๋Š” src-tauri/
packages/app/             React ์…ธ: ๋„ํ‚น(dockview), ํŒจ๋„, ๋ฉ”๋‰ด์™€ ๋‹จ์ถ•ํ‚ค, ํ…Œ๋งˆ, ๋‘ ์ง„์ž… ๋ชจ๋“œ
packages/ext-tilemap/     ํƒ€์ผ๋งต ํ™•์žฅ: ๋งต ๋ชจ๋ธ(ํฌ๋งท, ํƒ€์ผ ๊ณ„์‚ฐ, ๋ช…๋ น, ์˜ค๋ธŒ์ ํŠธ ์Šคํ‚ค๋งˆ, ์˜คํ† ํƒ€์ผ)๊ณผ ์”ฌ์˜ ํƒ€์ผ๋งต ์˜ค๋ธŒ์ ํŠธ ํƒ€์ž…,
                          ๋‹ค๋ฅธ ํ™•์žฅ์ด ๋งต์— ๋ ˆ์ด์–ด์™€ ์ด ๋งต์—์„œ ์‹คํ–‰ ์ œ๊ณต์ž๋ฅผ ๋ถ™์ด๊ณ , ๋งต์„ ๋„์šฐ๊ณ , ๋งต ๋ทฐ์—์„œ ํƒ€์ผ์„ ๊ณ ๋ฅด๋Š” ์ž๋ฆฌ(contrib.ts)
packages/ui/              React ์ž…๋ ฅ ๋ถ€ํ’ˆ: ์ธ์ŠคํŽ™ํ„ฐ์˜ ์ˆซ์ž, ๊ธ€, ์Šคํ‚ค๋งˆ ์นธ ์ž…๋ ฅ. ์•ฑ๊ณผ ํ™•์žฅ์ด ํ•จ๊ป˜ ์“ด๋‹ค
packages/ext-rpg/         RPG ํ™•์žฅ: ์ด๋ฒคํŠธ ๋ชจ๋ธ(์Šคํ‚ค๋งˆ, ๊ฒŒ์ž„ ์„ค์ •, ๊ฒ€์‚ฌ, ๋ช…๋ น, ์‹คํ–‰ ์ œ๊ณต์ž์™€ ์‹คํ–‰ ๋ณ€์ˆ˜), ๋งต ๋ทฐ์˜ ์ด๋ฒคํŠธ ๋ ˆ์ด์–ด
                          (๋ทฐ, ๋„๊ตฌ, ์ธ์ŠคํŽ™ํ„ฐ, ๋ชฉ๋ก ํŒจ๋„), ์ปค๋งจ๋“œ ๋ชฉ๋ก ํŽธ์ง‘๊ธฐ, ์ด๋ฒคํŠธ ์‹คํ–‰ ๋ช…๋ น, ์—”์ง„ ๊ต์ฐจ ๊ฒ€์‚ฌ
src-tauri/                Rust: ํŒŒ์ผ๊ณผ ํ”„๋กœ์„ธ์Šค ๋ช…๋ น, ๊ฐ์‹œ, ํ•ซ ๋ฆฌ๋กœ๋“œ push, ์•ฑ์— ๋“  ์—”์ง„ ์ฐพ๊ธฐ
tests/e2e/                Playwright (๋ธŒ๋ผ์šฐ์ € ๋ชจ๋“œ)์™€ ์•Œ๋ฐ๋ฐ”๋ž€ ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ, ๋„์šฐ๋ฏธ๋Š” tests/e2e/support/
tests/scripts/            scripts/*.mjs ์˜ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ (ํŒ ๋ฒˆํ˜ธ, ๊ณ ์ง€, ์ž๊ฐ€ ๊ฒ€์‚ฌ ๊ณ„ํš๊ณผ ํŒ์ •)
.github/workflows/        ci.yml (๋งค ํ‘ธ์‹œ), release.yml (์„ค์น˜ ํŒŒ์ผ๊ณผ ์ž๊ฐ€ ๊ฒ€์‚ฌ)
docs/plans/               ๊ณ„ํš๊ณผ ์ง„ํ–‰ ์ƒํ™ฉ
docs/design/              UI ์šฉ์–ด์™€ ๋ฌธ๊ตฌ ๊ทœ์น™ (ui-terms.md)

๊ฐœ๋ฐœ ๋ช…๋ น

๋ช…๋ น ๋ฌด์—‡
yarn dev, yarn build, yarn preview ์•ฑ (Vite)
yarn typecheck, yarn lint TypeScript ์™€ ESLint (core์™€ ext-rpg์˜ ๋ชจ๋ธ์€ DOM ๊ณผ PIXI ๋ฅผ import ํ•˜์ง€ ๋ชปํ•œ๋‹ค)
yarn test Vitest ๋‹จ์œ„ ํ…Œ์ŠคํŠธ (๋ชจ๋“  ํŒจํ‚ค์ง€, e2e ๋„์šฐ๋ฏธ tests/e2e/support/*.unit.ts, ์Šคํฌ๋ฆฝํŠธ tests/scripts/*.unit.ts)
yarn test:conformance ๋ธŒ๋ฆฌ์ง€ ๋ฐฑ์—”๋“œ ์ ํ•ฉ์„ฑ (์—”์ง„ ์ €์žฅ์†Œ์˜ ๋ธŒ๋ฆฌ์ง€ ์„œ๋ฒ„๋ฅผ ์ž„์‹œ ํ”„๋กœ์ ํŠธ๋กœ ๋„์šด๋‹ค. ์œ„์น˜๋Š” INITIAL2D_DIR, ๊ธฐ๋ณธ ../Initial2D)
yarn test:rust cargo test (src-tauri)
yarn test:engine-scene ์—๋””ํ„ฐ ํ…œํ”Œ๋ฆฟ์œผ๋กœ ๋งŒ๋“  ํ”„๋กœ์ ํŠธ(๋นˆ, ํ”Œ๋ž˜ํ”ผ, ํƒ€์ผ๋งต x Lua, Ruby)๋ฅผ ์ง„์งœ ์—”์ง„์ด ๋Œ๋ฆฌ๋Š” ๊ต์ฐจ ๊ฒ€์‚ฌ (INITIAL2D_DIR, ์‹คํ–‰ ํŒŒ์ผ์„ ์ง์ ‘ ์ค„ ๋•Œ๋Š” INITIAL2D_EXE)
yarn test:engine-map ๋งต ํŽธ์ง‘์˜ ์—”์ง„ ๊ต์ฐจ ๊ฒ€์‚ฌ (์œ„ "๋งต ํŽธ์ง‘ (E3)"): ํ†ตํ–‰ ํŽธ์ง‘๊ณผ ์—”์ง„์˜ ๋ง‰ํž˜, ์ƒˆ ๋งต๊ณผ ์—”์ง„ ํ™”๋ฉด์˜ ๊ณจ๋“ (Lua, Ruby), ํ•ญ๊ตฌ ๋งˆ์„ ํ•œ ์นธ์„ ์น ํ•œ ๋’ค์˜ ์—”์ง„ ์ธ์ˆ˜ ์‹œ๋‚˜๋ฆฌ์˜ค (INITIAL2D_DIR, ์‹คํ–‰ ํŒŒ์ผ์„ ์ง์ ‘ ์ค„ ๋•Œ๋Š” INITIAL2D_EXE)
yarn test:android-stage ์•ˆ๋“œ๋กœ์ด๋“œ ์Šคํ…Œ์ด์ง• ๊ต์ฐจ ๊ฒ€์‚ฌ (์—๋””ํ„ฐ์™€ ๊ฐ™์€ ์ธ์ž๋กœ ์Šคํ…Œ์ด์ง•ํ•œ ํด๋”๋งŒ์œผ๋กœ ๋ฐ์Šคํฌํ†ฑ ์—”์ง„์ด ํ”Œ๋ž˜ํ”ผ๋ฅผ ๋Œ๋ฆฐ๋‹ค, ์Šคํƒฌํ”„, config.setting ๊ณผ RTP ๊ฐ€ ๋น ์ง€๋Š”์ง€). ์—”์ง„ ์ €์žฅ์†Œ๋Š” INITIAL2D_DIR
yarn test:engine-graph ๊ทธ๋ž˜ํ”„์—์„œ ๋งŒ๋“  Lua ์™€ Ruby ๋ฅผ ์ง„์งœ ์—”์ง„์ด ๋Œ๋ฆฌ๋Š” ๊ต์ฐจ ๊ฒ€์‚ฌ (์œ„ "๋น„์ฃผ์–ผ ์Šคํฌ๋ฆฝํŒ…"): ๊ทธ๋ž˜ํ”„์˜ ํ”Œ๋ž˜ํ”ผ bird ๊ฐ€ ์†์œผ๋กœ ์“ด ๊ฒƒ๊ณผ ๊ฐ™์€ ํŒ์ธ์ง€, ์ƒ˜ํ”Œ๋Ÿฌ์˜ ๊ฐ’์ด ๋‘ ์–ธ์–ด์—์„œ ๊ฐ™์€์ง€ (INITIAL2D_DIR, ์‹คํ–‰ ํŒŒ์ผ์„ ์ง์ ‘ ์ค„ ๋•Œ๋Š” INITIAL2D_EXE)
yarn luals:fetch ์•ฑ์— ์‹ฃ๋Š” ์–ธ์–ด ์„œ๋ฒ„ LuaLS ๋ฅผ ๋ฐ›์•„(sha256 ํ™•์ธ) ์“ฐ์ง€ ์•Š๋Š” ๊ฒƒ์„ ๋นผ๊ณ  src-tauri/luals/ ์— ํ‘ผ๋‹ค. ๊ณ ์ง€๋Š” src-tauri/licenses/luals/. --target <ํŠธ๋ฆฌํ”Œ>, --from <์••์ถ• ํŒŒ์ผ>
yarn test:luals ์ง„์งœ LuaLS ์™€ ์—๋””ํ„ฐ์˜ LSP ํด๋ผ์ด์–ธํŠธ (tests/luals/): ์ƒˆ RPG ํ”„๋กœ์ ํŠธ๊ฐ€ ๊ฒฝ๊ณ  ์—†์ด ์ฝํžˆ๋Š”์ง€, ์Šคํ… ์—†๋Š” ํ”„๋กœ์ ํŠธ์˜ ์ง„๋‹จ, ์™„์„ฑ, ํ˜ธ๋ฒ„, ์ •์˜, ์ฐธ์กฐ, ์ด๋ฆ„ ๋ฐ”๊พธ๊ธฐ. ๋จผ์ € yarn luals:fetch, ๋‹ค๋ฅธ ์‹คํ–‰ ํŒŒ์ผ์€ INITIAL_EDITOR_LUALS
yarn test:engine-events ๋ชจ๋ธ์˜ ๋ช…๋ น์œผ๋กœ ๋งŒ๋“  RPG ์ด๋ฒคํŠธ๋ฅผ ์ง„์งœ ์—”์ง„์ด ๋Œ๋ฆฌ๋Š” ๊ต์ฐจ ๊ฒ€์‚ฌ (ํ•ญ๊ตฌ ๋งˆ์„ ์‚ฌ๋ณธ, ๋„ค ํŒ๊ณผ ๋Œ€์กฐ ์„ธ ํŒ, INITIAL2D_DIR)
yarn sync:templates ์—”์ง„ ์ €์žฅ์†Œ์˜ ์”ฌ ๋กœ๋”์™€ ํ…œํ”Œ๋ฆฟ๊ณผ ์˜ˆ์ œ๋ฅผ packages/app/templates/ ๋กœ ๋ณต์‚ฌํ•˜๊ณ  MANIFEST(์ถœ์ฒ˜, ์—”์ง„ ์ปค๋ฐ‹, sha256, ์ƒ์„ฑ๋ฌผ ํ‘œ์‹œ)๋ฅผ ๊ฐฑ์‹  (INITIAL2D_DIR). --from-zip <zip ์ด๋‚˜ dist ํด๋”> ๋Š” ์—”์ง„์˜ ํ…œํ”Œ๋ฆฟ ๋ฌถ์Œ์—์„œ
yarn sync:rpg ์—”์ง„ ์ €์žฅ์†Œ์˜ RPG ์ด๋ฒคํŠธ ๊ณ„์•ฝ ํŒŒ์ผ์„ packages/ext-rpg/test/fixtures/ ๋กœ ๋ณต์‚ฌํ•˜๊ณ  MANIFEST(์ถœ์ฒ˜, ์—”์ง„ ์ปค๋ฐ‹, sha256)๋ฅผ ๊ฐฑ์‹  (INITIAL2D_DIR)
yarn engine:fetch ์•ฑ์— ์‹ฃ๋Š” ์—”์ง„์„ ๋ฐ›๋Š”๋‹ค. --from <์—”์ง„ dist ํด๋”>, --target <ํŠธ๋ฆฌํ”Œ>, --templates <ํด๋”>, --any-commit (์œ„ "์•ฑ์— ์‹ฃ๋Š” ์—”์ง„")
yarn engine:check ํ•€(engine-pin.json)๊ณผ ์—”์ง„์—์„œ ์˜จ MANIFEST ์ „๋ถ€, ๋ฐ›์•„ ๋‘” engine.json ์˜ ์—”์ง„ ์ปค๋ฐ‹ ๋Œ€์กฐ
yarn engine:pin <ํƒœ๊ทธ> ํ•€์„ ์—”์ง„์˜ ๊ณต๊ฐœ ๋ฆด๋ฆฌ์Šค์— ๋ฌถ๋Š”๋‹ค (engineTag ์™€ ์ž์‚ฐ์˜ sha256). --from <ํด๋”> (์œ„ "์•ฑ์— ์‹ฃ๋Š” ์—”์ง„")
yarn version:set <ํŒ>, yarn version:check ํŒ ๋ฒˆํ˜ธ๋ฅผ ํ•œ๊บผ๋ฒˆ์— ๋ฐ”๊พธ๊ฑฐ๋‚˜ ํ•œ ๊ฐ€์ง€์ธ์ง€ ๋ณธ๋‹ค (์œ„ "์„ค์น˜ ํŒŒ์ผ๊ณผ ์ž๊ฐ€ ๊ฒ€์‚ฌ")
yarn licenses ์—๋””ํ„ฐ์˜ ์ œ3์ž ๊ณ ์ง€ src-tauri/licenses/THIRD-PARTY-editor.md ๋ฅผ ๋‹ค์‹œ ์“ด๋‹ค (scripts/gen-licenses.mjs). --check ๋Š” ๋‹ค๋ฅด๋ฉด ์‹คํŒจ
yarn build:desktop ์†Œ์Šค๋งต ์—†๋Š” ๋นŒ๋“œ (๋ฐ์Šคํฌํ†ฑ ๋ฒˆ๋“ค์šฉ, src-tauri/tauri.dist.conf.json ์ด ๋ถ€๋ฅธ๋‹ค)
yarn selftest:app <์•ฑ> ๋นŒ๋“œํ•œ ์•ฑ์˜ ์ž๊ฐ€ ๊ฒ€์‚ฌ (์ฐฝ ์—†์Œ). --forest <์—”์ง„ ์ €์žฅ์†Œ>, --rpg <์—”์ง„ ์ €์žฅ์†Œ>, --embedded, --plan <๊ณ„ํš> --no-check
yarn sync:engine-web ์—”์ง„ ์ €์žฅ์†Œ์˜ ์›น ๋นŒ๋“œ(build-web/site/ ์˜ Initial2D.js, Initial2D.wasm, initial2d-loader.js)์™€ ์ œ3์ž ๊ณ ์ง€(THIRD-PARTY.md)๋ฅผ packages/app/public/engine/ ์œผ๋กœ ๋ณต์‚ฌํ•˜๊ณ  MANIFEST(์ถœ์ฒ˜, ์—”์ง„ ์ปค๋ฐ‹, sha256, ๊ธฐ๋Šฅ)๋ฅผ ๊ฐฑ์‹  (INITIAL2D_DIR). ๋จผ์ € ์—”์ง„ ์ €์žฅ์†Œ์—์„œ tools/build_web.sh
yarn test:engine ์ง„์งœ ์—”์ง„๊ณผ ํ•ซ ๋ฆฌ๋กœ๋“œ ๊ต์ฐจ ๊ฒ€์‚ฌ (์—”์ง„์„ ํ—ค๋“œ๋ฆฌ์Šค๋กœ ๋„์šฐ๊ณ  I2DH ๋ฌถ์Œ์„ ๋ณด๋‚ด HotReload: reloaded ๋ฅผ ๋ณธ๋‹ค). ์—”์ง„ ์ €์žฅ์†Œ ์œ„์น˜๋Š” INITIAL2D_DIR, ๊ธฐ๋ณธ ../Initial2D
yarn test:e2e Playwright, Chromium ์œผ๋กœ ๋ชจ๋“  ์ŠคํŽ™ (๋จผ์ € yarn build, ์ฒ˜์Œ ํ•œ ๋ฒˆ yarn playwright install chromium). ๋ธŒ๋ฆฌ์ง€ ๋ชจ๋“œ์™€ ์•Œ๋ฐ๋ฐ”๋ž€ ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ๋Š” INITIAL2D_DIR์˜ ์—”์ง„ ์ €์žฅ์†Œ๋ฅผ ์“ฐ๊ณ , ์—†์œผ๋ฉด ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค. ํฌํŠธ๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค: E2E_PORT(๋ฏธ๋ฆฌ๋ณด๊ธฐ, ๊ธฐ๋ณธ 4173), E2E_BRIDGE_PORT(๋ธŒ๋ฆฌ์ง€๋ฅผ ๊ณ ์ • ํฌํŠธ๋กœ ๋„์šฐ๋Š” ํ…Œ์ŠคํŠธ์˜ ํฌํŠธ)
yarn test:e2e:webkit ๊ฐ™์€ Playwright ๋ฅผ WebKit(macOS ์•ฑ์˜ ์›น๋ทฐ WKWebView ์™€ ๊ฐ™์€ ์—”์ง„)์œผ๋กœ. ๋ธŒ๋ผ์šฐ์ € ์—”์ง„์— ๋”ฐ๋ผ ๋™์ž‘์ด ๊ฐˆ๋ฆฌ๋Š” ์ŠคํŽ™(playwright.config.ts ์˜ WEBKIT_SPECS: ์Šคํฌ๋ฆฝํŠธ ํŽธ์ง‘, ์Šคํฌ๋ฆฝํŠธ ํƒญ ์—ฌ๋Ÿฟ, ๊ทธ๋ž˜ํ”„, ์–ธ์–ด ์„œ๋ฒ„, ๋ถ„์„๊ธฐ ์›Œ์ปค)๋งŒ ๋•๋‹ˆ๋‹ค. ์–ธ์–ด ์„œ๋ฒ„ ์ŠคํŽ™(language-server.spec.ts)์€ yarn luals:fetch ๋กœ ๋ฐ›์€ LuaLS ๋ฅผ ์‹œํ—˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋„์›Œ ๋ถ™์ด๊ณ , ์—†์œผ๋ฉด CI ๊ฐ€ ์•„๋‹ ๋•Œ ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค. ์ฒ˜์Œ ํ•œ ๋ฒˆ npx playwright install --with-deps webkit, ์ŠคํŽ™ ํ•˜๋‚˜๋งŒ์€ yarn test:e2e:webkit tests/e2e/script-tabs.spec.ts
yarn guide:screenshots ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ์˜ ํ™”๋ฉด(docs/guide/images/*.png)์„ ๋‹ค์‹œ ์ฐ๋Š”๋‹ค (tests/guide/, playwright.guide.config.ts). ๋จผ์ € yarn build. ์›นํŒ ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋“œ์—์„œ RPG ๋ฐ๋ชจ์™€ ํ”Œ๋ž˜ํ”ผ๋ฒ„๋“œ ํ…œํ”Œ๋ฆฟ์œผ๋กœ ์ฐ๊ณ  ์ƒํƒœ ๋ฐ”๋Š” ์ž˜๋ผ ๋ƒ…๋‹ˆ๋‹ค
yarn check:colors ํ† ํฐ ํŒŒ์ผ ๋ฐ–์˜ ์ƒ‰ ๋ฆฌํ„ฐ๋Ÿด ๊ฒ€์‚ฌ (ํ…Œ๋งˆ ๊ทœ์น™)
yarn check:terms UI ๋ฌธ๊ตฌ ๊ฒ€์‚ฌ: packages/*/src, src-tauri/src ์˜ ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด๊ณผ JSX ํ…์ŠคํŠธ์—์„œ ์“ฐ์ง€ ์•Š๋Š” ๋ง๊ณผ ํ•œ๋‹ค์ฒด ๋๋งบ์Œ์„ ์ฐพ๋Š”๋‹ค (๊ทœ์น™์€ ์•„๋ž˜ "UI ๋ฌธ๊ตฌ"). ํด๋”๋‚˜ ํŒŒ์ผ์„ ์ฃผ๋ฉด ๊ฑฐ๊ธฐ๋งŒ
node scripts/check-web-dist.mjs ๋นŒ๋“œํ•œ dist/ ๊ฒ€์‚ฌ (_headers, ์›น ์—”์ง„๊ณผ MANIFEST, ๊ณ ์ง€, Pages ํ•œ๋„). --desktop ์€ ์†Œ์Šค๋งต์ด ์—†๋Š”์ง€๋„ (์œ„ "์›นํŒ ๋ฐฐํฌ")
yarn tauri <cmd> Tauri CLI

ํ…Œ๋งˆ

์ƒ‰์€ packages/app/src/theme/tokens.css์˜ ํ† ํฐ(CSS ๋ณ€์ˆ˜)์œผ๋กœ๋งŒ ์”๋‹ˆ๋‹ค. <html data-theme="dark|light">๋กœ ๋ฐ”๋€Œ๊ณ  ๊ธฐ๋ณธ์€ OS ์„ค์ •์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. ์ƒˆ ํ…Œ๋งˆ๋Š” ํ† ํฐ ๊ฐ’ ํ•œ ๋ฒŒ์„ ๋”ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๊ทœ์น™์€ docs/plans/02-scope-and-screens.md 6์ ˆ.

UI ๋ฌธ๊ตฌ

ํ™”๋ฉด, ์•Œ๋ฆผ, ์ฝ˜์†”, ์˜ค๋ฅ˜์— ์“ฐ๋Š” ๋ง์€ docs/design/ui-terms.md์˜ ์šฉ์–ดํ‘œ์™€ ๋๋งบ์Œ ๊ทœ์น™์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. ๊ฐ™์€ ๋Œ€์ƒ์€ ์–ด๋””์„œ๋‚˜ ๊ฐ™์€ ๋ง๋กœ ๋ถ€๋ฅด๊ณ (ํƒ€์ผ, ๋ธŒ๋Ÿฌ์‹œ, ๊ฒŒ์ž„ ํƒญ, ์ด ๋งต์—์„œ ์‹คํ–‰), ๋ฉ”๋‰ด์™€ ๋ ˆ์ด๋ธ”๊ณผ ์ƒํƒœ๋Š” ์งง์€ ๋ช…์‚ฌ๊ตฌ๋กœ ์”๋‹ˆ๋‹ค. ์„ค๋ช…, ์•Œ๋ฆผ, ์˜ค๋ฅ˜, ํ™•์ธ ๋Œ€ํ™”์ƒ์ž์˜ ์‚ฌ์‹ค๊ณผ ๊ฒฐ๊ณผ๋Š” ํ•ฉ๋‹ˆ๋‹ค์ฒด๋กœ ์“ฐ๊ณ  ์งˆ๋ฌธ์€ ~ํ• ๊นŒ์š”?๋กœ ์”๋‹ˆ๋‹ค. ๋ฌธ์žฅ์ด ๋‘˜ ์ด์ƒ์ด๋ฉด ๋ฌธ์žฅ๋งˆ๋‹ค ๋งˆ์นจํ‘œ๋ฅผ ์ฐ์Šต๋‹ˆ๋‹ค. ๋ณ€์ˆ˜ ๋’ค์—๋Š” ๋ฐ›์นจ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋Š” ์กฐ์‚ฌ๋ฅผ ๋ถ™์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ƒˆ ๋ฌธ๊ตฌ๋ฅผ ๋„ฃ์œผ๋ฉด yarn check:terms๋ฅผ ๋Œ๋ฆฝ๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๋ฅผ ๋บ€ ์†Œ์Šค์˜ ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด๊ณผ JSX ํ…์ŠคํŠธ์—์„œ ์“ฐ์ง€ ์•Š๋Š” ๋ง, ํ•œ๋‹ค์ฒด ๋๋งบ์Œ, ํ™•์‹คํ•˜๊ฒŒ ๊ตฌ๋ถ„๋˜๋Š” ์ „๋ณด์ฒด ๋๋งบ์Œ์„ ์ฐพ๊ณ , CI๋„ ์ƒ‰ ๋ฆฌํ„ฐ๋Ÿด ๊ฒ€์‚ฌ ์˜†์—์„œ ๊ฐ™์€ ๊ฒ€์‚ฌ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทœ์น™์ด ๋งž์ง€ ์•Š๋Š” ์ค„(์ƒˆ ์Šคํฌ๋ฆฝํŠธ ํ…œํ”Œ๋ฆฟ์ด ์“ฐ๋Š” ์ฝ”๋“œ ์ฃผ์„ ๊ฐ™์€ ๊ฒƒ)์€ ์ค„ ๋์— // terms-ok: <์ด์œ > ๋ฅผ ์ ์–ด ๋บ๋‹ˆ๋‹ค.

์˜› ์—๋””ํ„ฐ

2020๋…„๋ถ€ํ„ฐ์˜ ํƒ€์ผ๋งต ์—๋””ํ„ฐ(PIXI 7, jQuery ์‹œ์ ˆ์˜ ์…ธ)๋Š” E3์—์„œ ์ง€์› ์Šต๋‹ˆ๋‹ค. ์˜› ๊ธฐ๋Šฅ์ด ์ƒˆ ์—๋””ํ„ฐ์˜ ์–ด๋””๋กœ ๊ฐ”๋Š”์ง€๋Š” docs/plans/e3-tilemap.md์˜ ์ด์ „ํ‘œ์— ์žˆ๊ณ , ์ฝ”๋“œ๋Š” git ์ด๋ ฅ์— ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค.

License

MIT.

About

A web-based tilemap editor for a custom 2D game engine.

Topics

Resources

Stars

12 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Contributors

Languages