마켓플레이스 게임 빌드하기
이 튜토리얼이 끝나면 당신은 하나의 JavaScript 번들에 완전하고 플레이 가능한 Caputchin 게임을, 재생 가능하게 만들고 공개할 준비가 된 채로 갖게 됩니다. 이것은 지루한, 모든-단계를-밟는 버전입니다; 그것이 어디에 맞는지는 먼저 마켓플레이스에 게임 출시하기를 읽으세요.
Node와 번들러(esbuild, rollup, vite, 또는 webpack, 무엇이든)가 필요합니다. 빌드하는 데는 Caputchin 계정이 필요 없고, 공개하는 데만 필요합니다.
1. SDK 설치하기
npm install @caputchin/game-sdkSDK는 작습니다: register 헬퍼에 TypeScript 타입. 그것은 위젯 런타임을 번들하지 않으니, 당신의 게임이 작게 유지됩니다.
2. 게임 팩토리 등록하기
게임은 팩토리 함수로 register를 한 번 호출하는 것입니다. 위젯은 샌드박스된 iframe 안에서 당신의 팩토리를 호출합니다; 그 호출이 그 자체로 시작 신호입니다(기다릴 별도의 시작 이벤트가 없습니다).
import { register } from "@caputchin/game-sdk";
register((container, bridge, ctx) => {
// container - a DOM element inside the sandboxed iframe; render into it.
// bridge - push-only channel to the host (pass / error / setSize).
// ctx - the per-round context (seed + resolved locale/skin/config).
const cleanup = startGame(container, bridge, ctx);
// Return an optional cleanup function; the widget calls it on unmount.
return cleanup;
});당신은 register에 매니페스트를 넘기지 않습니다; 서버가 색인 시점에 caputchin.json을 읽고 해소된 프리셋을 ctx로 당신의 팩토리에 내려보냅니다. 전체 표면은 SDK 레퍼런스를 보세요.
3. 라운드별 컨텍스트에서 렌더링하기
팩토리의 세 번째 인자 ctx는 방문자마다 바뀌는 모든 것을 지닙니다:
ctx.seed- 라운드별 시드. 모든 무작위성을 이것에서 도출하세요(5단계 참고). 검증된 세션 밖에서는null.ctx.locale- 해소된 언어 문자열(ctx.locale._lang에 당신의 키), 또는null.ctx.skin- 해소된 색상과 자산 URL(ctx.skin._theme, 늘light또는dark, 에 당신의 키), 또는null.ctx.config- 해소된 게임플레이 구성, 또는null.
이것들에서 당신 자신의 키를 읽으세요; 당신은 결코 직접 프리셋을 해소하지 않습니다. 당신의 매니페스트가 맞는 블록을 선언하지 않으면 각각 null이니, 늘 내장 기본값으로 물러나세요:
function startGame(container, bridge, ctx) {
const title = ctx.locale?.title ?? "Tap the targets";
const accent = ctx.skin?.accent_color ?? "#2da44e";
const targetCount = ctx.config?.target_count ?? 5;
// ...render with these...
}당신의 레이아웃에 명시적 크기가 필요하면, 첫 페인트 뒤에 bridge.setSize(width, height)를 한 번 호출하세요.
4. 승리, 패배, 오류
당신의 게임이 플레이어가 언제 이기는지 정하고 브리지를 통해 호스트에 알립니다:
- 승리 시, 라운드의 트레이스(5단계)로
bridge.pass({ trace })를 호출하세요. - 패배나 포기 시, 아무것도 호출하지 마세요; 침묵이 실패 신호입니다.
- 게임 자체가 깨지면(자산 실패, 예외),
bridge.error({ code, message })를 호출하세요. 그것은 플레이어 패배가 아니라 게임 내부 실패를 위한 것입니다.
function onWin(traceString) {
bridge.pass({ trace: traceString });
}
function onAssetFailure(err) {
bridge.error({ code: "asset-load-failed", message: String(err) });
}5. 트레이스 기록하기
이것이 게임을 재생 가능하게 만드는 단계입니다. 플레이어가 행동하면서, 결과를 모는 입력(어떤 표적을 어떤 순서로 맞췄는지, 중요하면 타이밍과 함께)을 기록하고 그 기록을 문자열이나 바이트 배열로 직렬화하세요: 그것이 당신의 트레이스입니다. 시드와 결합해, 트레이스는 당신의 로직이 정확한 결과를 재현하게 해야 하는데, 서버가 그것을 다시 실행하기 때문입니다.
두 규칙이 그것을 가능하게 합니다:
- 모든 무작위 선택을
ctx.seed에서 도출하세요. 결과에 영향을 주는 어떤 것에도 결코Math.random()을 호출하거나 벽시계를 읽지 마세요. - 리플레이할 만큼 충분히 기록하세요. 트레이스에 시드를 더한 것이 당신의 게임 로직에 대한 완전한 입력입니다.
function makeRng(seed) {
// seed is ctx.seed; feed it so the server reproduces the same sequence.
let s = hashSeed(seed);
return () => (s = (s * 1103515245 + 12345) & 0x7fffffff) / 0x7fffffff;
}seed, 트레이스, 판정의 모양은 리플레이 계약이 정합니다; 그 페이지는 이 기록된 플레이를 서버가 리플레이하는 헤드리스 run 산출물로 바꾸는 것을 다룹니다. 결정론적 로직을 손으로 쓰는 것이 까다롭게 들리면, 엔진 키트가 선택적으로 그것을 당신을 위해 합니다.
6. 샌드박스를 위해 번들하기
위젯은 정확히 하나의 스크립트 URL을 로드하니, 모든 것이 그 한 파일에 있어야 합니다. 당신의 번들러를 하나의 자족적 출력으로 구성하세요:
- 자산(스프라이트, 사운드, 폰트)을 데이터 URL로 인라인;
- 코드 분할 비활성화;
- WASM을 쓰면, base64로 임베드하고 바이트에서 인스턴스화.
불투명 오리진, 엄격한 CSP iframe 안에서 동작하지 않는 패턴:
- 경로 상대
fetch('./sprite.png')- 가져올 경로가 없음; - 동적
import('./chunk.js')- 두 번째 URL이 차단됨; new Worker('./worker.js')- 대신 인라인BlobURL에서 워커를 띄우세요;- 런타임의 외부 CDN 가져오기 -
connect-src가 그것들을 차단함.
7. 로컬에서 테스트하기
특별한 하니스는 없습니다. 위젯을 정적 HTML 페이지에 임베드하고, game-src를 당신의 로컬 번들 출력으로 향하게 하고, 브라우저에서 플레이하세요:
<caputchin-game sitekey="cpt_pub_..." game-src="http://localhost:8080/game.js"></caputchin-game>이것은 커스텀 게임이 쓰는 같은 game-src 경로입니다; 마켓플레이스에서는 대신 저장소를 공개해 플랫폼이 당신을 위해 번들을 고정하게 합니다.
다음 단계
- 리플레이 계약: 당신의 기록된 플레이를 게임을 재생 가능하게 만드는
run산출물로 바꾸기. - caputchin.json 매니페스트: 게임, 그 프리셋, 그 번들 설명하기.
- 마켓플레이스에 공개하기: 저장소를 태그하고 라이브로 가기.
함께 보기
- 게임 SDK 레퍼런스: 모든 export, 전부.
- engine-kit: 결정론을 무료로 얻는 선택적 방법.