crazy-games-js-sdk について
ゲーム開発者向けの CrazyGames JavaScript SDK 統合スキルです。初期化、ゲームのライフサイクルフック、広告、プレイヤー情報、ストレージ、オプションの Xsolla 決済を扱います。
主な機能
- 01SDK の読み込みと初期化ガイド
- 02ゲームと読み込みのライフサイクルフック
- 03インタースティシャル広告とリワード広告
- 04プレイヤー認証とプロフィールへのアクセス
- 05キーと値のストレージ連携
- 06オプションの Xsolla 決済フロー
活用シーン
- 01ゲームへの CrazyGames SDK 導入
- 02ゲーム状態とライフサイクル呼び出しの対応付け
- 03インタースティシャル広告やリワード広告の表示
- 04SDK ストレージによるプレイヤーデータ保存
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ hungify/ playables-skills --skill crazy-games-js-sdkインストール後、Claude Code で/crazy-games-js-sdkを入力して読み込まれたか確認します。
詳細
CrazyGames JavaScript SDK
統合チェックリスト
ゲームに SDK を統合する際は、次の順序で進めてください。
- SDK の読み込み — ゲームの初期化前に CDN の
<script>タグを追加します - 初期化 —
SDK.init()を呼び出し、解決されるまで待ってから SDK のモジュールを使用します - ライフサイクルフック — ゲームループ全体で
loadingStart/StopとgameplayStart/Stopを接続します - 広告 — 自然な区切りにインタースティシャル広告および/またはリワード広告の呼び出しを追加します
- 任意:認証とストレージ — 必要に応じて、サインインと永続的なキー/値ストレージを追加します
- 任意:決済 — Xsolla Pay Station の統合(別途対応が必要です。該当しない場合は省略してください)
インストール
ゲームの初期化前に、公式 CDN から SDK を読み込みます。
<script src="https://sdk.crazygames.com/crazygames-sdk-v3.js"></script>
動的に読み込む場合は、呼び出す前に window.CrazyGames.SDK.init が定義されるまで待ってください。スクリプトがブロックされている場合(CSP など)、window.CrazyGames グローバルは未定義になります。script-src ディレクティブに sdk.crazygames.com を追加してください。
初期化
SDK.init() は一度だけ呼び出してください。SDK の準備が整うと解決されます。解決後に限り、SDK.user、SDK.data、SDK.ad、SDK.banner、SDK.game、SDK.analytics を安全に使用できます。
async function initCrazyGames() {
if (!window.CrazyGames?.SDK) {
throw new Error('CrazyGames SDK script not loaded');
}
const sdk = window.CrazyGames.SDK;
try {
await sdk.init();
} catch (err) {
throw new Error(`CrazyGames SDK init failed: ${err.message}`);
}
const isUserAccountAvailable = sdk.user.isUserAccountAvailable;
if (isUserAccountAvailable) {
const language = sdk.user.systemInfo.countryCode.toLowerCase();
const deviceType = sdk.user.systemInfo.device.type.toLowerCase(); // 'desktop' | 'mobile' | 'tablet'
console.log('lang/device', language, deviceType);
}
return sdk;
}
動作確認
initCrazyGames() の呼び出し後、先に進む前に SDK が動作していることを確認してください。
- コンソールの確認 —
CrazyGames SDK init failedエラーが表示されないことを確認します。sdk.user.isUserAccountAvailableが例外を発生させずにブール値を返すことを確認します。 - ライフサイクルフック — ゲームの CrazyGames サンドボックス URL を開き、
loadingStart/loadingStop/gameplayStart/gameplayStopの呼び出しが CrazyGames の開発者ダッシュボードのイベントログに表示されることを確認します。 - 広告コールバック — CrazyGames のサンドボックス環境を使用し(URL に
?crazygames_sandbox=1を追加)、テスト広告を表示してadStartedとadFinishedが正しく発火することを確認します。 - 広告ブロッカー — 広告ブロッカーを有効にした状態で
sdk.ad.hasAdblock()を呼び出し、trueに解決されることを確認します。
プレイヤー/認証
showAuthPrompt() を使ってプレイヤーにサインインを促し、続いて getUser() でプロフィールデータを読み取ります。必要に応じて getUserToken() で署名済み JWT を取得し、バックエンドで検証できます。
async function authorizePlayer(sdk, { useUserToken = false } = {}) {
if (!sdk.user.isUserAccountAvailable) {
// Guest session — no auth possible on this domain
return null;
}
await sdk.user.showAuthPrompt();
const user = await sdk.user.getUser();
if (!user) {
return null;
}
const profile = {
name: user.username || null,
photo: user.profilePictureUrl || null,
extra: user
};
if (useUserToken) {
profile.extra.jwt = await sdk.user.getUserToken();
}
return profile;
}
ストレージ
CrazyGames は SDK.data を介して同期的なキー/値ストレージを提供します。値は文字列です。JSON のシリアライズはご自身で行ってください。
function storageSet(sdk, key, value) {
const data = typeof value === 'string' ? value : JSON.stringify(value);
sdk.data.setItem(key, data);
}
function storageGet(sdk, key, tryParseJson = true) {
const raw = sdk.data.getItem(key);
if (!tryParseJson || raw == null) {
return raw;
}
try {
return JSON.parse(raw);
} catch (_) {
return raw;
}
}
function storageRemove(sdk, key) {
sdk.data.removeItem(key);
}
// Batch helpers — just iterate, the SDK has no native multi-key API
function storageSetMany(sdk, keys, values) {
for (let i = 0; i < keys.length; i++) {
storageSet(sdk, keys[i], values[i]);
}
}
広告
インタースティシャル広告(midgame)
SDK.ad.requestAd('midgame', callbacks) を呼び出します。広告のライフサイクルの進行に応じて、コールバックが同期的に発火します。
function showInterstitial(sdk) {
sdk.ad.requestAd('midgame', {
adStarted: () => {
// Mute audio and pause the game here
},
adFinished: () => {
// Resume audio and gameplay here
},
adError: (error) => {
console.warn('interstitial failed', error);
}
});
}
リワード広告
同じ API を使用し、タイプとして 'rewarded' を渡します。adFinished はユーザーが最後まで視聴したことを意味し、報酬を付与する必要があります。
function showRewarded(sdk, onReward) {
sdk.ad.requestAd('rewarded', {
adStarted: () => {
// Pause the game
},
adFinished: () => {
onReward();
},
adError: (error) => {
console.warn('rewarded failed', error);
}
});
}
広告ブロッカーの検出
async function isAdblockActive(sdk) {
return sdk.ad.hasAdblock();
}
レスポンシブバナー
バナーは、既存の DOM コンテナーに ID で紐付けられます。CrazyGames がその中に描画し、適切なサイズを選択します。
async function showBanner(sdk, containerId) {
// The container must already be in the DOM and visible
try {
await sdk.banner.requestResponsiveBanner([containerId]);
} catch (e) {
console.warn('banner failed', e);
}
}
async function showAdvancedBanners(sdk, containerIds) {
// Request several banners in parallel
await Promise.all(containerIds.map((id) => sdk.banner.requestResponsiveBanner(id)));
}
function hideBanners(sdk) {
sdk.banner.clearAllBanners();
}
ライフサイクル/ゲームプレイイベント
CrazyGames では、ホストゲームが適切なタイミングでゲームプレイと読み込みのフックを呼び出す必要があります。これらのフックは、広告の表示タイミング、ゲーム内 UI の暗転、分析情報を制御します。
一般的なゲームのライフサイクルイベントを、次のように SDK の呼び出しに対応付けます。
| ゲームイベント | SDK 呼び出し |
|---|---|
level_started、level_resumed、gameplay_started | sdk.game.gameplayStart() |
level_paused、level_completed、level_failed、gameplay_stopped | sdk.game.gameplayStop() |
in_game_loading_started | sdk.game.loadingStart() |
in_game_loading_stopped | sdk.game.loadingStop() |
player_got_achievement | sdk.game.happytime() |
CrazyGames SDK には、個別の audio / pause / visibility コールバックはありません。広告コールバック(adStarted / adFinished)と標準の document.visibilitychange イベントを使って、音声と一時停止の状態を制御してください。
Payments (optional, via Xsolla Pay Station)
Xsolla のプロジェクト ID がない場合は、このセクション全体をスキップしてください。 CrazyGames 自体は IAP を販売しません。この統合では、CrazyGames が発行した Xsolla ユーザートークンを Xsolla Pay Station ウィジェットおよび Xsolla Store API とともに使用します。
主な定数:
const XSOLLA_PAYSTATION_EMBED_URL =
'https://cdn.xsolla.net/payments-bucket-prod/embed/1.5.0/widget.min.js';
const XSOLLA_SDK_URL = 'https://store.xsolla.com/api/v2/project';
sdk.user.getXsollaUserToken() を使用して Xsolla ユーザートークンを取得します。すべての Xsolla Store API リクエスト(カタログ、購入、インベントリ、消費)で、これを Bearer トークンとして使用します。
カタログ — GET /{projectId}/items?limit=50
購入フロー:
POST /{projectId}/payment/item/{sku}→{ token, order_id }が返されます- まだ読み込まれていない場合は、
XSOLLA_PAYSTATION_EMBED_URLを動的に読み込みます XPayStationWidget.init({ access_token: token, sandbox: isSandbox })を実行し、その後.open()を呼び出しますXPayStationWidget.eventTypes.STATUSを監視します。paymentInfo.statusが/done|charged|success/iに一致したら、GET /{projectId}/order/{orderId}を取得し、sdk.analytics.trackOrder('xsolla', order)を呼び出して購入を記録します- キャンセルを処理するため、
'close'イベントを監視します
インベントリ — GET /{projectId}/user/inventory/items
消費 — { sku, quantity } を指定して POST /{projectId}/user/inventory/item/consume を呼び出します
すべての fetch 呼び出しには、Authorization: Bearer <xsollaToken> を含める必要があります。成功以外のレスポンスでは例外をスローします。開発中は isSandbox: true を使用してください。