mcpField
P
playproof

playproof

ローカル
github.com開発ツール06 日前に更新

playproof について

playproofは、開発者やコーディングエージェント向けのブラウザーゲームテストツールです。仮想クロックにより、再現可能なフレーム単位の確認、スクリプト操作、クラッシュ検出、デバイスレイアウト検査、性能測定を行えます。

主な機能

  1. 01決定的なフレーム取得と比較
  2. 02スクリプト操作とストーリーボード実行
  3. 03再現可能なランダムクラッシュ探索
  4. 04デバイスサイズ別のレイアウト検査
  5. 05フレームペーシングと性能指標
  6. 06シナリオ別の動作スナップショット

活用シーン

  1. 01アニメーション変更のフレーム単位での確認
  2. 02記録した手順によるゲームクラッシュの再現
  3. 03スマートフォンとデスクトップの画面レイアウト確認
  4. 04CIでの動作・デバイス検査

MCP 対応

playproofは、ツールを呼び出すアプリ向けのMCPサーバーとしても動作し、検査用の画像をツールから直接返します。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"emirhanozl-playproof": {
"command": "npx",
"args": [
"-y",
"playproof"
]
}
}
}
起動コマンドnpx -y playproof

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
npmplayproof0.3.2

ツール

6

掲載時のツール一覧 · 5 日前に更新

