ابنِ لعبة المتجر
بنهاية هذا الدرس سيكون لديك لعبة Caputchin كاملة قابلة للّعب في حزمة JavaScript واحدة، جاهزة لجعلها قابلة لإعادة التشغيل ونشرها. هذه النسخة المملّة، افعل-كل-خطوة؛ اقرأ اشحن لعبة إلى المتجر أولًا لمكانها.
تحتاج إلى Node ومُجمِّع (esbuild، أو rollup، أو vite، أو webpack، أيٌّ منها). لا تحتاج إلى حساب Caputchin للبناء، بل للنشر فقط.
1. ثبّت الـ SDK
npm install @caputchin/game-sdkالـ SDK ضئيل: مساعد 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- الألوان وروابط الأصول المحلولة (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. الفوز والخسارة والأخطاء
تقرّر لعبتك متى يفوز اللاعب وتخبر المضيف عبر الجسر:
- عند الفوز، ناد
bridge.pass({ trace })بـ أثر الجولة (الخطوة 5). - عند الخسارة أو الهجر، ناد لا شيء؛ الصمت إشارة الفشل.
- إن انكسرت اللعبة نفسها (فشل أصل، أو استثناء)، ناد
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. احزم للعزل
تحمّل الأداة رابط سكربت واحد بالضبط، فيجب أن يكون كل شيء في ذلك الملفّ الواحد. أعدّ مُجمِّعك لمخرَج واحد مكتفٍ بذاته:
- ضمّن الأصول كروابط data (الصور النقطية، والأصوات، والخطوط)؛
- عطّل تقسيم الكود؛
- إن استخدمت WASM، ضمّنه كـ base64 وأنشئه من بايتات.
أنماط لا تعمل داخل إطار iframe بأصل معتم بـ CSP صارم:
fetch('./sprite.png')نسبيّ المسار - لا مسار للجلب منه؛import('./chunk.js')ديناميكي - الرابط الثاني محجوب؛new Worker('./worker.js')- ولّد العمّال من روابطBlobمضمَّنة بدلًا؛- جلب 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 اللعبة: كل تصدير، كاملًا.
- عدّة engine-kit: الطريقة الاختيارية للحصول على الحتمية مجانًا.