赤宿 = Red Inn

素人の試行錯誤と2Dローグライク制作 (GUI)

Current Progress

 妥協案を出したトピックを上げていく。

Processing

 ローグライクシステムのベース。プログラミングでシーケンシャルなゲームの挙動を実現するのが難しく、現状の方法は苦肉の策。

Engine = Model, UI = View

 UIがEngineを持ち、engine.tick()で時間を進める図式。アニメの再生やプレイヤの行動の決定を終えると、UIは再びengine.tick()を呼ぶ。

Actionの演出

達成すべき条件:
  • Actionの演出(View)は、Engineのコードを変更せずに差し替えられる。
  • ModelとViewは時間的に同期している。
    (=> リアルタイムでModelを表示したとき、Viewと状況が一致する)
苦肉の妥協案:
手続き
  1. Actionを細切れのmotionFuncに分け、ActionをmotionFuncのシーケンスと見る。
  2. EngineはsomeMotionFunc()ごとにUIに制御を返す。Actionは次motion()の呼び出しを予約できる。(ラムダ式を用いる)
  3. Viewはmotionの演出を行い、再びengine.tick()を呼ぶ。(すると、予約された次motion()が呼ばれる)
演出方法

 ViewSequence(Queue)に、演出オブジェクトを載せていく。後は再生するだけ。
 演出オブジェクトは、overriddenMotionFunc()内で作る。(View.Actions.XxxがEngine.Actions.Xxxを継承)

Actions差し替えの策

 Actionの生成でActionFactoryを経由する。View.Actions.XxxがEngine.Actions.XxxとしてEngineの手に渡る。

成果
  • Actionの演出は一応差し替え可能(ActionFactoryを差し替える)
  • Model, Viewが時間的に同期する

  • 手間が多い (Factoryを書く必要や、chainのための制限など)

参考になりそうな記事:

Controlling

in OOP

 どうやってゲームを動かすか? オブジェクト指向で解決していく。つまり、個々のオブジェクトを考えることで、結果的に、ゲーム全体の時間的な挙動も実現させる。

 Controlという概念を持ち出す。"制御が働く"ニュアンス。Controlオブジェクトのツリーを作り、アクティブなControlが切り替わることによって、結果的にGameModeが切り替わる。コンポーネント指向のステートマシンと言えるのかもしれない(?)。ただし考えるのは、《状態》ではなく《制御》のコンポーネント。たとえば、RoguelikeModeを考えるよりも、EngineTickControl、PlayerControl、StairControlなどを考える。この方が発想が簡単で、しかも分離が適切になりやすいと思う。

Cradle Framework

 UI.update()はCradleの更新をするだけ。擬似コードは以下:

pub class Cradle {
  storage: [Control];
  stack: [Control]; // active controls.
  pub update() {
    self.stack.peek()?.update();
    ...
  pub get<T: Control>() -> T? {
    self.storage.first{ it is T } ?? None
  }
  ...

HUD

LogView : Control

問: Engine側で複数のログが一度に書き込まれるとき、一つずつ順番に描画・演出するには。
案: update()内でキューを見る。前回のログの演出が実行中ならreturn。未表示のログがあれば演出開始。
?: ウディタユーザとしては、LogView.update()が常に呼ばれる違和感がある。

Flexibility

Entity非依存

 EC(S)を使って、Engineを含むコードを組んでいる。
 EngineがSomeFramework.Entityに依存しないようにするには。traitが無いと無理か?

Engine/Modelの境界

 うまく分離できない。
 全ローグライクで共通のシステムをEngine、ゲーム固有のシステムをModelとするつもりだったが、分けるのは無理か……?

Size, Posで型を分けるか?

 今は両方Vec2自前クラスを使っている。