ブラウザゲームの60秒は本当に60秒か
performance.now・rAF・バックグラウンド停止を実測

『60秒後の彼女』は「60秒で遊べる」と謳っています。しかしブラウザのタイマーは、setInterval の積算、フレーム落ち、バックグラウンドタブの停止によって、意図した時間からずれることがあります。この記事では本作のタイマー実装と、それがどう時間を刻むかをシミュレーションで確かめます。

結論: 残り時間は performance.now() という単調増加する時計から毎フレーム「実経過時間」を引く方式で計算しています。setInterval の呼び出し回数を数える方式ではなく、実時計基準のためフレーム落ちに強く、バックグラウンドタブではゲームクロックを停止(freeze)する仕様にしています。シミュレーションでは、各難易度の制限時間(HARD 60秒 / NORMAL 64秒 / EASY 72秒)が正しく減算されることを確認しました。

1. なぜ「60秒」が問題になるのか

ブラウザゲームで「60秒」と表示しながら、実際には 58秒や 63秒で終わる、あるいは逆に長引くことがあります。原因は大きく三つあります。

2. 本作のアプローチ:実時計基準の残り時間

実装 『60秒後の彼女』の src/core.js は、制限時間を「絶対的な締め切り(deadline)」と performance.now() の差で算出します。ゲーム開始時に startTimer()deadline = now + timeLimit * 1000 を決め、tickTime() は毎フレーム timeLeft = (deadline - now) / 1000 を再計算します。

// ゲーム開始時(一度だけ)
export function startTimer(state, now) {
  state.deadline = now + state.timeLimit * 1000;
  state.timeLeft = state.timeLimit;
  state.ended = false;
  state.running = true;
}

// 毎フレーム呼ばれる。now は performance.now() の値。
export function tickTime(state, now) {
  if (!state.running) return;
  if (state.paused) { state.lastFrame = now; return; }
  if (DIFFICULTY_CONFIG[state.difficulty]?.timerFrozen) {
    state.lastFrame = now; // 練習モード:時間を減らさない
    return;
  }
  // ゲーム制限時間は deadline との差。実経過時間へ正確に追従する。
  state.timeLeft = Math.max(0, Math.min((state.deadline - now) / 1000, state.timeLimit));
  state.lastFrame = now;
}

ポイントは次のとおりです。

3. バックグラウンドタブの仕様

仕様 script.jsvisibilitychange イベントを監視し、タブが隠れたらゲームループ(rAF)を止めて freezeTimer() を呼びます。再表示時に unfreezeTimer() が、隠れていた時間分だけ deadline を後ろへずらしてから再開します。つまり裏にいる間はゲームクロックは進まず(freeze)、戻った直後に「数秒分まとめて減る」不公平な挙動を回避しています。手動で一時停止(pause)している場合は freeze が上書きすることはありません。

設計上の選択: 裏タブを「停止する」仕様にしました。これは「60秒という制限時間の公平性」を優先したものです。通信対戦ではなく単独のローカルゲームなので、裏タブでの進行を許容するより、戻ってきてからちゃんと遊べることを重視しています。

4. シミュレーションで確かめたこと

実測 固定 60fps の fake clock で各難易度を 70秒間(wall clock)シミュレーションした結果です。これは本物のブラウザ rAF ではなくユニットレベルのシミュレーションであり、相対的な挙動を確認するためのものです。

表1:70秒経過時点の残り時間(シミュレーション)
難易度制限時間70秒経過時の残り消費フレーム数
EASY72秒約 1.98秒4201
NORMAL64秒0秒(終了済み)3841
HARD60秒0秒(終了済み)3601

制限時間どおりに終了していることがわかります。また、バックグラウンドギャップ(10秒遊び→30秒非表示→再開)のシミュレーションでは、非表示中は残り時間が維持され、再開後に正しく減算が再開されることを確認しました。

5. リアルブラウザでの注意点

6. 読者が自作ゲームで使えるチェックリスト

限界: 本記事の数値は固定 60fps のシミュレーションです。実ブラウザではデバイスや負荷によってフレームタイミングが変わりますが、「時間の合計」は実時計基準のため変わりません。また本作はローカル単独ゲームのため、ネットワーク遅延は関与しません。

7. 参考文献

仕組みがわかったら、実際に遊んでみてください。

▶ 60秒後の彼女をプレイする

最終更新:2026-07-18 / 運営:cig4r / この記事は本作の実装とシミュレーションに基づく検証記事です。