自作のドット絵のRPGを開発中のKilianです。
先に考えたMVVMパターンを使ってMVVMパターンで自作ゲームのクラス構成を考えてみます。特に今回はプレイヤーの入力による内部処理からのゲームの表示の繋がりを考えてみます。
ゲームというのはおおよそ以下の流れの繰り返しでしょう(多分)
入力の受付モード切り替え(フィールド時専用の入力モード、戦闘時専用の入力モードなど)
↓
プレイヤーによる実際のコントローラーの入力
↓
入力されたボタンによる処理
↓
データの更新
↓
画面に更新された情報を出力
ゲーム制作にあたってそれぞれの役割を誰(クラス)がどのように担当しますかという設計をしたい。MVVMパターンの設計手法に従えば以下の分担になりそう。
# 処理なので => ViewModel
入力のモード切り替え(フィールド時、戦闘時など)
↓
# 入力受付なので => View
プレイヤーによるコントローラーの入力
↓
# ロジック処理なので => ViewModel
入力されたボタンによる処理
↓
# データそのものと、更新メソッドは => Model
# Modelのデータ操作、指示は => ViewModel
データの更新
↓
# 指令は => ViewModel
# 画面表示は => View
画面出力
プレイヤーの操作を実装するにあたって必要そうなクラスをMVVMパターンに当てはめて列挙してみる。こんな感じか。
// 全体管理
// View Model
public class CoreManager{} //ゲームの管制塔
public class StoryManager{} //フラグの管理
public class PhaseManager{} //ゲームの状態管理。主にコントローラ入力切り替えのため。InputControllerのMode切り替え用デリゲートにInputMode持ってきたモードをセット
/////// プレイヤーの入力に関するMVVM ///////
// View??
public class GameInputs{} // Unityでインストールできる入力システム構築用のパッケージ、Input Systemによって作られクラス。Editorから自分で任意のクラス名に変えられるみたい
// View Model
public class InputController{} // プレイヤーからのゲーム中のあらゆる入力を受け付け処理する唯一の窓口。入力モードの切り替え処理を持つが、指示の権限はゲームの状態を管理するPhaseManagerにある。PhaseManagerがCoreManagerを参照してこのInputControllerクラスインスタンスのモード切り替え処理をする。入力モードが変わる時にPhaseManagerがInputControllerに処理を依頼してモード変更させる。
// Model
public class InputMode{} //UnityのGameInputシステムを使って作る、ゲームの状態ごとに切り替える入力のモードのモデル。フィールド移動時、縦長リスト選択時とか色々作れる。更新メソッドもある。
/////// キャラクターグラフィック ///////
// View
public class charGraphicView{} //キャラのグラフィック表示などを担当するView。自身のCharacter Graphicに対応するビューモデルcharGraphicControllerのインスタンスを保持。コリジョンを検知してcharGraphicControllerに処理を依頼したりもする。
// View Model
public class CharGraphicController{} //キャラのグラフィックの動作を管理するクラス。フィールド移動時入力モード時にInputControllerから移動に関する処理がよばれるようにデリゲートの処理が記述してある。
public class SpriteLayerController{} //表示させるスプライトのレイヤーの処理の実行
// Model
public class charGraphic{} //画面に写っているキャラの座標を計算するLocomotionクラスやアニメーションなどのデータを保持
public class Locomotion{} //フィールド移動時のキャラの座標。移動の計算メソッドを持つモデル。メンバー一人につき1つインスタンスがあるので各メンバーごとに随時座標計算できる
public class SpriteLayer{} //スプライトのレイヤー情報を保持、更新メソッドもある
//////// キャラのステータス情報(スタッツ)
// View
public class StatsFieldView{} //フィールド画面でのステータス表示ビュー
// View Model
public class StatsController{} //キャラステータス情報のViewModel
/////// Model ///////
public class Party{} //行動してるキャラなどパーティー全体の情報
public class Stats{} //個々のキャラのHP、MP、攻撃力、アイテムなどの情報。更新メソッドもここ。
なんかとてつもなく複雑なのだが大丈夫か?
冷静に考えよう。
例えばゲーム内の状態が「フィールド移動」の状態の時にプレイヤーの十字キーの入力でキャラを移動させたいのであれば
ゲームを管理するCoreManagerインスタンスの中にPhaseManagerインスタンスを設置(ゲーム開始時)
|
PhaseManagerインスタンスが現在の状態を「フィールド移動」だと宣言
|
同時にPhaseManagerインスタンスがInputControllerインスタンスに現在の入力モードを「フィールド移動」用の入力に更新するように指示する(デリゲート)
|
要請を受けたInputControllerインスタンスがInputModeモデルの入力モードを更新
|
この瞬間からプレイヤーが十字キーを入力するとCharGraphicControllerインスタンス内のメソッドが呼ばれるようになる
|
CharGraphicController:このメソッドの中にcharGraphicモデルが持つ座標計算専用のクラスのLocomotionインスタンスがある
|
charGraphic:
Locomotionインスタンスに入力値を渡した上で移動による座標計算をさせ結果でcharGraphicモデルの座標データを更新
|
CharGraphicController:
CharGraphicControllerからViewであるCharaGraphicViewにCharGraphicモデルの座標データを渡して表示させる
図示するならこんな感じか。単純に移動入力だけならもっと簡単で良いんだろうけどメニューやらバトルやらコマンドやら今後どんどん増えていくことを考えるとこれぐらい役割を分けて明確化しておいた方がいいのかもしれない。
