赤宿 = Red Inn

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

Processing (Another)

 前回からやり方を変えて、キャラの行動の可視化を試みる。実際に試すのは後日。
 必要条件を次の2つとする。

  • Model/Viewのコードを別のファイルに入れられること
  • Model/Viewの状態が同期していること(ModelがViewに先走らないこと)

 後者が必要な理由は、UIがmodelを参照するため。マウス上のキャラの情報が表示されたとき、攻撃が終わる前にキャラの体力が減っていてはいけない。

実は、View用にModelのコピーをとっておき、そちらをViewに見せる手もある。ただしメモリの効率が悪いし、複雑になりそうだ。

ModelとViewを同期すると、先にModelを計算して後から再生することはできない。

案 - Idea

前提 - Context

 たとえば「投げる」というActionを実行した結果、

「投げる」
「アイテムが壁に当たって跳ね返る」
「床に落ちる」

 という、一連の挙動(motion)に終わったとする。
 これらを可視化する条件は、次の2つ。

  • motionの前後に演出を挟めるようにする
  • 次のmotionの起動までModelは待機する

UI側では - in UI

motionの前後に演出を挟めるようにする - Motion Sandwich

 UI側でActionを派生し、motionに相当する関数をoverrideする。これで、motionが起きる瞬間にView側のコードを挟める。
 base.someMotionFunction()の前後に演出を挟められればいいが、overrideしたmotion関数は一瞬で終了するのが問題だ。(IEnubmerableな関数ではないため)。

motionの演出をする(案) - SequenceControl

 そこで、演出用のオブジェクトや、base.someMotionFunction()をラップしたものをキューに入れ、後から順に実行すればいい。

本当は、キューに頼るのは嫌だ。ここがうまくいくかがまだ分からない。

Model側では - in Model

 そもそもmodelでは、model::Engine.tick()が呼ばれることで処理で進む。演出のために待つのはUI側に任せて、Model側ではtick()時の再開ができればいい。
 model側のゲームループではyield return すれば再開は容易い。Action内で次のようにして再開時のmotionを指定しておく。

// motonを関数オブジェクトにラップしておくと、再開時に呼び出される。
base.chainMotion( () => someMotionFunction( andTheArgs ) );
// 美しくはないな!!

 不満はあるがやってみよう。

SequenceControlで逐次的に再生する

 キューの部分を担当するオブジェクト。Controlの概念として導入する(別記事参照)。

let seq = self.SEQ -- SequenceControl  
seq.wait( 1.0f )  
...  

 これで演出などを作り、再生する。