パラメーター型必須説明
fpsnumberいいえシート上の1秒あたりのタイル数(デフォルト:約24タイルに合わせて調整)
areastringいいえゲーム領域の CSS セレクター(デフォルト:最大のキャンバス)
zoomstringいいえ動く領域に合わせて切り抜く("auto")か、ゲーム領域に対する割合で x,y,w,h を指定します
readystringいいえゲームの読み込み完了後に true となる JavaScript 式
stepsstringいいえ「;」で手順を区切ります。手順(「;」または改行で区切り、「#」で始まる行はコメント):wait <time> 指定時間待つ(仮想時間:即時かつ正確)tap <x,y>|@label ゲーム領域内をタップ/クリック("50%,80%" またはピクセル座標 "120,300")press <x,y> <time> 長押し drag <x,y> <x,y> [time] スワイプ/ドラッグ(デフォルト 300ms)key <Key> [time] キーを押す。例:Space、ArrowLeft、a、Enter(デフォルトで 50ms 押し続ける)type <text> テキストを入力 click <css selector> DOM 要素(メニュー、HTML ボタン)をクリック shot [label] ストーリーボード用のスクリーンショットを撮影 film <time> [fps] 時間の経過中にフレームをキャプチャ until <js expression> [time] 式が真になるまで時間を進める(デフォルトのタイムアウトは 5s)js <js expression> ページ内で JavaScript を評価し、結果をログに記録 時刻形式:500、500ms、1.5s。
devicestringいいえエミュレートするデバイス:"iPhone 15"、"Pixel 8"、"desktop"(デフォルト)、または "390x844@3 mobile"
targetstringいいえゲームの URL(例:http://localhost:5173)、フォルダー(./dist)、または HTML ファイル。playproof.config.json に設定されている場合は省略可能です。
comparestringいいえ比較対象となる以前の frames 実行の出力フォルダー
waitForstringいいえ開始前に待機する CSS セレクター
durationstringいいえ撮影時間。例:800ms、1.5s(デフォルト 1s)
scenariostringいいえplayproof.config.json 内のシナリオ名。手順、時間、ズーム、デバイスを指定します

詳細

README の画像

playproof

ブラウザーゲームを見る目と動かす手。

npm CI License: MIT Node

コーディングエージェントは数分でウェブゲームを書けますが、ゲームの動きを見届けることはできません。playproof を使えば、エージェント(そしてあなたも)がゲームをフレームごとに確認し、スクリプトによる入力でプレイし、クラッシュを探し、スマートフォンの画面で確認し、動作の滑らかさを測定できます。デスクトップでも、実際の Android スマートフォンでも利用できます。結果はすべて、読み取りやすい画像と、問題がありそうな箇所を示す短い概要として返されます。

不具合のあるゲームのコンタクトシート。2枚の白いちらつきフレームとワープするボールが赤枠で囲まれ、チャートの下に説明がある

Canvas 2D、DOM、Phaser 3、PixiJS 8、three.js、Godot 4 のウェブエクスポート、Unity WebGL ビルドでテスト済みです。それぞれを2回実行しても、同じフレームが得られます(npm run test:engines)。

インストール

エージェントに依頼する

これを Claude Code、Codex、Cursor、Gemini CLI、またはその他のコーディングエージェントに貼り付けます。

Install playproof from https://github.com/EmirhanOzl/playproof

エージェントが自身に適した下記のコマンドを選びます。

Claude Code
claude plugin marketplace add EmirhanOzl/playproof
claude plugin install playproof@playproof
Codex
codex plugin marketplace add EmirhanOzl/playproof
codex plugin add playproof@playproof
Gemini CLI
gemini extensions install https://github.com/EmirhanOzl/playproof
Cursor、OpenCode、GitHub Copilot、その他のエージェント
npx skills add EmirhanOzl/playproof
Claude Desktop、その他の MCP アプリ

コマンドを実行する代わりにツールを呼び出すアプリ向けに、playproof はツールから画像を直接返す MCP サーバーとしても動作します。アプリの MCP 設定に追加してください。

{
  "mcpServers": {
    "playproof": { "command": "npx", "args": ["-y", "playproof", "mcp"] }
  }
}
エージェントを使わない場合

インストールは不要です。ゲームのフォルダーで npx playproof init を実行すると、playproof.config.json が作成されます(開発サーバー、ビルドフォルダー、または HTML ファイルを検出します)。または、任意のコマンドに開発サーバー、ビルドフォルダー、HTML ファイルを直接指定できます。

npx playproof frames http://localhost:5173 --device "Pixel 8" --do "tap 50%,50%" --duration 1s

playproof はインストール済みの Chrome または Edge を使用します。必要に応じて、npx playproof install-browser で専用の Chromium をダウンロードできます。

理由

スクリーンショットで捉えられるのはランダムな一瞬だけなので、ゲームを壊れたように感じさせる要素は見過ごされがちです。動き出す前の予備動作がないジャンプ、ワープするスプライト、1フレームだけのちらつき、何も起きないボタン、何百回もタップした後のクラッシュ、どのスマートフォンでもぼやけるキャンバスなどです。

playproof はゲームを仮想クロックで実行します。時間は playproof が進めたときだけ、正確に1フレームずつ進みます。そのため、どの瞬間も記録でき、実行するたびに同じピクセルが得られます。さらに、モデル(または人)が実際に確認できるようにフレームを並べます。実行結果が毎回まったく同じなので、エージェントは動きを記録し、コードを変更してからもう一度記録し、変更の影響を正確に確認できます。

できること

frames:アニメーションを確認する

ゲームを1フレームずつ撮影してコンタクトシートを作成します。破線の枠は前のタイルから変化した部分を示し、棒グラフは各フレームで画面のどの程度が変化したかを示します。playproof は突然のジャンプ(テレポート、トゥイーンの欠落)、1フレームのちらつき(描画順のバグ、状態の一部しか更新されない問題)、停止(動作の停滞)、まったく動かない状態にフラグを立てます。

npx playproof frames ./dist --device "Pixel 8" --do "tap @Play; wait 400ms; key Space" --duration 700ms

ジャンプのコンタクトシート:700 ms間の14枚のタイル。動いた部分が破線の枠で囲まれ、各フレームの下に棒グラフが表示されています

--animate を追加すると、実際の速度で再生されるアニメーション PNG も取得できます。自分で確認したり、プルリクエストに添付したりできます。動くものが小さい場合は、--zoom auto を追加します。playproof はデバイスのフル解像度で撮影し、動きの大部分がある位置に合わせて各フレームを切り抜くので、キャラクターのつぶれや伸びがタイルいっぱいに表示されます。

さらに、オニオンスキンも描画します。動き全体を1枚の画像に重ねて表示し、古い動きほど薄くなります。残像の間隔がイージングを表します(間隔が広いほど速く、狭いほど遅い)。これは、アニメーターが軌道、予備動作、オーバーシュートを評価する際に見るものと同じです。

ジャンプのオニオンスキン:軌道の頂点付近ではキャラクターの速度が落ちるため、残像が密集しています
frames --compare:変更の影響を確認する

撮影し、コードを変更してから、--compare <earlier run> を指定してもう一度撮影します。以前の実行の各サンプルフレームが、現在の同じフレームの上に並び、差分が輪郭で示されます。また、以前の実行の動きが新しい棒グラフの上に線として描画されます。実行は決定的なため、「同一」は完全に同一を意味します。

npx playproof frames http://localhost:5173 --do "tap @Play; key Space" --out .playproof/before
# ...change the jump...
npx playproof frames http://localhost:5173 --do "tap @Play; key Space" --compare .playproof/before

よりキビキビしたジャンプの変更前と変更後:新しいフレームでは、より早く頂点に達し、着地も早くなっています

play:スクリプトを実行してストーリーボードを作成する
npx playproof play http://localhost:5173 --device "Pixel 8" \
  --do "shot title; tap @Play; wait 400ms; key Space; film 600ms; until window.playproof.state().screen === 'over' 20s; shot game over; tap @Retry; shot retry"

ストーリーボード:タイトル画面、ジャンプの4フレーム、ゲームオーバー画面、リトライ

monkey:クラッシュを探すランダムプレイ

タップ、ドラッグ、長押し、高速な3連続タップ、キー入力、タブをバックグラウンドに送る操作を、ランダムに、ただしシードによって再現可能な形で実行します。捕捉されなかったエラー、リクエストの失敗、ハング(無限ループ)、ソフトロック(入力は受け付けるものの何も変化しない状態)、レンダーループの停止を報告します。各エラーにはその状況を正確に再現するコマンドが付属し、実行全体は repro.steps に保存されます。play --script で操作を1つずつ再生し、重要な操作だけが残るまで行を削除できます。

ゲームがボタンを公開している場合(下記のフックを参照)、monkey が探索を行います。各画面で、同じ操作を繰り返す前に、まだ押していないボタンを試します。screens.png には到達したすべての異なる画面が表示されるので、ランダムプレイヤーがどこまで進めるか、またどの画面に到達できなかったかを確認できます。

npx playproof monkey ./dist --device "Pixel 8" --steps 300
ERROR   Uncaught error: TypeError: Cannot read properties of undefined (reading 'activate')
        during: action 13: tap 699,820, wait 119ms
        at HTMLCanvasElement.<anonymous> (http://127.0.0.1:52009/:51:40)
        Reproduce: playproof monkey "./dist" --seed 1 --steps 13 --device "Pixel 8"
devices:スマートフォン、タブレット、デスクトップを並べて確認する

9つの画面でゲームを読み込み、その画面でのみ発生するレイアウトのバグを確認します。ぼやけたキャンバス(devicePixelRatio に合わせたスケーリングがない)、引き伸ばされたキャンバス、キャンバスの切れ、ページのスクロール、viewport meta の欠落、touch-action: none の欠落、テキストの切れ、小さすぎるタッチターゲットが対象です。複数のデバイスで同じ問題が見つかった場合、報告は1回だけです。

npx playproof devices http://localhost:5173

6台のデバイスを並べて表示。横向き画面とデスクトップでボールが引き伸ばされているのが明らかで、下には検出結果が一覧表示されています

実際の Android 端末で、Chrome またはアプリ内で

frames、play、monkey、perf は、--android(Chrome のタブ)または --app <package> を指定すると、USB 接続された Android 端末上で実行されます。--app <package> を指定すると、Capacitor、Cordova、Ionic で構築されたアプリ内の WebView に接続します。playproof は仮想クロックを使ってアプリのページを再読み込みするため、実機上の実際のアプリで、フレーム単位で正確な同じシートを取得できます。完了後には通常の状態に戻して再読み込みします。localhost は自動的に端末へ転送されます。

npx playproof frames http://localhost:5173 --android --do "tap 50%,60%" --duration 800ms
npx playproof monkey --app com.example.mygame --steps 200
npx playproof perf --app com.example.mygame --duration 10s --monkey

Capacitor アプリと Cordova アプリのデバッグビルドでは WebView のデバッグが有効になっています。それ以外のビルドについては、webContentsDebuggingEnabled を参照してください。Chrome では、playproof は専用のタブを開き、そのタブとのみ通信して、処理後にタブを閉じます。他のタブを一覧表示したり読み取ったりすることはありません。

perf:ローカルまたは実機でのフレームペーシング

ゲームをアイドル状態にする、スクリプトを実行する(--do)、またはランダムなタップを行う(--monkey)間の実際のフレーム時間を測定します。fps、p95/p99、ディスプレイのリフレッシュレートに対するドロップフレーム数、メインスレッドの長時間タスク、ヒープの増加量を計測します。ローカルでは、ミドルレンジのスマートフォンを想定して CPU を 4 倍遅くします。--android を指定すると、USB 接続された Android 端末上の Chrome を測定します。localhost は自動的に端末へ転送されます。

npx playproof perf ./dist --duration 10s --monkey
npx playproof perf http://localhost:5173 --android

16.7 ms の予算ラインを超えるバーが多く、赤色で示されたフレーム時間のグラフ

シナリオと check:動きのスナップショットテスト

ゲームのデフォルト設定と、確認したいタイミングを playproof.config.json に記述します(エディターでは スキーマ に基づいて自動補完されます)。

{
  "$schema": "https://unpkg.com/playproof/schema/config.schema.json",
  "target": "http://localhost:5173",
  "device": "Pixel 8",
  "scenarios": {
    "title": { "duration": "800ms" },
    "jump": { "do": "tap @Play; wait 400ms; key Space", "duration": "700ms", "zoom": "auto" }
  },
  "check": { "monkey": { "steps": 200 }, "devices": true }
}

その後、ターゲットを省略でき、--scenario jump を指定するとステップリスト全体が置き換えられます。

npx playproof frames --scenario jump

playproof check は各シナリオを撮影し、playproof-baselines/ 内のベースラインと比較してから、monkey と devices を実行します。初回の実行でベースラインが書き込まれるので、コミットしてください。その後は、シナリオの動きに変更があると、変更箇所が正確にわかる compare.png とともにチェックが失敗します。--update を指定すると、その変更を受け入れられます。フォントとアンチエイリアスの違いを考慮し、ベースラインはオペレーティングシステムごとに保存されます。

npx playproof check                 # everything
npx playproof check --only jump     # one scenario
npx playproof check --update        # accept the current motion
CI での実行
- uses: actions/checkout@v7
- uses: EmirhanOzl/playproof@v0
  with:
    start: npm run preview
    wait-for-url: http://localhost:4173

このアクションは Chromium をインストールし、playproof check(または command と args を使った任意のコマンド)を実行して、ジョブページにサマリーを書き込み、画像をアーティファクトとしてアップロードします。チェックを実行するマシンと環境を一致させるため、CI で Linux のベースラインを一度生成してください(初回の実行で書き込まれます。アーティファクトからダウンロードするか、そこで --update を実行してください)。

ステップ

--do と --script <file>(ファイルでは 1 行につき 1 ステップ)で使用します。ステップは ; で区切ります。座標はゲーム領域(最大の canvas、または --area <selector>)を基準とします。

ステップ意味
wait 500ms時間を進めます(仮想クロックでは即座かつ正確です)
tap 50%,80% / tap 120,300 / tap @Playタップまたはクリックします。@label はゲームが公開するターゲットを使います
press 50%,50% 800ms長押しします
drag 10%,50% 90%,50% 300msスワイプします
key Space [200ms]キーを押します(デフォルトでは 50 ms 押したままにします)
type helloテキストを入力します
click #startDOM 要素をクリックします
shot [label]ストーリーボード用のスクリーンショットを撮ります
film 1s [30]時間の経過中にフレームをキャプチャします
until <js> [5s]式が true になるまで時間を進めます
expect <js>式が true でなければ実行を失敗させます(左辺の値を表示します)
background 5sゲームをバックグラウンドに移し(フレームなし)、その後前面に戻します
js <js>値を評価してログに記録します

時間:500、500ms、1.5s。

オプション:ゲーム内のフック

必須ではありませんが、小さな関数を 4 つ追加すると、テストの精度が向上します。

window.playproof = {
  ready: () => assetsLoaded,               // boolean, function or promise: when to start
  state: () => ({ screen, level, score }), // logged; used to tell a soft-lock from a busy screen
  targets: () => [{ x, y, width, height, label: "Play" }], // CSS px; enables "tap @Play" and aims the monkey at buttons
  area: () => ({ x, y, width, height }),   // the game world inside a letterboxed canvas; crops every capture
};

フックがない場合は、読み込みを待つために --ready "<js expression>" または --wait-for <selector> を使い、タップにはパーセンテージを指定します。examples/jumper では、フックを完全なゲーム内で使用する例を確認できます。

仕組み

  • 仮想クロック。 ゲームスクリプトが実行される前に、playproof は requestAnimationFrame、setTimeout/setInterval、performance.now、Date を置き換え、CSS アニメーションのタイムラインを停止します。時間は停止した状態で始まります。時間を進めると、タイマーとフレームが正確な順序で 60 fps で実行されるため、wait 2s がミリ秒で完了し、2 回の実行で同じフレームが生成されます。
  • 再現可能な読み込み。 ページの読み込み中、playproof は自動でフレームを進めます。ゲームで実時間のかかる処理(ネットワークリクエスト、WebAssembly のコンパイル、画像や音声のデコード、IndexedDB)が進行中の場合、仮想時間はその処理が終わるまで待つため、マシンや接続が遅くても速くても、同じフレームが得られます。安定化時間はゲームのレンダーループが始まった時点から計測されます。これは、Unity や Godot などのエンジンが独自のクロックを開始するタイミングです。
  • シード付き乱数。 Math.random にシードを設定します(--seed または --seed off)。
  • 実際の入力。 タッチデバイスでは実際のタッチイベントを使用します(Chrome がそこから生成するポインターイベントとマウスイベントも含みます)。それ以外のデバイスではマウスイベントを使用します。入力をポーリングするゲームで認識されるよう、キーの押下状態を数フレーム維持します。
  • ログではなく画像。 コンタクトシート、オニオンスキン、ストーリーボード、チャートは空の Chromium ページに描画するため、playproof の依存関係は playwright-core だけで、ネイティブ画像ライブラリは不要です。

出力

各実行では .playproof/<time>-<command>/(または --out <dir>)に、画像、すべての数値を含む report.json(フレームごとの動き、ステップログ、フレーム時間)、summary.txt、後で比較するための tiles/ 内のサンプリング済みフレームが書き込まれます。.gitignore に .playproof/ を追加してください。--json を指定すると、サマリーの代わりにレポートが出力されます。

終了コード:0 は重大な問題なし、1 はエラーあり(クラッシュ、リクエスト失敗、ステップ失敗、実機スマートフォンでのフレーム落ち)、2 は playproof 自体を実行できなかったことを示します。これにより、CI チェックで monkey と devices を使用できます。

要件

  • Node.js 22.18 以降。
  • Chromium ベースのブラウザー:インストール済みの Chrome または Edge、あるいは npx playproof install-browser。--browser chromium|chrome|msedge|<path> で選択します。
  • --android と --app を使用する場合:adb(Android platform-tools)、USB デバッグが許可されたスマートフォン、画面の電源がオンでロック解除されていること。

制限事項

  • 音声、動画、Web Workers、WebAssembly スレッドは実時間で動作するため、シミュレーションをワーカーで実行するゲームではフレーム単位の完全な再現はできません。
  • ローカルの perf 数値は GPU を使わないエミュレーションによるものです。変更前後の比較には適していますが、フレームレートの保証には使えません。GPU レンダリングには --headed を、実機での確認には --android を使用してください。
  • 動きに関する検出結果はヒューリスティックです。急なジャンプは意図的なカットかもしれませんし、1 フレームのフラッシュは意図的なヒットエフェクトかもしれません。そのため、確認事項として提示されます。
  • 現時点では Chromium のみです。

開発

npm install
node src/cli.ts install-browser   # once
npm run check                     # type check + unit and end-to-end tests
npm run docs:images               # regenerate the README images with playproof itself

2 つのサンプルゲームはテスト対象でもあります。examples/jumper は小規模でシンプルなゲームで、examples/buggy には playproof が検出することをテストで確認する、仕込まれたバグが 8 つあります。

Issue やプルリクエストを歓迎します。CONTRIBUTING.md をご覧ください。

ライセンス

MIT

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。