2008/09/18(木)にゅーふれーむわーくの悩み3

はてブ数 2008/09/17 18:12 計算機な日記::ソフト作りつーさ

結局描画はSprite使うことにして、今度はライブラリAPIの提供スタイルについて悩んでいる。

たとえば、Direct3Dをラッピングしたクラスを作った。個人的にはDirect3Dもだんだん理解が進んできたし、この程度のものをもはや何のためにラッピングしてるのか全然さっぱりわかんなくなってきてるんだけど。

で、問題はこのクラスの提供スタイルをどうしようかということ。内容としては、内部的にnew DeviceしたDirect3Dのデバイスクラスに対してあーだこーだするものなのだけれど、Direct3Dデバイスは1つしか作れないようにして、もしかして、全部のメソッドをstaticメソッドとして提供した方がいいのではないかという疑問を感じる。

というのは……。当然この後、TextureとかFontもラッピングしたクラスを作るんだけど、たとえば、TextureLoaderを使うには、Direct3DのDeviceのインスタンスを引数に渡さなきゃいけないわけで、それをラッピングしたメソッドがDirect3Dのラッピングクラスのインスタンスをいちいち引数に受けるのはどうかなと思うのが主な理由。Direct3Dのデバイスが1つであることを保証すれば、staticプロパティへのアクセスでDeviceを取得できるようにできるから、TextureのLoadメソッドにインスタンスを渡す必要はなくなる。要するにDeviceを大域変数的に扱うってことだ。他のメソッドも全部staticになる。

これをやったときの問題として、さし当たっては、オブジェクト指向っぽくなくなるという精神衛生上の問題と、このラッパを使ったDirect3DのDeviceを同時に2つ作れなくなるという2つの問題が思い浮かぶ。いろいろなシーンクラスからDeviceへはアクセスしたいし、その都度Direct3Dラッパクラスへの参照を伝搬し続けるのもかっこわるいように感じる。テクスチャを読み込むたび、フォントを生成するたび、Direct3Dのインスタンスをメソッドに渡すのか? ラッピングしないとしたら、MDXの実装としてはそうなってるけど。でも、確かに1つのDeviceインスタンスに対して、staticメソッドでアクセスしてしまうのも気持ち悪いと思う。staticメソッドたるもの再入可能じゃないといけないんじゃないの、的な。Deviceが2つ作れない問題は、そのまま、ウィンドウが2つ作れない問題である。まぁ、こっちはいいのかなぁと思わなくもない。ただ、PictureBoxにDirectXを使いたいとかいうときに、1つしかラッパが使えなくなってしまう。そこまで考えたらキリがないか……?

Direct3D(Device)ラッパがstaticクラスで、TextureとかFontがインスタンスクラスっていうのもちょっと気持ち悪いような気もしないでもない。でも、いろんなシーンクラスのDraw()やいろんなタスククラスのDraw()からデバイスにアクセスしたい。その都度伝搬するのか、staticなアクセッサを提供するのか。オブジェクト指向であることを無視すればわかりやすいのは後者だと思う……。うーん。ぱねりあやQoFでは、全部のデバイスへのアクセスを持った親玉みたいなクラスを作って伝搬させてたんだけど……。その方が自然かなぁやっぱ^^;;;; どうしよう。

他に、ぱねりあのときは、テクスチャやフォントのリソースリークが大問題になった(作ったきりDispose呼ばない・呼べない)。この辺はタスクシステムの設計がまずかったんだけど。せっかく、Garbage collectionのある言語を使っていて、メモリは自動回収してくれるのにこれではさっぱり意味がない。テクスチャやフォントのリーク対策もしようと思う。思いつく方法としては、何度Loadされても同じインスタンスを返すみたいなFlyweightパターンかしら。。

あとアプリ側で用意したTTFのフォント描画もとらぶってる。PrivateFontCollectionっていうクラスがあるんだけど、暗号化されたファイルをメモリ上に読み込んでメモリ上でデコードして AddMemoryFont した場合、このコレクション内ではちゃんと列挙できるんだけど、いざDirect3DのFontオブジェクトを生成しようとするとコンストラクタでInvalidOperationExceptionが出る。えー、なんでよー! って感じ。泣く泣くTemporaryディレクトリにフォントファイルを書き出してAddFontFileで追加してるんだけど、こうやって作ったフォントファイル、アプリ終了時に削除できないんだよね! この辺ももっと調査する必要がありそうではあるのだけど、いっそWin32APIに逃げようかなぁ……。

まぁ、俺のSDKなんか使わないで、yanesdkdotnetとか使えばいいよ!ってことですね。ぐぅ。