Bangun game marketplace
Di akhir tutorial ini kamu akan punya game Caputchin lengkap yang bisa dimainkan dalam satu bundel JavaScript, siap dibuat bisa-diputar-ulang dan diterbitkan. Ini versi membosankan, lakukan-tiap-langkah; baca Kirim game ke marketplace dulu untuk di mana ia cocok.
Kamu butuh Node dan sebuah bundler (esbuild, rollup, vite, atau webpack, salah satu). Kamu tak butuh akun Caputchin untuk membangun, hanya untuk menerbitkan.
1. Pasang SDK
npm install @caputchin/game-sdkSDK mungil: sebuah helper register plus tipe TypeScript. Ia tak membundel runtime widget, jadi game-mu tetap kecil.
2. Daftarkan sebuah game factory
Sebuah game adalah satu panggilan ke register dengan fungsi factory. Widget memanggil factory-mu di dalam iframe ber-sandbox; panggilan itu sendiri adalah sinyal mulai (tak ada event mulai terpisah untuk ditunggu).
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;
});Kamu tak melewatkan manifest ke register; server membaca caputchin.json saat-indeks dan mengirim preset terselesaikan ke factory-mu sebagai ctx. Lihat referensi SDK untuk permukaan penuhnya.
3. Render dari konteks per-ronde
Argumen ketiga factory, ctx, membawa semua yang berubah per pengunjung:
ctx.seed- seed per-ronde. Turunkan semua keacakan dari ini (lihat langkah 5).nulldi luar sesi terverifikasi.ctx.locale- string bahasa terselesaikan (ctx.locale._langplus kunci-mu), ataunull.ctx.skin- warna dan URL aset terselesaikan (ctx.skin._theme, selalulightataudark, plus kunci-mu), ataunull.ctx.config- konfigurasi gameplay terselesaikan, ataunull.
Baca kunci-mu sendiri dari ini; kamu tak pernah menyelesaikan preset sendiri. Masing-masing null saat manifest-mu mendeklarasikan tanpa blok cocok, jadi selalu jatuh ke default bawaan:
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...
}Jika tata letakmu butuh ukuran eksplisit, panggil bridge.setSize(width, height) sekali setelah cat pertamamu.
4. Menang, kalah, dan galat
Game-mu memutuskan kapan pemain menang dan memberi tahu host lewat jembatan:
- Saat menang, panggil
bridge.pass({ trace })dengan trace ronde (langkah 5). - Saat kalah atau ditinggalkan, panggil tak ada; keheningan adalah sinyal kegagalan.
- Jika game itu sendiri rusak (aset gagal, eksepsi), panggil
bridge.error({ code, message }). Itu untuk kegagalan internal-game, bukan pemain kalah.
function onWin(traceString) {
bridge.pass({ trace: traceString });
}
function onAssetFailure(err) {
bridge.error({ code: "asset-load-failed", message: String(err) });
}5. Rekam sebuah trace
Inilah langkah yang membuat game bisa-diputar-ulang. Selagi pemain bertindak, rekam input yang mengemudikan hasil (target mana yang mereka kenai, dalam urutan, dengan waktu jika penting) dan serialisasikan catatan itu ke string atau array byte: itu adalah trace-mu. Digabung dengan seed, trace harus membiarkan logikamu mereproduksi hasil persis, karena server menjalankannya-ulang.
Dua aturan membuat itu mungkin:
- Turunkan setiap pilihan acak dari
ctx.seed. Jangan pernah panggilMath.random()atau membaca jam dinding untuk apa pun yang memengaruhi hasil. - Rekam cukup untuk memutar-ulang. Trace plus seed adalah input lengkap ke logika game-mu.
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;
}Bentuk seed, trace, dan vonis didefinisikan oleh kontrak putar-ulang; halaman itu mencakup mengubah permainan terekam ini menjadi artefak run headless yang dijalankan-ulang server. Jika menulis-tangan logika deterministik terdengar rewel, kit engine melakukannya untukmu, opsional.
6. Bundel untuk sandbox
Widget memuat persis satu URL skrip, jadi semua harus ada di satu berkas itu. Konfigurasi bundler-mu untuk satu keluaran mandiri:
- inline aset sebagai data URL (sprite, suara, font);
- nonaktifkan pemisahan kode;
- jika kamu memakai WASM, sematkan ia sebagai base64 dan instansiasi dari byte.
Pola yang tidak berfungsi di dalam iframe ber-origin-opaque, CSP-ketat:
fetch('./sprite.png')relatif-path - tak ada path untuk diambil;import('./chunk.js')dinamis - URL kedua diblokir;new Worker('./worker.js')- munculkan worker dari URLBlobinline sebagai gantinya;- pengambilan CDN eksternal saat runtime -
connect-srcmemblokirnya.
7. Uji ia secara lokal
Tak ada harness khusus. Sematkan widget di halaman HTML statis, arahkan game-src ke keluaran bundel lokalmu, dan mainkan di peramban:
<caputchin-game sitekey="cpt_pub_..." game-src="http://localhost:8080/game.js"></caputchin-game>Ini adalah jalur game-src yang sama yang dipakai game kustom; untuk marketplace kamu akan menerbitkan repo sebagai gantinya agar platform memin bundel untukmu.
Langkah berikutnya
- Kontrak putar-ulang: ubah permainan terekam-mu menjadi artefak
runyang membuat game bisa-diputar-ulang. - Manifest caputchin.json: deskripsikan game, preset, dan bundel-nya.
- Terbitkan ke marketplace: tag repo dan tayang.
Lihat juga
- Referensi game SDK: setiap ekspor, secara penuh.
- engine-kit: cara opsional mendapat determinisme gratis.