舞台裏:『Ghost in the Grid』を作る――2Dエマージェントかくれんぼシミュレーション

Dev.to / 2026/3/28

💬 オピニオンDeveloper Stack & InfrastructureTools & Practical UsageModels & Research

要点

  • この記事では、2Dエマージェントかくれんぼシミュレーション「Ghost in the Grid」について、物理エンジンに Matter.js、UI/レンダリングに React を用いた、イン-デプスでモジュール化されたアーキテクチャを紹介します。
  • シミュレーションの中核となる状態機械を、準備(Preparation)、捜索(Search)、終了(Over)という明確なゲームフェーズごとに整理し、それらを中心となる Engine クラスが管理することを説明します。
  • 自律エージェント(隠れる人=Hider、探す人=Seeker)は、力ベースの移動、ウェイポイントのリストによる経路追従、回転のスムージングによって視覚的なジッタ(揺れ)を抑える仕組みなどを共有し、共通の Agent 実装をベースとして動作します。
  • 検知が「公正」に感じられ、難易度の一貫性が保たれるようにするには、堅牢な視界システムと物理駆動の振る舞いが重要であることを強調しています。
  • 全体として、本記事は物理、AIの意思決定ループ、信頼できるセンシング/可視性ロジックを組み合わせることで、「公正に感じられる」エージェント同士の相互作用を構築するための技術的な設計図を提示しています。

この技術的なディープダイブでは、Ghost in the Grid のアーキテクチャと実装を掘り下げます。これは、2Dシミュレーション上で自律エージェント同士が、駆け引きのあるハイステークスなかくれんぼのゲームに競い合うものです。物理、AIの意思決定、そしてゲームを「公平で挑戦的に感じさせる」堅牢なビジョンシステムについて説明します。

構造: モジュール化されたアプローチ

シミュレーションの中核は、モジュール化されたオブジェクト指向のアーキテクチャに基づいて構築されています。物理エンジンにはMatter.jsを選び、UIとレンダリングにはReactを採用しました。

1. シミュレーションエンジン(Engine.ts

Engine クラスはプロジェクトの心臓部です。物理ワールドをオーケストレーションし、ゲームフェーズを管理し、レンダリングループを処理します。

  • 準備フェーズ:隠れる側(Hider)は限られた時間内にツール(箱、板、スロープ)を動かし、隠れ場所を作ります。
  • 捜索フェーズ:探す側(Seeker)が解放され、体系的な探索を開始します。
  • 終了フェーズ:隠れる側が見つかったとき、または時間切れになったときに発動します。

2. 自律エージェント(Agent.ts

隠れる側(Hider)と探す側(Seeker)の両方は、ベースとなる Agent クラスを継承しています。このクラスは次を扱います:

  • 経路追従:エージェントが到達しようとする単純な点のリスト。
  • 力ベースの移動:位置を直接設定する代わりに、物理ボディに力を加えます。これにより、より自然で、モメンタム(勢い)に基づく移動になります。
  • 回転のスムージング:エージェントは移動方向へ回転しますが、角度を補間してジャギーのような見た目(ちらつき)を防ぎます。
// Agent.ts - 力ベースの移動
const desiredSpeed = Math.min(dist * 0.1, maxSpeed);
const currentSpeed = Matter.Vector.magnitude(this.body.velocity);
const forceMag = (desiredSpeed - currentSpeed) * 0.05;

const dir = Matter.Vector.normalise(diff);
if (!isNaN(dir.x) && !isNaN(dir.y)) {
  const force = Matter.Vector.mult(dir, Math.max(0, forceMag));
  Matter.Body.applyForce(this.body, this.body.position, force);
}

ビジョンシステム: 単純なレイキャスティングの先へ

最も難しかったのは、探す側(Seeker)の視界を「公平に」感じさせることでした。中心同士を結ぶ単純なレイキャストでは、わずかな隙間を通り抜けて勝てたり、地図の向こう側から隠れる側(Hider)を見通してしまったりすることがよくありました。

複数ポイント検出

そこで、複数ポイントの検出システムを実装しました。探す側(Seeker)は、視認を確定するために、隠れる側(Hider)のボディ上の少なくとも2つのポイント(例:中心と片側のエッジ)を見なければなりません。

発見タイマー&反応時間

さらに、500ms の視認遅延も追加しました。勝利するには、この間ずっと視界(見通し)を維持する必要があります。これは「反応時間」をシミュレートし、隠れる側(Hider)に一瞬の猶予を与えて物陰へ素早く戻れるようにします。

// Engine.ts - 視認ロジック
if (canSeeNow) {
  this.spottingTimer += dt;
  if (this.spottingTimer >= this.MAX_SPOTTING_TIME) {
    this.isSpotted = true;
    this.phase = GamePhase.OVER;
  }
} else {
  this.spottingTimer = Math.max(0, this.spottingTimer - dt * 0.5); // 視認をゆっくり減衰させる
}

AIの意思決定

隠れる側(Hider)の戦略

隠れる側(Hider)は単に逃げているわけではありません。準備フェーズの間に、環境の「戦略ポイント」(隙間)を特定し、ツールを使ってそれらを「塞ぎます」。角の一画で囲ったスペースを作ることを最優先にします。

探す側(Seeker)の戦略

探索者は、角や中心点を訪れるという体系的な探索パターンを使います。しかし、それには疑念システムもあります。もしそれがかくれんぼする側(Hider)を近くで「察知」したり、あるツールを調べたりした場合は、障害物の向こう側を覗くためにその周囲をぐるりと回り込みます。

課題と安定性

ブラウザ上で物理ベースのシミュレーションを構築するには、それなりの課題があります:

  • 物理の爆発:大きすぎる力、またはNaNの値によって、物体が無限遠へ吹き飛ばされることがあります。安定性を確保するために、防御的なチェックとデルタタイムの上限設定を追加しました。
  • レンダリングと物理の整合:視覚上の「視野コーン」が、数学的なレイキャスティングと完全に一致するようにすることは、プレイヤーの信頼にとって重要でした。

Ghost in the Grid(グリッドの中のゴースト)は、レイキャスティング、力ベースの移動、基本的な状態機械といった単純なルールが、複雑で創発的な挙動につながり得ることを示しています。ゲームAI、物理シミュレーションに興味があるのならもちろん、単にロボットが隅に隠れるのを見てみたいだけでも、このプロジェクトは今後の探究のためのしっかりした土台を提供してくれます。

Example Output 1

Example Output 2

Example Output 3

Example Output 4

GitHubでコードをチェックして、自分だけの自律エージェントを作り始めましょう!

広告