RPGツクールVXAceの網

RPGツクールVXAceの製作過程で気が付いたことをメモする。

メッセージウィンドウとFiber

RPGツクールVXAceから実装されているFiberで少しはまったので挙動をメモする。

 

VXAceのメッセージウィンドウはデフォルトで文章を1文字ずつ表示する(1文字表示ごとに画面が更新される)。これを実現するために、Window_Messageクラス内で以下のようなメソッドが構成されている。

 f:id:kazamit:20121113015137p:plain

①update:画面(ウィンドウ)描画更新のために定期的に呼ばれる。

②update_fiber:update内で更新パーツの一部として定期的に呼ばれる。

 もしインスタンス変数@fiberがnilならFiberを新しく生成され、resumeによってfiber_mainで定義される子のコンテキストに制御が切り替わる。

③fiber_main:子のコンテキスト。ウィンドウを開いてから文章を表示し、閉じるまでの一連の処理が全て記述されている。

④process_all_text:全てのメッセージを描画する。

⑤process_character(WIndow_Baseで定義):制御文字を考慮した1文字を描画する。

⑥process_normal_character:通常の1文字描画を行い、メッセージウィンドウの場合は⑦を呼ぶ。

⑦wait_for_one_character:1文字描画後の処理が記述されている。Enterで瞬間表示判定がかからなかった場合は、Fiber.yieldで親に処理を返す。

 

Fiber.yieldの制御戻り先は@fiber.resumeの真下。描画に関してはここで処理が終了し、次の周期のupdateを待つ。fiber.resumeが次の周期で呼ばれたとき、③fiber_mainははじめからではなく前回のFiber.yieldの直後から再開される。(図中青矢印の着地点は、初回と2回目以降で異なる。)このときslice後の次の1文字が描画され、また処理が親に戻る。全ての文字を書き終わるまでこの制御の受け渡しを繰り返す。

 

構成の狙いとしては、fiber_mainはそれ単体でfiber.resumeのくだりを除いて「全文を描画処理する」という機能のみを記述し、途中で切りたいところにfiber.resumeを差し込んでいるというもの。文章の全表示という機能の中に、グラフィック更新タイミングのいざこざを巻き込まなくて良い、というシンプルな記述を得ることが出来る。ただし、yieldの戻り先をきちんとわかっておかないと、goto的な制御系が難解な構成になる。ためしにfiber.resumeをコメントアウトすると、瞬間表示と等しい処理になる。

 

さて、本来自分がチャレンジしていたのはメッセージの表示スピードを速くしたり遅くしたりすることだった。たとえば3文字を1度に描画したい場合は、yieldで制御を戻す頻度を3回に1回にすれば良い。下手にfiberの外側をいじると、メッセージウィンドウ表示動作全体の挙動がおかしくなる可能性がある。