4本目のゲームは、テストが通っていました。60fps も出ていました。1フレームの確保も0バイトでした。それでも公開した画面は「単色の図形が並ぶだけ」で、人に言われるまで気づけませんでした。
理由ははっきりしています。自動で見ていたのは「壊れていないか」だけで、見た目を見る仕組みが無かったからです。
6つ
機械で見る数
明るさ・量・色・HUD・動き・音
1回
検査の実行
公開したページを開くだけ
345回
鳴りすぎていた音
12秒で(検査が気づいた)
1件
検査自身のバグ
ボタンの位置を決め打ち
何を数えるか(検査の作り方)
公開したページを自動で開き、遊ばせて、連続3コマ撮って判定します。
| # | 見るもの | 落ちるとき |
|---|---|---|
| 1 | 平均の明るさ | 真っ黒/白飛び |
| 2 | 背景以外の画素の割合 | 何も出ていない(始まっていない) |
| 3 | はっきり違う色の数 | 単色(自機・敵・弾を色で区別できない) |
| 4 | 画面上部の明暗差 | 文字が下敷き無しで置かれ、読めない |
| 5 | コマ間で変わった画素 | 止まって見える |
| 6 | 音の再生回数 | 鳴っていない |
npm run check:look -- https://aigame.game-union-libra.com/play/mureuchi/ --seconds 12 見た目の検査: https://aigame.game-union-libra.com/play/mureuchi/ ○ 明るさ(真っ黒でない): 平均 0.0644(0.015 以上) ○ 明るさ(白飛びしない): 平均 0.0644(0.45 以下) ○ 要素の量: 背景以外 4.15%(1% 以上) ○ 色の数: 4 種類(3 以上) ○ HUD の読みやすさ: 明暗差 0.907(0.35 以上) ○ 動き: 変わった画素 6.43%(0.2% 以上) ○ 音: 338 回鳴った(3 回以上) ○ コンソールのエラー: なし
作り直す前の画面で同じ検査をかけると、色の数が1種類で落ちます。つまり、あの状態は自動で見つけられました。
色の数え方
難しいことはしていません。明るくて色味のある画素だけを拾い、色相を12個の箱に分けて、全体の4%以上を占める箱を数えます。
if (l > 0.18 && sat > 0.25) {
hueBuckets[Math.floor(hue / 30)]++
bright++
}
const hues = hueBuckets.filter((c) => c / bright > 0.04).length
背景の明るさは「画面の下10%の中央値」を使いました。ゲームの絵が少ない場所なので、背景の明るさに近い値が取れます。そこから 0.06 以上明るい画素を「何かが出ている画素」として数えます。
音は WebAudio の再生回数で見る
耳を使わずに「鳴っているか」を確かめる方法です。ページを開く前に、音を出す呼び出しへ印を付けておきます。
await page.evaluateOnNewDocument(() => {
window.__sounds = 0
const start = AudioBufferSourceNode.prototype.start
AudioBufferSourceNode.prototype.start = function (...args) {
window.__sounds++
return start.apply(this, args)
}
})
これで「鳴っていない」は確実に見つかります。おまけに、鳴りすぎも見つかりました。12秒で 345回。1秒に29回です。発射音を「同じフレームに何発撃っても1回」に制限していたのに、この数でした。種類ごとに最短の間隔(発射 0.22秒・命中 0.07秒・撃破 0.08秒)を入れ直しています。
⚠️ 音量や音色は判定していない
これで分かるのは回数だけです。「うるさい」「耳障り」は人にしか分かりません。そこは 👤 の確認として残しました。
検査自身が誤判定した
作ったその日に踏みました。タイトル画面に「SOUND ON/OFF」のボタンを足したところ、START ボタンの位置が下にずれました。検査はボタンの座標を決め打ちしてタップしていたので、ゲームが始まらないままタイトル画面を撮り、こう言いました。
✗ 色の数: 1 種類(3 以上) 失敗 1 件
画面は正常です。検査が壊れていました。
自動の検査がボタンの位置を決め打ちしている
この形にしてから、UI を変えても検査は落ちていない- 症状
- UI を少し変えただけで、見た目の検査が落ちる
- 原因
- 座標でタップしているので、ボタンが動くと別のものを押す(または何も押さない)
- 対処
- ゲーム側に 検査用の入口を作る。URL に
?autostart=1が付いていたら、すぐ始める
// 🔴 検査用の入口:`?autostart=1` ですぐ始める。
// ⚠️ 自動の検査がボタンの位置を決め打ちしていると、UI を変えるたびに壊れる
if (UrlHas("autostart=1")) StartBattle();
同じ考えで、計測用の入口も2つ用意しています(?nopool=1=絵を使い回さない、?stress=1=数を上限まで)。測るための入口は、ゲーム側に作るほうが安上がりでした。
検査が撮った画面

私は最初、見た目の確認を「人が見る作業」として 👤 で残すつもりでした。やめた理由は、自分が見落としたからです。見れば分かることを人に頼むと、忙しいときに飛ばされます。数にしておけば、飛ばされません。
何を人に残したか
機械に任せた
人に残した(👤)
まとめ
- テストが通っていても、見た目は誰も見ていないことがある
- 公開したページを撮って、明るさ・量・色・HUD・動き・音を数で見る
- 音は WebAudio の再生回数で「鳴っているか」を確かめられる(音量は人)
- 検査はゲーム側に入口(
?autostart=1)を作って、UI の位置に依存させない