Table of Contents
왜 대화형 스토리텔링 플랫폼을 구축합니까?
대화형 스토리텔링은 독자들에게 독자들을 변화시키고, 플로우 방향, 캐릭터 결정, 세계 ‐ 건물에 대한 기관을 제공합니다. JavaScript 기반 플랫폼은 제작자가 브라우저에서 완전히 실행되는 풍부한 분지의 narratives를 구축할 수 있도록 해줍니다. 선택에서 ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐
Interactive Narratives의 핵심 개념
코드의 단일 라인을 작성하기 전에 대화 형 소설 작업을 만드는 기본 빌딩 블록을 이해해야합니다. 다음 구성 요소는 필수적입니다 :
- Story Structure: Non-linear branch (nodes) 선택에 의해 연결. narrative graph는 나무, 방향 그래프, 또는 루프를 허용 (시간 여행 또는 재방문).
- State: 변수 추적 플레이어 통계, 재고, 플래그, 방문 노드. 상태 드라이브 조건 내용 및 새로운 경로 잠금 해제.
- User Interface: 프레젠테이션 레이어-텍스트 렌더링, 선택 버튼, 미디어 embeds. 그것은 응답 및 액세스해야합니다.
- JavaScript Logic:] 스토리 데이터를 파고, 조건을 평가하고, 전환을 관리하고, 지속성을 지속합니다(localStorage or IndexedDB).
Twine] 스토리 형식 (Harlowe, SugarCube, Chapel) 및 Ink]] 같은 기존 표준을 연구하여 이러한 개념을 처리하는 방법을 볼 수 있습니다. 플랫폼은 고급 사용자를 위한 맞춤형 API를 제공하면서 최고의 관행을 빌릴 수 있습니다.
스토리 프레임 디자인
스토리 엔진은 표현과 저자에게 쉽게 사용되는 데이터 모델이 필요합니다. JSON 기반 스키마는 웹 플랫폼에서 잘 작동합니다.
Node를 대표
각 narrative 노드(또는 “passage”)는 다음과 같습니다:
- id:] 고유 식별자(예: ], ).
- text: 문자열이나 마크다운과 같은 내용(안전 HTML 변환기로 렌더링).
- choices: 옵션의 배열, 대상 노드 ID, 옵션 조건 및 상태에 대한 옵션 효과 각각.
- tags: 필터링, 그저닝, 오디오를 위한 메타데이터.
- onEnter / onLeave: Hooks arbitrary JavaScript (sound, 이미지 변경, 통계 업데이트)를 실행합니다.
{
"start": {
"text": [
"You stand at the edge of a dark forest.",
"The wind carries a faint whisper."
],
"tags": ["outdoor", "moody"],
"choices": [
{ "text": "Enter the forest", "target": "forest_path",
"effect": "playerStats.fear++" },
{ "text": "Turn back to the village", "target": "village_square",
"condition": "player.hasCompass" }
]
}
}
국가 선택
상태 변수는 민감하는 저장소에 살고 있습니다. getters/setters와 변경 알림 시스템을 사용하여 간단한 객체를 사용하여 UI가 자동으로 상태 업데이트에 렌더링됩니다. 예를 들어:
class StoryState {
constructor(initialData) {
this._state = { ...initialData };
this._listeners = [];
}
get(key) { return this._state[key]; }
set(key, value) {
this._state[key] = value;
this._notify();
}
subscribe(fn) { this._listeners.push(fn); }
_notify() { this._listeners.forEach(fn => fn(this._state)); }
}
이 패턴은 DOM에서 논리를 분리하고, 플랫폼 테스트 및 확장하기 쉬운.
JavaScript Engine 구축
엔진은 스토리 데이터를 읽습니다 (정전적으로 JSON으로 가져 오기 또는 fetched) 그리고 탐색을 제어합니다. 여기에 최소한의 구현입니다.
Node 로딩 및 렌더링
function renderNode(nodeId, storyData, state) {
const node = storyData[nodeId];
if (!node) throw new Error(`Node ${nodeId} not found`);
// Run hooks before rendering
if (node.onEnter) node.onEnter(state);
const container = document.getElementById('story-content');
container.innerHTML = ''; // Clear previous content
// Render text paragraphs
node.text.forEach(para => {
const p = document.createElement('p');
p.textContent = para; // Use a safe renderer for markdown
container.appendChild(p);
});
// Render choices, filtered by conditions
const choicesContainer = document.getElementById('choices');
choicesContainer.innerHTML = '';
node.choices.forEach(choice => {
if (choice.condition && !evaluateCondition(choice.condition, state)) return;
const btn = document.createElement('button');
btn.textContent = choice.text;
btn.addEventListener('click', () => {
if (choice.effect) applyEffect(choice.effect, state);
renderNode(choice.target, storyData, state);
});
choicesContainer.appendChild(btn);
});
// Run exit hooks
if (node.onLeave) node.onLeave(state);
}
상태 평가
조건은 안전한 표현 파서 (avoid ])을 통해 평가 된 과 같은 간단한 문자열이 될 수 있습니다. expr-eval와 같은 경량 표현 증발기를 사용하거나 변수 검색 및 기본 연산자를 허용하는 반복적인 희석을 작성합니다. 샌드 박스링이 완벽한 실행을 하지 않는 한 이야기 작성자의 임의 코드를 제공하지 마십시오.
저축과 선적 진행
]를 persist 상태로 사용하십시오. (방문된 노드, 현재 노드 및 변수 포함). 각 노드 전환 후 화재가 발생되는 자동 저장 기능을 제공, 수동 저장 / 로드 UI.
function save(state, nodeId) {
localStorage.setItem('story_save', JSON.stringify({
state: state._state,
current: nodeId,
timestamp: Date.now()
}));
}
function load() {
const raw = localStorage.getItem('story_save');
if (!raw) return null;
return JSON.parse(raw);
}
더 큰 이야기에 대해 IndexedDB를 고려하여 이미지 또는 오디오 파편과 같은 바이너리 자산을 저장합니다.
사용자 경험 향상
기본 텍스트 및 버튼 인터페이스는 작동하지만 현대 관객은 멀티미디어, 반응형 디자인 및 접근성을 기대합니다.
미디어 통합
- Images: ] CSS 전환을 통해 페이드 태그를 사용합니다. ]]와 같은 패턴을 사용하여 스토리 텍스트 내의 인라인 이미지가 렌더링자에 의해 파싱됩니다.
- Audio: 배경 주변 루프와 ] Hooks에 의해 방아쇠를 끄는 소리 효과. 낮은 latency 재생 및 볼륨 제어를위한 웹 오디오 API를 사용합니다.
- 비디오: 단편영화 클립을 위한 주요 장면입니다. ]를 통해 제어 또는 자동 재생 (사용자 제스처 활성화).
책임감 있는 UI
- semantic HTML을 사용하십시오: , ], ] 사이드바 재고 또는 로그에 사용됩니다.
- ARIA 속성을 추가하십시오: 동적 텍스트 업데이트에 대한, ] 선택 컨테이너에.
- 키보드 탐색 지원: 선택 탭, 선택 입력. 숨겨진 선택에 집중할 수 있습니다.
- ] CSS 미디어 쿼리와 일치 시스템 테마.
구성 요소 기반 아키텍처 (선택 사항)
React나 Vue와 같은 보기 프레임워크를 고려하면 됩니다. 상태 관리와 렌더링을 단순화합니다. 상호 작용하는 소설을 위해 ] 무한한 상태 머신 라이브러리(예:1]] XState]]])는 가드, 행동, 병렬한 상태와 복잡한 이야기 그래프를 모델링할 수 있습니다. 그러나, 바닐라 JavaScript는 종속성을 유지하고 최소한의 핵심 개념을 가르치는 것을 계속합니다.
고급 기능
플랫폼에 차별화하려면 저자 및 플레이어가 갈망하는 기능을 추가하십시오.
다중 브랜딩 & 변수
간단한 선택 표적 쌍을 넘어, 허용:
- 조건 텍스트:다른 단락은 상태에 근거하여 (예를 들어, "당신은 오래된 사람의 경고를 기억한다"만하면 ).
- Increment/decrement 통계: 용기, 신뢰, 마법 같은 트레잇에 영향을 미칩니다.
- Inventory: 선택 사항이 있거나 소모품이 있는 항목의 목록입니다.
- 세계 플래그: 과거의 행동을 기록하고 새로운 지점을 잠금 해제하는 볼레간 변수.
비선형 항법
"back" 버튼, 장 선택, 또는지도보기를 허용하십시오. 방문한 노드의 역사를 구현하기 때문에 플레이어는 국가를 잃지 않고 패스를 다시 볼 수 있습니다 (하지만 선택이 영구적 인 영향을받은 경우 paradoxes의 조심).
실시간 공동창업자
웹 기반 권한 도구의 경우 WebSockets (또는 Firebase와 같은 서비스)를 사용하여 여러 작가가 동시에 동일한 이야기를 편집 할 수 있습니다. 이 문서의 플랫폼은 드래그 앤 드롭 노드와 시각적 편집기를 포함하도록 확장 될 수 있습니다.
테스트 및 디버깅
대화 형 스토리는 폭발 경로 수를 가지고 있습니다. 수동 테스트는 불가능합니다. 자동화 된 도구가 필요합니다.
단위 시험
테스트 조건 평가, 상태 mutations, 및 노드 로드 Jest 또는 Mocha. DOM과 localStorage를 매기.
test('renderNode shows correct text for start node', () => {
document.body.innerHTML = ``;
const storyData = {
start: { text: ['Hello'], choices: [] }
};
const state = new StoryState({});
renderNode('start', storyData, state);
expect(document.getElementById('story-content').innerHTML).toContain('Hello');
});
그래프 적용
시작에서 모든 도달 가능한 노드를 가로 질러 쓰기, 상태의 변이 수집. 모든 노드가 적어도 하나의 경로 완료 (엔드 노드). 플래그 죽은 끝이나 orphan 노드.
접근성 감사
자동 축사 ‐ 코어는 CI 파이프라인에서 확인합니다. 화면 리더 (NVDA, VoiceOver)를 테스트하고 색상 대비가 WCAG 2.1 AA 표준을 충족시킵니다.
플랫폼 배포
CDN을 통해 제공되는 정적 사이트는 대화 형 소설에 이상적입니다. 백엔드가 더 낮은 비용과 간단한 호스팅을 의미합니다.
Pipeline을 구축
- 엔진, 스토리 데이터 및 자산을 묶는 번들러 (Vite 또는 Webpack)를 사용합니다.
- JSON이 거대하면 Lazy-load story 장 (다중 파일로 분할).
- 오프라인 서비스 작업자를 생성하여 플레이어는 인터넷 없이 계속할 수 있습니다.
웹 사이트
개인 정보 보호 기능을 통합 (예 : Plausible, Umami)은 어떤 선택이 대중적이고 드롭오프 포인트 및 평균 플레이 시간을 볼 수 있습니다. 이 데이터를 사용하여 이야기를 정제합니다.
사례 연구: 간단한 공포 이야기 데모
완전한 엔진을 보여주는 두 개의 노드 데모를 상상해보십시오. 시작 노드는 선택 사항이 표시됩니다. 혹독한 집을 입력하거나 멀리 실행하십시오. 플래그 ]를 설정하고 점프 스카프 이미지와 노드로 이동합니다. 플레이어는 다시 뛰거나 진행할 수 있습니다. 이 작은 예로는 국가 전환, 미디어 로딩 및 저장 /로드를 검증합니다.
관련 기사
JavaScript 기반 대화형 스토리텔링 플랫폼은 narrative 디자인, 소프트웨어 엔지니어링 및 사용자 경험을 혼합하는 보상 프로젝트입니다. 그래프로 모델링하는 스토리 구조로, 민감하는 상태 엔진을 구현하고, 접근성과 미디어 통합에 집중하면 누구나 tales를 제작할 수 있는 도구를 만들 수 있습니다. 작은 시작으로 실제 저자와 함께 이더레이트를 시작하고, 스토리텔러 커뮤니티를 성장시키기 위해 오픈 소스로 플랫폼을 출시하십시오.