agentsclimarketplace

Phaser mcp verify throttled

Skill bokuwalily/claude-code-skills/skills/phaser-mcp-verify-throttled

ブラウザMCP(claude-in-chrome等)でPhaser3ゲームを自動検証する際、対象タブが非フォアグラウンドでRAFスロットリングされゲームループが止まり、delayedCall/シーン遷移が発火しない/待っても進まないときFrom its SKILL.md

Install
npx -y skills add bokuwalily/claude-code-skills --skill phaser-mcp-verify-throttled

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

3.5 KB, ~1.1k tokens by cl100k_base, as published. Nobody here has run it

Procedure

MCP(headless)でPhaserゲームを driveすると対象タブはOSフォアグラウンドにないため、 ChromeがRAFを激しく throttle し game.loop がほぼ停止する。結果:

  • scene.time.delayedCall(...) が発火しない(遷移コールバックが永遠に保留)
  • カメラfadeが途中(progress 0.2等)で止まる
  • 実時間 wait をいくら挟んでもゲーム内時間が進まない

対策:ゲームループを手動でポンプして決定論的に時間を進める。

  1. dev handle でゲーム本体を公開しておく(window.__game = game 等、import.meta.env.DEV内)

  2. 状態遷移やタイマーを進めたいときは game.loop.step() を実時間タイムスタンプを 進めながら複数回呼ぶ。1フレーム≒16msで、遷移+create+fadeなら 100〜160回が目安:

    const g = window.__game;
    let t = performance.now();
    for (let i = 0; i < 160; i++) { t += 16; g.loop.step(t); }
    

    これで保留中の delayedCall が発火し、scene.start() のキュー処理・create・fadeまで進む。

  3. シーンの「本当の」状態は isActive() ではなく sys.settings.status を読む。 遷移中の game.scene.isActive(key) は古い値を返して描画と食い違う:

    const P = Phaser.Scenes;
    const cn = c => Object.keys(P).find(k => P[k] === c) || c; // 'RUNNING'/'SHUTDOWN'/'INIT'
    game.scene.scenes.map(s => ({ key: s.scene.key, status: cn(s.sys.settings.status) }));
    const uiUp = game.scene.getScene('ui').sys.settings.status === P.RUNNING;
    
  4. document レベルのキーハンドラ(document.addEventListener('keydown', ...))は 合成イベントでテストできる。発火後にループをポンプして反映を確認:

    document.dispatchEvent(new KeyboardEvent('keydown', { key: 'i', bubbles: true, cancelable: true }));
    for (let i = 0; i < 20; i++) { t += 16; g.loop.step(t); }
    
  5. 画面の見た目は MCP screenshot で確認(canvasは最後にstepした内容を描画している)。 ステップ→screenshot の順でバッチ実行すると最新状態が映る。

Pitfalls

  • セーブを書き換えて検証する場合は 先に localStorage をバックアップし、検証後に復元する (window.__BK = {key, val} に退避 → 末尾で localStorage.setItem + PS.load() で戻す)。
  • game.loop.step() はRAFと二重に走り得るが、検証用途では許容。終わったらリロードでクリーン化。
  • 実プレイ確認は「クラッシュしない」だけでなく、遷移後に期待UI(HUD等)が RUNNING かつ screenshotで視認できることまで見る(スモークテストで終わらせない)。
  • 関連: (手動コンソール用にsceneを公開する基本形)。

Verification

// ポンプが効いているか:stepを回す前後で scene.time.now が増える
const g = window.__game, before = g.scene.getScene('game').time.now;
let t = performance.now(); for (let i=0;i<60;i++){ t+=16; g.loop.step(t); }
g.scene.getScene('game').time.now > before;  // → true ならループが進んでいる

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,851. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.