Rxを使ってクソプラグインを作る

はいどーも全ては一つのニートに収束しますこんにちは。
Rxが全然わからんわけでして、わからないならわかるまでやろうホトトギス。
ちゅーわけで本日も懲りずにRxをいじいじしたいと思います。

クソプラグインを作る

今回作るプラグインは以下のような機能を持っています。

・ゲームのプレイ時間が二秒以上のとき、メニュー画面を2回開くとコモンイベント1を予約する
・以降も二回開くごとにコモンイベント1が予約される
・ただし有効なのは10秒以内

何の役に立つのか全くもってわかりませんが、学習用なのでまあいいでしょう。
ちなみにですが、「二回以上開いたら~」の部分は起動ごとにリセットされる上に、セーブデータを変えても関係なしです(セーブデータ1で1度開いたあとにセーブデータ2で開いてもコモンイベント1が予約される)。
ほんと役に立たないプラグインですねえ!

とりあえずコード

なにはともあれコードです。

最初にObserverを作っています(timeObserver)。
と言ってもふつーのオブジェクトです。
例えば普通にtimeObserver.next()としても実行できます(あんまり意味ないですが)。

次はObservableを作成しています(stoppingObservable)。
これは10秒後にnextが呼ばれるストリームで、nextが呼ばれたらストリーム(次に作成します)を停止させることを意図しています。

最後にSubjectを作成しています(timeSubject)。
takeUntil(stoppingObservable)でストリームを停止させます。
あとは流れてきた値が2(秒)以上ならストリームを通し、bufferCountで2回まで記憶します。
2回溜まった時点でストリームを流し、最終的にtimeObserverの内容が実行されることになります。
doはただのデバッグ用で、filterオペレータを通り過ぎた時点でbufferに溜められたかどうかを確認しているだけです。

ちなみにですが、Scene_Menu.prototype.startでは「プレイ時間」を渡す処理をおこなっています。
セーブデータをロード(あるいは新規作成)したタイミングでないと$gameSystem.playtime()でエラーが出るので、ここでチェックしている感じですね。

実行してみる

ニューゲーム後、メニュー画面を開きまくります(コンソール画面も開いといてください)。
最初の2秒は何も表示されませんが、2秒後からログが表示されるようになります。
「コモンイベント1を予約したよ」という文字列が見えたあとにマップへ戻るとコモンイベント1が実行されます。
そして10秒経つと「もう記録しないよ」という文字が表示され、もう何も起きなくなります(ストリームが停止した)。

これの何がいいのか?

これと同じ機能をRxなしで作ろうとしてみると、何がよいのかすぐにわかるのではないかなと思います。
複雑なif文であふれるでしょうし、文字通り一時的に状態を保存したい使いたいだけの一時変数も増えるでしょう。
ですがRxを使うと、それらが全て隠蔽されます(実際if文は一つも存在せず、ロジック部分に一時変数がないことがわかると思います)。
つまり見た目がスッキリして読みやすいんですね(読みやすいかどうかには異論もあるようですが、僕は普通に書くよりは読みやすいと思いました)。
あと単純に時間を扱いやすいです(この時間単位というやり方が基本フレーム単位で動いているツクール的にどうかというのはありそうですが)。

終わりに

Everything is a streamをだんだんと感じられるようになってきています。
しかし無理に全てをストリームで表現してもややこしくなるだけとも読んだので、適材適所で使えるようになりたいですね。
ほなそんな感じでまた。

フォローする