赤宿 = Red Inn

素人の試行錯誤と2Dゲームプログラミング

Control

 いかにゲームを動かすかの第一歩。制御の要素を考えていくことで、ゲーム全体の振る舞いを作ってしまう。この世界観、つまりオブジェクト指向のありかたがゲーム制作に非常に有効だと思う。
 素は例によってBob氏のコードより。氏のものはViewとしての面が強かったが、この記事では制御の要素として注目する。

Classes

 Controlの構造は、スタック式のステートマシンと木構造の親子関係を掛け合わせたもの。

Cradle

 Controlの木構造のルートにあたるクラス。(命名は気分による)。

  • controls: 登録(格納)されたControlのリスト。
  • state: 子のスタック(LIFO)。一番上のものをactiveとみなし、更新する。
  • regester<T>(Control): self.controlsに格納(登録)する。
  • push<T>(): self.controlで型がTのものをスタックに積む。
  • pop<T>(): スタックから一番上のControlを取り出す。
Control

 ゲームの制御要素。

  • children: 子のリスト(オプショナル)。
  • onEnter(), onExit(): ステート的ライフサイクル(?)関数。
  • update(), handleInput(): ライフサイクル(?)関数。

 ライフサイクル関数と言っていいのか、Cradleから呼ばれる関数を持つ。親がactiveな子は、親によって(自動)更新され得る。

Controlによる世界観の具体例(ローグライク)

Controlの親子関係:

  • RoguelikeControl
    • EngineControl
    • PlayerControl
      • DiagonalModeControl
      • DirectionModeControl
  • SequenceControl

各Controlの役割(責務):

 RoguelikeControl: cradle.push(child) により適切な子をactiveにする。
  EngineControl: ゲームモデルの時間を進める。
  PlayerControl: プレイヤ操作の制御をする。
   DiagonalModeControl: コンポーネントとして振る舞う。斜め以外の方向入力をオミットする。
   DirectionModeControl: コンポーネント。方向入力で移動せず、向きのみ変更するモードを担当する。
  SequenceControl: エフェクトの表示など、シーケンシャルな振る舞いを再生する。

 こうして、実にシンプルにゲームの振舞(制御)を組んでいける。

「ステート」を振り返って

 ゲームの状態を切り替えてゲームを制御するというアイデアはよく聞く。Controlもステートに近いが、考え方が決定的に違うと思う。Controlは、

  • 制御という"もの"を考える( -> 自身の動作を定義していく: 「制御が働く」ニュアンス)
  • 責務は担当範囲を制御すること(controlling) (次行の通りサイズは自由)
  • 制御を要素の集まりとして捉えやすい (a big control may consist of small ones)

 一方、ゲームのステートを考える場合、

  • ある状態を考える (他者の動きを定義していく)
  • 責務はその状態におけるゲーム全体の動作を指示すること (大きい)
  • 制御を動作の集まりとして捉えにくい (GameState/Mode_Componentの一般的な呼び名が無い)

 小さなもの、たとえばキャラの状態を切り替えることは容易く理解できる。一方、大きなもの、ゲーム全体の状態(モード)を考えるのは難しい。責務の範囲が分からないからだ。PlayerControlModeの責務は、PlayerBehaviorに限定されず、そのときのゲーム全体の振る舞いを書く必要がある。それらを全部考えていくと手が止まるし、自身が状態であるだけに、機能を分割しづらい。
 また、ゲームの状態を見つけるのは、制御の要素を考えるよりも難しい。制御は、動作するものの方から考え始めることができるが、ステートから考え始めた場合、ゲームの状況から考える必要がある。
 制御の存在を認めると自然にコードを組んでいけると思う。viva OOP!!

まとめ

 Controlの世界観では、制御の要素を考えていく。ステートオブジェクトは存在せず、アクティブなControlを切り替えることで、ゲームの振る舞いが変わる。Controlの世界観を導入することで、自然な発想でゲームを作ることができるかもしれない。