kowさんは天ざる大好き

創作に絶望すると、世界が反転した日記

Yanesdk.netによるノベルゲーム実装(4)

yanesdkがらみの本が出るらしい。楽しみである。
まあ、なんにせよ、あたしの感想文は続く。

あたしは.netアプリはまるで詳しくないのだけど、もちろん、去人たちのソースにもプログラムのエントリポイントがある。

mainかWinMainぐらいしか使ったことはないが、去人たちのソースでは、Program.Mainがエントリポイントとなっている。そういうものなんだろうとおもう。
src/kyojin/Program.cs
がそれに当たる。

それが全てのプログラムのスタートラインである。
去人たちではいきなりスタートして FileArchiverZip の設定をしている。
こんなところでいきなりやるんかいと言われそうだが、やるのである。

あたしは昔馬鹿みたいに、コンストラクタでテクスチャをロードしたりしていた。すると大変よろしくないことが起こる。生ファイルのときは正しく動くが、pass付きzipにするとFileArchiverZipがセットアップされていなくて読み込めずエラーになるのである。
コンストラクタで必ず使うものだから、インスタンス生成しておこう、とおもったクラスは、その部品としてなんらかの画像を表示クラスがふくまれていて、そのコンストラクタで画像を読み込んでいる。画像ファイル読み込み時にはFileArchiverZipにデフォルトのpassが設定されていなければならないのに、それが設定されていなければ読み込めるわけもない。

だから、もうここではなりふりかまわず、何に先駆けてもpassを設定しておきたいという意思表示である。
だから、間違ってもstaticなコンストラクタ(静的コンストラクタ)でファイルアクセスをしてはいけない。静的コンストラクタは呼び出される順番も規定されていないので、たとえ、どこかの静的コンストラクタでFileArchiverZipにデフォルトのpassが設定しても、それが一番最初に呼ばれるとは限らないからである。

当たり前のことと言われても、わたしに当たり前などない。そんなもんで、実際にわたしがこのちょんぼをしていたということである。

そんなわけでkow@suhitoは、間違ってこのエントリーにたどり着いてしまったちびっこに
コンストラクタでは本当に必要な最小限の処理に留めよう
という標語を来年の書き初めにいかがであろうかと提案する次第だ。

さて、FileArchiverZipのセットアップをしたら次は、ゲームループへと突入する。
それを担っているのがGameSystemクラスである。(※去人たちのプログラムは、手と栗鼠をスケルトンにしとります)
GameSystem.Run

というメソッドのなかでぐるぐるとゲームループが回っておりますよ。まるでハムスターのように休むことなく、何が愉しいのかいっこうにわからないけどぐるぐるとまわっております。

GameSystemクラスはまず、ループに入る前に、準備体操をする。
プールに入る前には準備体操をするものである。そうでないと心臓麻痺を起こしてしまう。
ただ、準備体操をするまえにも、やることがある。まずは相応しい装備をしなければならない。さあ、プールだといって準備対応をしてプールに飛び込んでも、制服のままでは場が騒然としてしまうし、あなたは気が触れたのではないかと思われてしまう。

まずウィンドゥをつくらなきゃならない。これはSDLWindow2DGlを作ってTestVideoModeを呼べばできちゃう。中で何が行われているかなんてよくわからんでもこれでウィンドゥが作られるならそれでいいとしよう。

これで水着をきたようなもので、これで準備体操をしてプールに飛び込んでもいいけど、キャップをつけたりゴーグルをつけたり、自信がないならビート板も欲しいと思う。まあ、眼病予防のためにもゴーグルはあってもよいだろう。

そこで是非ともあれば嬉しいゴーグルのようなSmartXXXXLoaderはここで用意してしまおう。
yanesdkをでは次の3つのSmartXXXXLoaderをよく使うことになると思う。
 ・SmartTextureLoader
 ・SmartSoundLoader
 ・SmartFontLoader

そもそも、XXXXXLoaderというローダーがある。TextureLoaderとか、SoundLoaderとかみたいに。
これらはそれのスマート版である。
TextureLoaderは何をするもんかというと、テクスチャ(画像)をリストから読み込んでくれる装置。
テキストファイルに
img/a.jpg
img/b.jpg
のように書いて、そのファイルをTextureLoaderに読み込ませる。それに0番目のTexture画像をくれといえば img/a.jpgの画像が、1番目の画像をくれといえばimg/b.jpgのTexture画像が取得できる。
つまり、TextureLoaderにリストの0番目のテクスチャをくれ、というと
0番目の画像をくれ→img/a.jpgを読み込み→テクスチャ登録→キャッシュに登録→ITextureの具象クラスのインスタンス返却
ということをする。
キャッシュするので、次は
0番目の画像をくれ→(キャッシュに発見!)→ITextureの具象クラスのインスタンス返却
という感じでお手軽に取得できる。

ここまでは以前のyanesdkにもあった。yanesdk.netの肝はこのTextureLoaderをさらにこのスマートしているSmartTextureLoaderだ。TextureLoader自体をスマートに管理している。
シナリオを描画するとき、背景画像をTextureLoaderで管理するとする。たとえば背景画像が100枚あるとして、一つのシナリオをプレイして70枚の画像を表示したらそのうちの何枚かはキャッシュとして保持している。シナリオ部分を一端終了したら、TextureLoaderは破棄するだろう。キャッシュもすべて捨てるだろう。
もういちど、シナリオをやり直したら、背景はTextureLoaderをキャッシュなしからはじめることになる。
なんだ、もういちどシナリオやるなら前のTextureLoaderがあればキャッシュされてるしちょうど良かったのになー、と思うだろう。
その期待に応えるのがSmartTextureLoader。SmartTextureLoaderは画像リストを渡すとTextureLoaderを返却してくれる。これは毎回新しいTextureLoaderを返すわけではなく、もし前にも読み込まれた画像リストだったらそのときのTextureLoaderを返す。
結果、無駄な画像ロードを減らし、キャッシュを有効に機能させ、無駄なTextureLoaderインスタンス生成を抑止する。

言葉の意味はよくわかなくても、この効果はかなり大きいのでSmartTextureLoaderはぜひ活用しよう。
TextureLoaderはSmartTextureLoaderからつくっとけばいいのである。

yanesdk.netのキャッシュシステムは以前と比べてかなり強力になっている。
わたしにとっては一番の目玉だった。
Textureはコストが高い。本当であればStringみたいに不変クラスみたいに扱いたいなあと思っていた。
img/a.jpgのTextureは二つ作れないような感じである。
yanesdk.netのキャッシュシステムはとくに意識せずそれができる感じだ。


そんな画像やら音楽やらフォントリソースを読み込んでくれる便利なものを用意した。
さて、いよいよプールに飛び込もうか。
まあ、マウスやらキーインプットクラスは用意しておく。ゲームの場合、大概入力がなければ話がはじまらない。
MouseInput、KeyBoardInput。
十分である。
ただ、去人たちはこのさきMouseInputやKeyBoardInputでは不足してくるのだが、それはそのときに。