アーキテクチャ方針
本ドキュメントは層の責務と契約を定義する。この契約は言語にもエンジンにも依存しない。 契約を Godot 上で守るための具体的な規約は コーディング規約、決定の経緯は ADR。 用語の正式な定義は 用語集。
この設計が達成すべきこと
このプロトタイプは、以下の4つを同時に満たす必要がある。これらは全て「状態と表現の分離」という同じ根から出ている。
| 要求 | 出典 |
|---|---|
| グラフィック・UI・サウンド・アニメーションを後から差し込める | PRD |
| 戦闘中を含めていつでも中断・再開でき、復帰後に見分けがつかない | セーブ/開発者モード |
| 開発者モードから状態を直接操作できる。ただし裏口は作らない | 同上 |
| ゲームルールをヘッドレスで高速にテストできる | テスト方針 |
層構成
状態層
バトル・マップ・ラン全体の状態を保持し、規則に従って変更する。
性質:
- 画面表示や入力デバイスに関する知識を一切持たない
- 外部からの変更手段は Intent(意図) のみである。それ以外の変更経路を持たない
- 状態が変化するたびに、変化の内容を Event として発行する
- シード付き乱数を自ら所有する。 外部の乱数源を参照しない
- 任意の時点でまるごと保存でき、保存した値から復元できる
表現層(View)
状態層が発行するイベントを受け取り、画面表示・音・演出を行う。
性質:
- イベントだけを購読すれば画面を構築できる。 状態層の内部詳細を知る必要はない
- イベントの発行と画面上の反映は同期していなくてよい(演出のためにイベントを溜めてから順番に反映してよい)
- プロトタイプ段階では単純な図形とテキストで表現するが、イベントの受け取り方は本番の資産に差し替えても変わらない
入力層
マウス・キーボード・タッチ操作を、デバイスに依存しない Intent に変換してから状態層に渡す。
デバイスの違いは入力層と表現層の中に閉じ込め、状態層には影響させない。
開発者モード
状態層から見れば、開発者モードは入力層と同じ Intent インターフェースを通じて特別な指示を送る、もう一つの発信元である。
通常の入力経路を迂回して状態層を直接改変する裏口は作らない。 デバッグ用の変更も Intent として表現し、状態層の同じ入口を通る。
3つの契約
契約1:Intent が唯一の入口である
状態層を変更する方法は、Intent を適用することだけである。
これが保証すること:
| 保証 | 理由 |
|---|---|
| リプレイが可能 | Intent 列を記録すれば、同じ状態を再現できる |
| 開発者モードに裏口が不要 | デバッグ操作も Intent の一種 |
| テストが書きやすい | テストは Intent 列を投げて状態を検証するだけ |
| undo が実装可能 | 状態のスナップショットと Intent 列があれば戻せる |
契約2:イベントキュー
状態層はイベントをキューに積む**。表現層は自分のペースでそれを取り出す。**
シグナルによる即時通知ではなく、順序付きのキューであることが重要である。 シグナルでは「演出を待っている間に状態層が先へ進んでしまう」問題を解けない。
| 保証 | 理由 |
|---|---|
| 演出と状態の分離 | 表現層が3秒かけて演出しても、状態層は既に確定済み |
| テストでの検証 | 発行されたイベント列をそのまま assert できる |
| 演出スキップ | キューを一気に消費すれば飛ばせる |
イベントは 「何が起きたか」の事実のみを表し、「どう見せるか」を指定しない。
契約3:決定論と乱数
状態層はシード付き乱数を自ら所有し、その内部状態はセーブに含まれる。
これがないと「保存前と見分けがつかない状態で再開できる」という要求は原理的に達成できない。 デッキのシャッフル、座の移動先の決定、マップの生成、報酬候補の抽選、すべてが乱数に依存している。
| 保証 | 理由 |
|---|---|
| セーブ/ロードの完全性 | 復帰後の乱数列が保存前と一致する |
| バグの再現 | シードを共有すれば同じ状況を再現できる |
| テストの安定 | 固定シードで決定論的なテストが書ける |
グローバルな乱数(randi() など)は状態層で使用してはならない。
観測可能な契約
- 表現層は、状態層が発行するイベントだけを購読すれば画面を構築できる
- イベントの発行と画面上の反映は同期していなくてよい
- 状態層が保持する値は、任意の時点でまるごと保存でき、保存した値から復元した際、保存前と同一の観測結果(同一のイベント列)が得られる
制約
- Godot 4.7 / GL Compatibility レンダラ上で動作すること
- PC(マウス・キーボード)操作と、将来のタッチ操作の両方が入力層で成立すること
- 状態層は Godot のシーンツリー(
Node)に依存しないこと — これによりヘッドレスでの高速テストが可能になる(ADR-0011)
この方針が禁じること
以下はバグではなく設計違反として扱う。
- 表現層が状態層のオブジェクトを直接書き換えること
- 状態層が
Node/SceneTree/Input/ 画面サイズなどを参照すること - Intent を経由しない状態変更(開発者モードを含む)
- 状態層でグローバル乱数を使うこと
- イベントに「どう見せるか」の情報(アニメーション名・色・座標など)を含めること
関連
- コーディング規約 — この契約を Godot 上で守るための規約
- データの契約 — 定義データとセーブデータの契約
- セーブ/開発者モード — 保存と復元
- テスト方針 — 契約をどう検証するか
- ADR — 各契約に至った経緯