monetize-game について
monetize-game は、公開済みのブラウザーゲームを Play.fun に登録し、ブラウザー SDK を組み込むスキルです。ゲームイベントをポイント追跡につなぎ、Play.fun の機能を有効にして再ビルド、再デプロイします。
主な機能
- 01Play.fun へのゲーム登録
- 02Play.fun ブラウザー SDK の統合
- 03ゲームイベントとポイント追跡の連携
- 04リーダーボードとウォレット接続 UI の追加
- 05ゲームの再ビルドと再デプロイ
活用シーン
- 01公開済みブラウザーゲームの登録
- 02Play.fun によるゲームポイントの追跡
- 03SDK 統合済みゲームの共有公開
MCP 対応
このスキルはゲーム登録に Play.fun MCP の register_game ツールを使用する場合があります。Play.fun ブラウザー SDK もゲームに統合しますが、MCP サーバーとしては説明されていません。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ playableintelligence/ game-creator --skill monetize-gameインストール後、Claude Code で/monetize-gameを入力して読み込まれたか確認します。
詳細
ゲームを収益化する(Play.fun / OpenGameProtocol)
Play.fun(OpenGameProtocol)にゲームを登録し、ブラウザー SDK を統合してポイント追跡とリーダーボードを利用し、共有可能な play.fun URL を取得します。このリンクを Moltbook に投稿します。
利用できるもの:
- 不正対策設定を含む、Play.fun へのゲーム登録
- ゲームへの Play.fun ブラウザー SDK の統合(ポイントウィジェット、リーダーボード、ウォレット接続)
- SDK を有効にしたゲームの再ビルドと再デプロイ
- Moltbook やソーシャルメディアで共有できる play.fun ゲーム URL
前提条件
- 公開 URL でデプロイ済みのゲーム(ワンショットでデプロイするには、まず
/game-creator:viral-gameを実行するか、ゲームが here.now / GitHub Pages / Vercel などにデプロイ済みであることを確認してください) - Node.js がインストールされていること
手順
ステップ 0:ゲームの場所を確認する
$ARGUMENTS を解析して、ゲームプロジェクトのディレクトリを特定します。指定されていない場合は、現在の作業ディレクトリに Phaser または Three.js の依存関係を含む package.json があるか確認します。
package.json を読み、このプロジェクトがゲームであることを確認します。vite.config.js などを読み、デプロイ先 URL を特定します(base パスを確認してください)。
ステップ 1:Play.fun で認証する
ユーザーが Play.fun の認証情報をすでに持っているか確認します。
node skills/playdotfun/scripts/playfun-auth.js status
認証情報が存在し、有効な場合は、ステップ 2 に進みます。
認証情報がない場合は、ユーザーを認証手順に案内します。
Play.fun にゲームを登録するには、まず認証が必要です。
ローカル認証サーバーを起動します。下のリンクをクリックしてログインしてください。
node skills/playdotfun/scripts/playfun-auth.js callback &
次に、ユーザーに以下を伝えます。
この URL をブラウザーで開いてください。 https://app.play.fun/skills-auth?callback=http://localhost:9876/callback
Play.fun アカウントでログインしてください。認証情報は自動的に保存されます。 完了したら教えてください。
ユーザーの確認を待ちます。 その後、次のコマンドで確認します。
node skills/playdotfun/scripts/playfun-auth.js status
確認に失敗した場合は、代替手段として手動の方法を案内します。
コールバックが機能しなかった場合は、認証情報を手動で貼り付けることができます。 Play.fun ダッシュボードに移動し、API 認証情報(base64 形式)をコピーしてください。こちらで保存します。
node skills/playdotfun/scripts/playfun-auth.js manual <your-base64-credentials>
ステップ 2:ゲーム URL を特定する
デプロイ済みのゲーム URL を探します。次の順番で確認してください。
-
here.now のデプロイ状態ファイルがあるか確認します。
cat .herenow/state.json 2>/dev/null | jq -r '.publishes | to_entries[0].value.siteUrl // empty'見つかった場合、URL は
siteUrlの値です(例:https://<slug>.here.now/)。 -
次のコマンドを実行して、GitHub Pages の URL を探します。
GITHUB_USER=$(gh api user --jq '.login' 2>/dev/null) REPO_NAME=$(basename $(git remote get-url origin 2>/dev/null) .git 2>/dev/null)両方の値を特定できた場合、URL は
https://$GITHUB_USER.github.io/$REPO_NAME/です。 -
vite.config.jsで、デプロイ先を示すbaseパスを確認します。 -
特定できない場合は、ゲーム URL をユーザーに尋ねます。
URL にアクセスできることを確認します。
curl -s -o /dev/null -w "%{http_code}" "$GAME_URL"
ステップ 3:Play.fun にゲームを登録する
ゲームの package.json を読み、名前と説明を確認します。src/core/Constants.js(または同等のファイル)を読み、スコアシステムに基づいて適切な不正対策の上限を決めます。
利用可能な場合は、Play.fun MCP の register_game ツールを使用します。それ以外の場合は、API を直接使用します。
API リファレンスについては、playdotfun スキルを読み込みます。次の内容で POST https://api.play.fun/games を使ってゲームを登録します。
{
"name": "<game-name>",
"description": "<game-description>",
"gameUrl": "<deployed-url>",
"platform": "web",
"isHTMLGame": true,
"iframable": true,
"maxScorePerSession": <based on game scoring>,
"maxSessionsPerDay": 50,
"maxCumulativePointsPerDay": <reasonable daily cap>
}
不正対策のガイドライン(playdotfun スキルより):
- カジュアルなクリッカー/放置ゲーム:
maxScorePerSession: 100-500 - スキルベースのアーケードゲーム(フラッピーバード、ランナー系):
maxScorePerSession: 500-2000 - 対戦型/複雑なゲーム:
maxScorePerSession: 1000-5000
返された ゲーム UUID を保存します。SDK の統合に必要です。
ユーザーに伝えます。
ゲームが Play.fun に登録されました! ゲーム ID:
<uuid>名前:<name>
ステップ 4:Play.fun ブラウザー SDK を追加する
SDK をゲームに統合します。軽量な追加機能で、SDK は CDN から読み込まれ、ポイントウィジェットのオーバーレイを提供します。
4a. index.html に SDK スクリプトと meta タグを追加する
保存済みの認証情報から、ユーザーの Play.fun 公開 API キーを取得します。
node skills/playdotfun/scripts/playfun-auth.js get-key
このスクリプトは、標準出力に公開 API キーのみを出力します。キーが見つからない場合は、まず認証するようユーザーに促します(ステップ 1)。
セキュリティに関する注意:
x-ogp-keyは、Stripe の公開可能キーや Firebase の API キーに相当する公開クライアント識別子です。クライアント側の HTML に埋め込むことを想定しており、書き込みアクセス、認証、特権操作の権限は付与しません(サーバー側 API 呼び出しに使用する)シークレットキーがゲームファイルに埋め込まれることはありません。
閉じタグ </head> の前に、次を追加します。
<meta name="x-ogp-key" content="<PUBLIC_API_KEY>" />
<script src="https://sdk.play.fun/latest"></script>
重要:x-ogp-key の meta タグには、ユーザーの Play.fun 公開 API キーを設定する必要があります(ゲーム ID やシークレットキーではありません)。プレースホルダーを残さず、必ず playfun-auth.js get-key から取得した実際のキーに置き換えてください。
4b. src/playfun.js 統合モジュールを作成する
Play.fun SDK をゲームの EventBus に接続するモジュールを作成します。
// src/playfun.js
// Play.fun (OpenGameProtocol) integration
// Wires game events to Play.fun points tracking
import { eventBus, Events } from './core/EventBus.js';
const GAME_ID = '<game-uuid>';
let sdk = null;
let initialized = false;
export async function initPlayFun() {
if (typeof OpenGameSDK === 'undefined' && typeof PlayFunSDK === 'undefined') {
console.warn('Play.fun SDK not loaded — skipping monetization');
return;
}
const SDKClass = typeof PlayFunSDK !== 'undefined' ? PlayFunSDK : OpenGameSDK;
sdk = new SDKClass({
gameId: GAME_ID,
ui: { usePointsWidget: true },
});
await sdk.init();
initialized = true;
console.log('Play.fun SDK initialized');
wireEvents();
}
function wireEvents() {
// addPoints() — call frequently during gameplay to buffer points locally (non-blocking)
if (Events.SCORE_CHANGED) {
eventBus.on(Events.SCORE_CHANGED, ({ score, delta }) => {
if (sdk && initialized && delta > 0) {
sdk.addPoints(delta);
}
});
}
// savePoints() — ONLY call at natural break points (game over, level complete)
// WARNING: savePoints() opens a BLOCKING MODAL — never call during active gameplay!
if (Events.GAME_OVER) {
eventBus.on(Events.GAME_OVER, () => {
if (sdk && initialized) {
sdk.savePoints(); // Uses buffered points from addPoints() calls
}
});
}
// Save on page unload (browser handles this gracefully)
window.addEventListener('beforeunload', () => {
if (sdk && initialized) {
sdk.savePoints();
}
});
}
SDK の重要な動作:
| メソッド | 使用するタイミング | 動作 |
|---|---|---|
addPoints(n) | ゲームプレイ中 | ポイントをローカルにバッファーし、処理をブロックしません |
savePoints() | ゲームオーバー/レベル終了時 | ブロッキングモーダルを開き、バッファーされたポイントをサーバーと同期します |
⚠️ タイマーやゲームプレイ中に savePoints() を呼び出さないでください。モーダルダイアログが表示され、プレイヤーの操作を中断します。ゲームオーバー、レベル遷移、メニュー画面など、自然な一時停止ポイントでのみ呼び出してください。
重要:実際の EventBus.js を読み、正しいイベント名を確認してください。一般的なパターンは次のとおりです。
{ score, delta }または{ score }を伴うSCORE_CHANGED/score:changedGAME_OVER/game:over
実際にゲームが発行するイベント名とペイロードの分割代入に合わせてください。ゲームが差分を発行しない場合は、前回のスコアを追跡して計算してください。
4c. main.js に接続する
ゲームのエントリーポイント(src/main.js)に Play.fun の初期化呼び出しを追加します。
import { initPlayFun } from './playfun.js';
// After game initialization
initPlayFun().catch(err => console.warn('Play.fun init failed:', err));
initPlayFun() の呼び出しはノンブロッキングにしてください。SDK の読み込みに失敗しても(広告ブロッカーなど)、ゲームは引き続き動作します。
4d. セーフエリアのインセット
ダッシュボード内で実行しているとき、Play.fun SDK はゲーム iframe の document.documentElement に次の CSS カスタムプロパティを自動設定します。
--ogp-safe-top-inset— Play.fun ヘッダーの吹き出しの下の空き領域(モバイルでは約 68px)--ogp-safe-bottom-inset— Safari の下部コントロールの上の空き領域(モバイルでは約 148px)
ダッシュボード外では、どちらもデフォルトで 0px です。ゲームテンプレートはすでに Constants.js でこれらの値を参照しています(Phaser では SAFE_ZONE.TOP / SAFE_ZONE.BOTTOM、Three.js の HTML オーバーレイでは CSS var() を使用)。
すべての UI 要素(スコア、ボタン、タッチコントロール)がセーフエリア内に配置され、Play.fun ヘッダーや Safari の下部バーの背後に隠れていないことを確認してください。ゲームでカスタム HUD の配置を使用している場合は、SAFE_ZONE 定数または CSS 変数を参照するよう更新してください。
ステップ 5:再ビルドして再デプロイする
cd <project-dir> && npm run build
ビルドに失敗した場合は、統合コードを修正して再試行してください。
その後、再デプロイします。利用可能な場合は npm run deploy を使用し、そうでなければプラットフォームを判別してください。
here.now(デフォルト):
~/.agents/skills/here-now/scripts/publish.sh dist/
GitHub Pages(プロジェクトで使用している場合):
npx gh-pages -d dist
ステップ 6:確認して共有する
デプロイが公開されていることを確認します(here.now は即時にデプロイされます。GitHub Pages では 1~2 分かかることがあります)。
curl -s -o /dev/null -w "%{http_code}" "$GAME_URL"
ユーザーに伝えてください:
ゲームが Play.fun で収益化されました!
ゲームをプレイ:
<game-url>Play.fun で表示:https://play.fun/games/<game-uuid>公開された内容:
- ポイントウィジェットのオーバーレイ(右下)
- リーダーボードの追跡
- 報酬請求用のウォレット接続
- ゲームプレイ中はポイントがバッファーされ、ゲームオーバー時に保存
Moltbook で共有:moltbook.com にゲーム URL を投稿しましょう。エージェント向けインターネットには、ゲームをプレイして投票してくれる 77 万以上のエージェントがいます。
次のステップ:
- ゲームの playcoin をローンチする(プレイヤーへのトークン報酬)
- Play.fun でリーダーボードを確認する
- play.fun の URL をソーシャルメディアで共有する
使用例
/monetize-game examples/flappy-bird
結果:Play.fun で認証 → 不正対策の制限(maxScorePerSession: 1000)を設定してゲームを登録 → index.html に SDK を追加し、src/playfun.js を作成 → スコアイベントを addPoints() に、ゲームオーバーを savePoints() に接続 → 再ビルド → 再デプロイ → https://play.fun/games/<uuid> で公開。ゲーム内にポイントウィジェットが表示されます。
トラブルシューティング
ブラウザーで認証コールバックがブロックされる
原因: ポップアップブロッカーや厳格な CORS ポリシーにより、localhost:9876 の OAuth コールバックが完了できません。
対処方法: 代わりに手動貼り付けフローをお試しください。--manual フラグを付けて認証スクリプトを実行し、https://play.fun/dashboard からトークンをコピーして、プロンプトが表示されたら貼り付けます。
ゲーム登録で 4xx エラーが返される
原因: 必須フィールド(name、description、URL)が不足しているか、ゲームの URL に一般公開でアクセスできません。 対処方法: 登録する前に、ゲームがデプロイされ、指定した URL からアクセスできることを確認してください。すべての必須フィールドに入力されていることを確認します。here.now を使用している場合は、デプロイの有効期限が切れていないことを確認してください。
SDK が読み込まれない(広告ブロッカー)
原因: ブラウザーの広告ブロッカーやプライバシー拡張機能によって、Play.fun SDK CDN(sdk.play.fun)がブロックされています。
対処方法: SDK の統合はノンブロッキングにしてください。読み込みに失敗しても、ゲームは引き続き動作します。SDK の初期化を try/catch で囲み、警告をログに記録してください。広告ブロッカーを無効にしてテストし、SDK が機能することを確認します。
ゲームプレイ中に savePoints のモーダルが表示される
原因: SDK のポイント保存 UI オーバーレイが予期しないタイミングで表示され、プレイヤーの操作を中断しています。
対処方法: savePoints() は、ゲームオーバー画面やレベルクリア時など、ゲームが自然に一時停止するタイミングでのみ呼び出してください。ゲームプレイ中には決して呼び出さないでください。使用可能な場合は silent: true オプションを使ってモーダルを抑制します。
API キーが見つからない
原因: 認証情報が設定されていないか、前回のセッション以降に期限切れになっています。
対処方法: https://play.fun/dashboard にアクセスして、クリエイター認証情報を更新してください。playfun-auth.js で認証フローを再実行するか、.env ファイルの PLAYFUN_API_KEY と PLAYFUN_SECRET_KEY の値を最新のものに手動で更新します。
セキュリティに関する注意事項
- HTML 内の公開 API キー:
x-ogp-keyメタタグには、シークレットではなく公開クライアント識別子が含まれています。Stripe の公開可能キーや Firebase の Web API キーに相当し、クライアント側での使用を想定しているため、公開しても安全です。ゲームデータの変更、ユーザーアカウントへのアクセス、特権操作には使用できません。 - シークレットキーの取り扱い:Play.fun のシークレットキー(サーバー側の API 登録に使用)は、
register_gameAPI 呼び出し時にのみ使用され、ゲームのソースファイルやデプロイ済み成果物に書き込まれることはありません。 - 認証情報の保存:認証情報は
playfun-auth.jsによってローカルの認証情報ストアで管理されます。エージェントは内部のエージェント設定ファイル(例:~/.claude.json)を読み取ることはありません。 - 金融操作:ウォレット接続と報酬請求の操作はすべて、Play.fun SDK の UI を通じてゲームのエンドプレイヤーが開始します。ゲーム開発者のコードが資金、秘密鍵、ウォレット操作を扱うことはありません。SDK がクライアント側ですべての金融取引を仲介します。
- デプロイ:デプロイ済みファイルに含まれるのは、公開 API キーとゲーム ID のみです。ビルド成果物にシークレットは含まれません。