2024/8/8(木)

ゲーム制作ライブラリの開発を進めた。割と基本的な部分の設計に光明が見えてきた。

単に「こう動けばいい」というソフトウェアを作るなら恐らくここまで悩むことはないのだが、「こう書きたい」という要求からライブラリを作っているので悩むことになっている。もちろん設計に対する自分の経験不足もあるのだが。

悩んでいる主な原因としては、グローバルな状態の持ち方である。なるべくプログラミング初心者にも取っつきやすいよう、描画コンテキストみたいな類を意識しなくても関数1つで図形が描けたり画像が描けたりして欲しいのである。Siv3DやDXライブラリがそうであるように!しかし、それは当然グローバルなコンテキストを裏で持つことを意味する。もうこれ自体は避けられないので仕方ないのだが、なるべくならば美しく状態を持ちたいものだ。

始め、なんかグローバルにただ1つコンテナみたいなのを持って、そいつがグローバルなものを全て保持しており、最初に各種オブジェクトを登録しておいて「この型のオブジェクトくれ」といったらどこでももらえるみたいなのを考えていた。しかしこれは問題があった。このようなコンテナを作り、オブジェクトをぶち込むところまでは良いのだが、このコンテナが所有権を持っている限りは破棄処理が厳しい。動的に適当な型のオブジェクトを入れられても破棄する方法を保持していられないのである。container::register<T>()みたいな関数を作ったとして、register()の中では型Tにアクセスできるが、~container()の中にTという型の情報を持っていく術がない。従ってデストラクタを呼びようがない。一応の対処法として全ての登録クラスを同じ抽象クラスから派生させる手はあるが、多重継承はなんかイヤというか遅くなりそうだし使いこなせないのでやめた。

それで別の作戦として、みんなが見るコンテナに所有権は持たせないことにした。参照だけを持たせる。所有権は別途グローバル変数を用意し、手動で処分することにした。

グローバルなモジュールの管理が決まったところで、次の壁は描画関係の状態の持ち回りだ。「描画対象」と「描画処理(2D描画、3D描画など)」を表すオブジェクトがそれぞれある。「描画対象」はまあ普通にグローバルに保持すればいいとして、「描画処理」の交換可能性をどういう形で確保すればいいかにあんまり見当がついていない。

Siv3Dなどを参考にしてみようとしてみたのだが、なんかむしろ「描画対象」と「描画処理」を一体のものとしてやっていっている?JavaScriptのcanvasとかは'2d''webgl'を選べたりするので、こちらの方が自分の求める設計に近そう。processingとかもそんな感じで「レンダラ」を選べるようだ。

Categories: